145
146 struct expression *string_expression(char *str)
147 {
148 struct expression *ret;
149 struct string *string;
150 int len;
151
152 len = strlen(str) + 1;
153 string = (void *)__alloc_sname(4 + len);
154 string->length = len;
155 string->immutable = 0;
156 memcpy(string->data, str, len);
157
158 ret = alloc_tmp_expression(get_cur_pos(), EXPR_STRING);
159 ret->wide = 0;
160 ret->string = string;
161
162 return ret;
163 }
164
165 struct expression *gen_expression_from_key(struct expression *arg, const char *key)
166 {
167 struct expression *ret;
168 struct token *token, *prev, *end;
169 const char *p = key;
170 char buf[4095];
171 char *alloc;
172 size_t len;
173
174 /* The idea is that we can parse either $0->foo or $->foo */
175 if (key[0] != '$')
176 return NULL;
177 p++;
178 while (*p >= '0' && *p <= '9')
179 p++;
180 len = snprintf(buf, sizeof(buf), "%s\n", p);
181 alloc = alloc_string(buf);
182
183 token = tokenize_buffer(alloc, len, &end);
184 if (!token)
|
145
146 struct expression *string_expression(char *str)
147 {
148 struct expression *ret;
149 struct string *string;
150 int len;
151
152 len = strlen(str) + 1;
153 string = (void *)__alloc_sname(4 + len);
154 string->length = len;
155 string->immutable = 0;
156 memcpy(string->data, str, len);
157
158 ret = alloc_tmp_expression(get_cur_pos(), EXPR_STRING);
159 ret->wide = 0;
160 ret->string = string;
161
162 return ret;
163 }
164
165 static struct expression *get_expression_from_base_and_str(struct expression *base, const char *addition)
166 {
167 struct expression *ret = NULL;
168 struct token *token, *prev, *end;
169 char *alloc;
170
171 if (addition[0] == '\0')
172 return base;
173
174 alloc = alloc_string_newline(addition);
175
176 token = tokenize_buffer(alloc, strlen(alloc), &end);
177 if (!token)
178 goto free;
179 if (token_type(token) != TOKEN_STREAMBEGIN)
180 goto free;
181 token = token->next;
182
183 ret = base;
184 while (token_type(token) == TOKEN_SPECIAL &&
185 (token->special == SPECIAL_DEREFERENCE || token->special == '.')) {
186 prev = token;
187 token = token->next;
188 if (token_type(token) != TOKEN_IDENT)
189 goto free;
190 switch (prev->special) {
191 case SPECIAL_DEREFERENCE:
192 ret = deref_expression(ret);
193 ret = member_expression(ret, '*', token->ident);
194 break;
195 case '.':
196 ret = member_expression(ret, '.', token->ident);
197 break;
198 default:
199 goto free;
200 }
201 token = token->next;
202 }
203
204 if (token_type(token) != TOKEN_STREAMEND)
205 goto free;
206
207 free:
208 free_string(alloc);
209
210 return ret;
211 }
212
213 struct expression *gen_expression_from_name_sym(const char *name, struct symbol *sym)
214 {
215 struct expression *base;
216 int skip = 0;
217 struct expression *ret;
218
219 if (!name || !sym)
220 return NULL;
221
222 base = symbol_expression(sym);
223 while (name[skip] != '\0' && name[skip] != '.' && name[skip] != '-')
224 skip++;
225
226 ret = get_expression_from_base_and_str(base, name + skip);
227 if (ret) {
228 char *new = expr_to_str(ret);
229
230 /*
231 * FIXME: this sometimes changes "foo->bar.a.b->c" into
232 * "foo->bar.a.b.c". I don't know why... :(
233 *
234 */
235 if (!new || strcmp(name, new) != 0)
236 return NULL;
237 }
238 return ret;
239 }
240
241 struct expression *gen_expression_from_key(struct expression *arg, const char *key)
242 {
243 struct expression *ret;
244 struct token *token, *prev, *end;
245 const char *p = key;
246 char buf[4095];
247 char *alloc;
248 size_t len;
249
250 /* The idea is that we can parse either $0->foo or $->foo */
251 if (key[0] != '$')
252 return NULL;
253 p++;
254 while (*p >= '0' && *p <= '9')
255 p++;
256 len = snprintf(buf, sizeof(buf), "%s\n", p);
257 alloc = alloc_string(buf);
258
259 token = tokenize_buffer(alloc, len, &end);
260 if (!token)
|