Print this page
new smatch
*** 160,169 ****
--- 160,245 ----
ret->string = string;
return ret;
}
+ static struct expression *get_expression_from_base_and_str(struct expression *base, const char *addition)
+ {
+ struct expression *ret = NULL;
+ struct token *token, *prev, *end;
+ char *alloc;
+
+ if (addition[0] == '\0')
+ return base;
+
+ alloc = alloc_string_newline(addition);
+
+ token = tokenize_buffer(alloc, strlen(alloc), &end);
+ if (!token)
+ goto free;
+ if (token_type(token) != TOKEN_STREAMBEGIN)
+ goto free;
+ token = token->next;
+
+ ret = base;
+ while (token_type(token) == TOKEN_SPECIAL &&
+ (token->special == SPECIAL_DEREFERENCE || token->special == '.')) {
+ prev = token;
+ token = token->next;
+ if (token_type(token) != TOKEN_IDENT)
+ goto free;
+ switch (prev->special) {
+ case SPECIAL_DEREFERENCE:
+ ret = deref_expression(ret);
+ ret = member_expression(ret, '*', token->ident);
+ break;
+ case '.':
+ ret = member_expression(ret, '.', token->ident);
+ break;
+ default:
+ goto free;
+ }
+ token = token->next;
+ }
+
+ if (token_type(token) != TOKEN_STREAMEND)
+ goto free;
+
+ free:
+ free_string(alloc);
+
+ return ret;
+ }
+
+ struct expression *gen_expression_from_name_sym(const char *name, struct symbol *sym)
+ {
+ struct expression *base;
+ int skip = 0;
+ struct expression *ret;
+
+ if (!name || !sym)
+ return NULL;
+
+ base = symbol_expression(sym);
+ while (name[skip] != '\0' && name[skip] != '.' && name[skip] != '-')
+ skip++;
+
+ ret = get_expression_from_base_and_str(base, name + skip);
+ if (ret) {
+ char *new = expr_to_str(ret);
+
+ /*
+ * FIXME: this sometimes changes "foo->bar.a.b->c" into
+ * "foo->bar.a.b.c". I don't know why... :(
+ *
+ */
+ if (!new || strcmp(name, new) != 0)
+ return NULL;
+ }
+ return ret;
+ }
+
struct expression *gen_expression_from_key(struct expression *arg, const char *key)
{
struct expression *ret;
struct token *token, *prev, *end;
const char *p = key;