aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLinus Torvalds <torvalds@ppc970.osdl.org>2004-10-08 09:40:53 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 21:03:33 -0700
commit744bd80a0bc48ecd4fccb745cb357550a83101fd (patch)
tree0fb53b32e31a64950da4ac7d0fac674de3875792
parent30fbaa8a02f8c726a6faf1be1e346c038f929dfb (diff)
downloadsparse-dev-744bd80a0bc48ecd4fccb745cb357550a83101fd.tar.gz
Handle __func__, __FUNCTION__ and __PRETTY_FUNCTION__ the same
way, and give them a real string. This means that __func__ actually works as a constant string, not as a pseudo-symbol, which is wrong. But hey, sue me.
-rw-r--r--evaluate.c2
-rw-r--r--expression.c59
-rw-r--r--ident-list.h2
-rw-r--r--lib.c5
-rw-r--r--parse.c29
-rw-r--r--symbol.h3
6 files changed, 68 insertions, 32 deletions
diff --git a/evaluate.c b/evaluate.c
index 4de33b90..e00ca8bf 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -25,7 +25,7 @@
#include "target.h"
#include "expression.h"
-static struct symbol *current_fn;
+struct symbol *current_fn;
static int current_context, current_contextmask;
static struct symbol *degenerate(struct expression *expr);
diff --git a/expression.c b/expression.c
index f0ec5721..b450b677 100644
--- a/expression.c
+++ b/expression.c
@@ -59,11 +59,66 @@ struct token *parens_expression(struct token *token, struct expression **expr, c
return expect(token, ')', where);
}
+/*
+ * Handle __func__, __FUNCTION__ and __PRETTY_FUNCTION__ token
+ * conversion
+ */
+static int convert_one_fn_token(struct token *token)
+{
+ struct symbol *sym = current_fn;
+
+ if (sym) {
+ struct ident *ident = sym->ident;
+ if (ident) {
+ int len = ident->len;
+ struct string *string;
+
+ string = __alloc_string(len+1);
+ memcpy(string->data, ident->name, len);
+ string->data[len] = 0;
+ string->length = len+1;
+ token_type(token) = TOKEN_STRING;
+ token->string = string;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int convert_function(struct token *next)
+{
+ int retval = 0;
+ for (;;) {
+ struct token *token = next;
+ next = next->next;
+ switch (token_type(token)) {
+ case TOKEN_STRING:
+ continue;
+ case TOKEN_IDENT:
+ if (token->ident == &__func___ident ||
+ token->ident == &__FUNCTION___ident ||
+ token->ident == &__PRETTY_FUNCTION___ident) {
+ if (!convert_one_fn_token(token))
+ break;
+ retval = 1;
+ continue;
+ }
+ /* Fall through */
+ default:
+ break;
+ }
+ break;
+ }
+ return retval;
+}
+
static struct token *string_expression(struct token *token, struct expression *expr)
{
struct string *string = token->string;
struct token *next = token->next;
+ convert_function(token);
+
if (token_type(next) == TOKEN_STRING) {
int totlen = string->length-1;
char *data;
@@ -248,6 +303,9 @@ struct token *primary_expression(struct token *token, struct expression **tree)
struct symbol *sym = lookup_symbol(token->ident, NS_SYMBOL | NS_TYPEDEF);
struct token *next = token->next;
+ if (!sym && convert_function(token))
+ goto handle_string;
+
expr = alloc_expression(token->pos, EXPR_SYMBOL);
/*
@@ -267,6 +325,7 @@ struct token *primary_expression(struct token *token, struct expression **tree)
}
case TOKEN_STRING: {
+ handle_string:
expr = alloc_expression(token->pos, EXPR_STRING);
token = string_expression(token, expr);
break;
diff --git a/ident-list.h b/ident-list.h
index e7eed0c2..67374581 100644
--- a/ident-list.h
+++ b/ident-list.h
@@ -59,6 +59,8 @@ __IDENT(__VA_ARGS___ident, "__VA_ARGS__", 0);
__IDENT(__LINE___ident, "__LINE__", 0);
__IDENT(__FILE___ident, "__FILE__", 0);
__IDENT(__func___ident, "__func__", 0);
+__IDENT(__FUNCTION___ident, "__FUNCTION__", 0);
+__IDENT(__PRETTY_FUNCTION___ident, "__PRETTY_FUNCTION__", 0);
#undef __IDENT
#undef IDENT
diff --git a/lib.c b/lib.c
index 86b44485..c9d64d25 100644
--- a/lib.c
+++ b/lib.c
@@ -786,9 +786,4 @@ void create_builtin_stream(void)
add_pre_buffer("#define __builtin_va_start(a,b) ((a) = (__builtin_va_list)(&(b)))\n");
add_pre_buffer("#define __builtin_va_arg(arg,type) ((type)0)\n");
add_pre_buffer("#define __builtin_va_end(arg)\n");
- // These live somewhere between parse-land (they need to know the
- // function name) and pre-processor-land (they concatenate with
- // strings). Punt.
- add_pre_buffer("#define __FUNCTION__ \"function\"\n");
- add_pre_buffer("#define __PRETTY_FUNCTION__ \"function\"\n");
}
diff --git a/parse.c b/parse.c
index 58184ccd..03036d8e 100644
--- a/parse.c
+++ b/parse.c
@@ -1043,38 +1043,15 @@ static struct statement *start_function(struct symbol *sym)
stmt->ret = ret;
fn_local_symbol(ret);
- // static const char __func__[] = "function-name";
- if (sym->ident) {
- struct symbol *funcname = alloc_symbol(sym->pos, SYM_NODE);
- struct symbol *array = alloc_symbol(sym->pos, SYM_ARRAY);
- struct expression *expr = alloc_expression(sym->pos, EXPR_STRING);
- int len = sym->ident->len;
- struct string *string = __alloc_string(len+1);
-
- array->ctype.base_type = &char_ctype;
- array->ctype.modifiers = MOD_CONST | MOD_STATIC;
-
- memcpy(string->data, sym->ident->name, len);
- string->data[len] = '\0';
- string->length = len + 1;
-
- expr->string = string;
-
- funcname->initializer = expr;
- funcname->ctype.modifiers = array->ctype.modifiers;
- funcname->ctype.base_type = array;
- funcname->ident = &__func___ident;
- bind_symbol(funcname, &__func___ident, NS_SYMBOL);
-
- add_symbol(&stmt->syms, funcname);
- fn_local_symbol(funcname);
- }
+ // Currently parsed symbol for __func__/__FUNCTION__/__PRETTY_FUNCTION__
+ current_fn = sym;
return stmt;
}
static void end_function(struct symbol *sym)
{
+ current_fn = NULL;
end_function_scope();
}
diff --git a/symbol.h b/symbol.h
index 05f9d207..f8561fb0 100644
--- a/symbol.h
+++ b/symbol.h
@@ -156,6 +156,9 @@ struct symbol {
#define MOD_EXPLICITLY_SIGNED 0x40000000
#define MOD_BITWISE 0x80000000
+/* Current parsing/evaluation function */
+extern struct symbol *current_fn;
+
/* Basic types */
extern struct symbol void_type,
int_type,