summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2011-10-10 20:41:40 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2011-10-10 20:41:40 (GMT)
commit27e0842899c6d2a674d95d888e10d0b036e27753 (patch) (side-by-side diff)
tree6f9519b8b40747aca8c505b8a7af0c3fcae6a0f5
parent250d9aab8f79ebd7a2f2535de9db60172df51598 (diff)
downloadcflow-27e0842899c6d2a674d95d888e10d0b036e27753.tar.gz
cflow-27e0842899c6d2a674d95d888e10d0b036e27753.tar.bz2
Improve parser. Allow users to declare aliases to other symbols.
The latter feature is useful for declaring reserved symbols such as __restrict or __inline, e.g. --symbol __restrict:=restrict instructs cflow to treat `__restrict' exactly as `restrict'. * src/Makefile.am: Minor fix in rule for flowgraph. * src/c.l (init_tokens): New function, separated from init_lex. Install qualifiers. * src/cflow.h (symbol_alias): New flag. (symbol)<alias>: New member. (INSTALL_DEFAULT,INSTALL_OVERWRITE) (INSTALL_CHECK_LOCAL,INSTALL_UNIT_LOCAL): New defines. * src/cflow.rc: Rewrite for use with --cpp='gcc -E' * src/main.c (symbol_override): Extend syntax to allow for defining aliases to other tokens (--symbol __inline:=inline). * src/parser.c (print_token): print qualifiers and ops. (file_error): Change signature. All uses changed. (save_token): Improve output spacing. (skip_balanced): Treat LBRACE0 and RBRACE0 as { and }. (is_function): allow for qualifiers and wrappers before defintion. (parse_function_declaration): Remove PARM_WRAPPER case: it is taken care of by the caller. (fake_struct): leave when '(' is encountered. (parse_variable_declaration): Allow for qualifiers before the identifier. (skip_struct): Use skip_balanced. (dcl): Handle wrappers. Leave if a semicolon is encountered. (dirdcl): Optimize handing of wrapper. (maybe_parm_list): Handle qualifiers. (declare): allow for wrappers. (declare_type): Pass INSTALL_UNIT_LOCAL as a flag to install. * src/symbol.c (lookup): Argument is const now. (install): Change semantics of the 2nd argument. (install_ident): Change the call to install accordingly. * tests/nfparg.at: Change spacing to reflect changes to save_token.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--src/Makefile.am9
-rw-r--r--src/c.l95
-rw-r--r--src/cflow.h16
-rw-r--r--src/cflow.rc20
-rw-r--r--src/main.c45
-rw-r--r--src/parser.c175
-rw-r--r--src/symbol.c30
-rw-r--r--tests/nfparg.at2
8 files changed, 235 insertions, 157 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 05acd30..f4736d7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -44,11 +44,12 @@ AM_CPPFLAGS=-DLOCALEDIR=\"$(localedir)\"
AM_LFLAGS=-dvp
EXTRA_DIST=cflow.rc
+CFLOW=$(abs_builddir)/cflow
CFLOW_FLAGS=-i^s --brief
cflow_CFLOW_INPUT=$(cflow_OBJECTS:.@OBJEXT@=.c)
cflow.cflow: $(cflow_CFLOW_INPUT) cflow.rc Makefile
- CFLOWRC=$(top_srcdir)/src/cflow.rc \
- cflow -o$@ $(CFLOW_FLAGS) $(DEFS) \
- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
- $(CPPFLAGS) \
+ $(AM_V_GEN)CFLOWRC=$(top_srcdir)/src/cflow.rc \
+ $(CFLOW) -o$@ --cpp="$(CC) -E" $(CFLOW_FLAGS) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) \
$(cflow_CFLOW_INPUT)
diff --git a/src/c.l b/src/c.l
index be14004..f3467e8 100644
--- a/src/c.l
+++ b/src/c.l
@@ -75,7 +75,6 @@ auto /* ignored */;
extern return EXTERN;
static return STATIC;
typedef return TYPEDEF;
-inline {yylval.str = "inline"; return QUALIFIER; }
struct {yylval.str = "struct"; return STRUCT;}
union {yylval.str = "union"; return STRUCT;}
enum {yylval.str = "enum"; return STRUCT;}
@@ -85,30 +84,39 @@ enum {yylval.str = "enum"; return STRUCT;}
/* Operators
*
*/
-"->" |
-"." return MEMBER_OF;
-"*=" |
-"/=" |
-"%=" |
-"+=" |
-"-=" |
-"<<=" |
-">>=" |
-"&=" |
-"|=" |
-"^=" |
-"||" |
-"&&" |
-"==" |
-"!=" |
-">=" |
-">" |
-"<=" |
-"<" |
-"<<" |
-">>" |
-"++" |
-"--" return OP;
+"->" {yylval.str = "->"; return MEMBER_OF;}
+"." {yylval.str = "."; return MEMBER_OF;}
+"*=" {yylval.str = "*="; return OP;}
+"/=" {yylval.str = "/="; return OP;}
+"/" {yylval.str = "/"; return OP;}
+"%=" {yylval.str = "%="; return OP;}
+"%" {yylval.str = "%"; return OP;}
+"+=" {yylval.str = "+="; return OP;}
+"+" {yylval.str = "+"; return OP;}
+"-=" {yylval.str = "-="; return OP;}
+"-" {yylval.str = "-"; return OP;}
+"<<=" {yylval.str = "<<="; return OP;}
+">>=" {yylval.str = ">>="; return OP;}
+"&=" {yylval.str = "&="; return OP;}
+"|=" {yylval.str = "|="; return OP;}
+"^=" {yylval.str = "^="; return OP;}
+"^" {yylval.str = "^"; return OP;}
+"||" {yylval.str = "||"; return OP;}
+"|" {yylval.str = "|"; return OP;}
+"&&" {yylval.str = "&&"; return OP;}
+"&" {yylval.str = "&"; return OP;}
+"==" {yylval.str = "=="; return OP;}
+"=" {yylval.str = "="; return '=';}
+"!=" {yylval.str = "!="; return OP;}
+"!" {yylval.str = "!"; return OP;}
+">=" {yylval.str = ">="; return OP;}
+">" {yylval.str = ">"; return OP;}
+"<=" {yylval.str = "<="; return OP;}
+"<" {yylval.str = "<"; return OP;}
+"<<" {yylval.str = "<<"; return OP;}
+">>" {yylval.str = ">>"; return OP;}
+"++" {yylval.str = "++"; return OP;}
+"--" {yylval.str = "--"; return OP;}
'.' |
'\\.' |
'\\[0-7]{2,3}' |
@@ -181,50 +189,67 @@ static char *keywords[] = {
static char *types[] = {
"char",
- "const",
"double",
"float",
"int",
+ "void",
+};
+
+static char *qualifiers[] = {
"long",
+ "const",
"register",
"restrict",
"short",
"signed",
"unsigned",
- "void",
"volatile",
+ "inline"
};
void
-init_lex(int debug_level)
+init_tokens()
{
int i;
Symbol *sp;
- yy_flex_debug = debug_level;
-
- obstack_init(&string_stk);
-
for (i = 0; i < NUMITEMS(keywords); i++) {
- sp = install(keywords[i], 0);
+ sp = install(keywords[i], INSTALL_OVERWRITE);
sp->type = SymToken;
sp->token_type = WORD;
}
for (i = 0; i < NUMITEMS(types); i++) {
- sp = install(types[i], 0);
+ sp = install(types[i], INSTALL_OVERWRITE);
sp->type = SymToken;
sp->token_type = TYPE;
sp->source = NULL;
sp->def_line = -1;
sp->ref_line = NULL;
}
- sp = install("...", 0);
+
+ for (i = 0; i < NUMITEMS(qualifiers); i++) {
+ sp = install(qualifiers[i], INSTALL_OVERWRITE);
+ sp->type = SymToken;
+ sp->token_type = QUALIFIER;
+ sp->source = NULL;
+ sp->def_line = -1;
+ sp->ref_line = NULL;
+ }
+ sp = install("...", INSTALL_OVERWRITE);
sp->type = SymToken;
sp->token_type = IDENTIFIER;
sp->source = NULL;
sp->def_line = -1;
sp->ref_line = NULL;
+}
+
+void
+init_lex(int debug_level)
+{
+ yy_flex_debug = debug_level;
+ obstack_init(&string_stk);
+ init_tokens();
}
int
diff --git a/src/cflow.h b/src/cflow.h
index 1749ada..07cc8cf 100644
--- a/src/cflow.h
+++ b/src/cflow.h
@@ -83,7 +83,8 @@ enum symbol_flag {
symbol_none,
symbol_temp, /* Temporary symbol. Must be deleted after
processing of the current module */
- symbol_parm /* Parameter */
+ symbol_parm, /* Parameter */
+ symbol_alias /* Alias to another symbol */
};
typedef struct symbol Symbol;
@@ -96,7 +97,11 @@ struct symbol {
enum symtype type; /* Type of the symbol */
char *name; /* Identifier */
enum symbol_flag flag; /* Specific flag */
-
+ struct symbol *alias; /* Points to the aliased symbol if
+ type==SymToken and flag==symbol_alias.
+ In this case, the rest of the structure
+ is ignored */
+
int active; /* Set to 1 when the symbol's subtree is
being processed, prevent recursion */
int expand_line; /* Output line when this symbol was first
@@ -165,7 +170,12 @@ extern int token_stack_increase;
extern int symbol_count;
extern unsigned input_file_count;
-Symbol *lookup(char*);
+#define INSTALL_DEFAULT 0x00
+#define INSTALL_OVERWRITE 0x01
+#define INSTALL_CHECK_LOCAL 0x02
+#define INSTALL_UNIT_LOCAL 0x04
+
+Symbol *lookup(const char*);
Symbol *install(char*, int);
Symbol *install_ident(char *name, enum storage storage);
void ident_change_storage(Symbol *sp, enum storage storage);
diff --git a/src/cflow.rc b/src/cflow.rc
index 8c875f1..e4be309 100644
--- a/src/cflow.rc
+++ b/src/cflow.rc
@@ -1,6 +1,14 @@
-# Default configuration file for cflow
---symbol __const:type
---symbol __restrict:type
--D__extension__=
--D__attribute__\\(c\\)=
--D__asm__\\(c\\)=
+# Default configuration file for cflow.
+--symbol __inline:=inline
+--symbol __inline__:=inline
+--symbol __attribute__:wrapper
+--symbol __const__:=const
+--symbol __const:=const
+--symbol __restrict:=restrict
+--symbol __extension__:qualifier
+--symbol __asm__:wrapper
+--symbol __nonnull:wrapper
+--symbol __nothrow__:wrapper
+--symbol __pure__:wrapper
+--symbol __wur:wrapper
+
diff --git a/src/main.c b/src/main.c
index dbb8453..de41689 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,5 +1,5 @@
/* This file is part of GNU cflow
- Copyright (C) 1997, 2005, 2007, 2009, 2010 Sergey Poznyakoff
+ Copyright (C) 1997, 2005, 2007, 2009, 2010, 2011 Sergey Poznyakoff
GNU cflow is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -257,7 +257,6 @@ static struct option_type symbol_optype[] = {
static void
symbol_override(const char *str)
{
- int type;
const char *ptr;
char *name;
Symbol *sp;
@@ -267,19 +266,35 @@ symbol_override(const char *str)
error(0, 0, _("%s: no symbol type supplied"), str);
return;
} else {
- type = find_option_type(symbol_optype, ptr+1, 0);
- if (type == 0) {
- error(0, 0, _("unknown symbol type: %s"), ptr+1);
- return;
+ name = strndup(str, ptr - str);
+ if (ptr[1] == '=') {
+ Symbol *alias = lookup(ptr+2);
+ if (!alias) {
+ alias = install(ptr+2, INSTALL_OVERWRITE);
+ alias->type = SymToken;
+ alias->token_type = 0;
+ alias->source = NULL;
+ alias->def_line = -1;
+ alias->ref_line = NULL;
+ }
+ sp = install(name, INSTALL_OVERWRITE);
+ sp->type = SymToken;
+ sp->alias = alias;
+ sp->flag = symbol_alias;
+ } else {
+ int type = find_option_type(symbol_optype, ptr+1, 0);
+ if (type == 0) {
+ error(0, 0, _("unknown symbol type: %s"), ptr+1);
+ return;
+ }
+ sp = install(name, INSTALL_OVERWRITE);
+ sp->type = SymToken;
+ sp->token_type = type;
}
- }
- name = strndup(str, ptr - str);
- sp = install(name, 0);
- sp->type = SymToken;
- sp->token_type = type;
- sp->source = NULL;
- sp->def_line = -1;
- sp->ref_line = NULL;
+ sp->source = NULL;
+ sp->def_line = -1;
+ sp->ref_line = NULL;
+ }
}
/* Args for --print option */
@@ -736,7 +751,7 @@ const char version_etc_copyright[] =
/* Do *not* mark this string for translation. %s is a copyright
symbol suitable for this locale, and %d is the copyright
year. */
- "Copyright %s 2005, 2006, %d Sergey Poznyakoff";
+ "Copyright %s 2005, 2006, 2009, 2010, 2011 %d Sergey Poznyakoff";
int
main(int argc, char **argv)
diff --git a/src/parser.c b/src/parser.c
index 8ba1747..2e4148a 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -85,6 +85,8 @@ print_token(TOKSTK *tokptr)
case MODIFIER:
case STRUCT:
case PARM_WRAPPER:
+ case QUALIFIER:
+ case OP:
fprintf(stderr, "`%s'", tokptr->token);
break;
case LBRACE0:
@@ -104,9 +106,6 @@ print_token(TOKSTK *tokptr)
case TYPEDEF:
fprintf(stderr, "`typedef'");
break;
- case OP:
- fprintf(stderr, "OP"); /* ouch!!! */
- break;
case STRING:
fprintf(stderr, "\"%s\"", tokptr->token);
break;
@@ -116,12 +115,12 @@ print_token(TOKSTK *tokptr)
}
static void
-file_error(char *msg, int near)
+file_error(char *msg, TOKSTK *tokptr)
{
fprintf(stderr, "%s:%d: %s", filename, tok.line, msg);
- if (near) {
+ if (tokptr) {
fprintf(stderr, _(" near "));
- print_token(&tok);
+ print_token(tokptr);
}
fprintf(stderr, "\n");
}
@@ -249,18 +248,26 @@ save_token(TOKSTK *tokptr)
need_space = 0;
break;
case ')':
+ obstack_1grow(&text_stk, tokptr->type);
+ need_space = 1;
+ break;
case '[':
case ']':
obstack_1grow(&text_stk, tokptr->type);
need_space = 0;
break;
+ case OP:
+ obstack_1grow(&text_stk, ' ');
+ obstack_grow(&text_stk, tokptr->token, strlen(tokptr->token));
+ need_space = 1;
+ break;
default:
if (verbose)
- file_error(_("unrecognized definition"), 1);
+ file_error(_("unrecognized definition"), tokptr);
}
}
-static Stackpos start_pos; /* Start position in stack for saving tokens */
+static Stackpos start_pos; /* Start position in stack for saving tokens *///FIXME: REMOVE
static int save_end; /* Stack position up to which the tokens are saved */
void
@@ -328,12 +335,18 @@ skip_balanced(int open_tok, int close_tok, int level)
if (nexttoken() != open_tok) {
return 1;
}
+ level++;
}
while (nexttoken()) {
+ if (tok.type == LBRACE0 && open_tok == '{')
+ tok.type = '{';
+ else if (tok.type == RBRACE0 && close_tok == '}')
+ tok.type = '}';
+
if (tok.type == open_tok)
level++;
else if (tok.type == close_tok) {
- if (level-- == 0) {
+ if (--level == 0) {
nexttoken();
return 0;
}
@@ -384,17 +397,29 @@ is_function()
int res = 0;
mark(sp);
-/* if (tok.type == STRUCT)
- nexttoken();*/
- while (tok.type == TYPE ||
- tok.type == IDENTIFIER ||
- tok.type == MODIFIER ||
- tok.type == STATIC ||
- tok.type == EXTERN)
- nexttoken();
-
- if (tok.type == '(')
- res = nexttoken() != MODIFIER;
+ while (1) {
+ switch (tok.type) {
+ case QUALIFIER:
+ case TYPE:
+ case IDENTIFIER:
+ case MODIFIER:
+ case STATIC:
+ case EXTERN:
+ nexttoken();
+ continue;
+ case PARM_WRAPPER:
+ if (skip_balanced('(', ')', 0) == -1)
+ file_error(_("unexpected end of file in declaration"),
+ NULL);
+ continue;
+ case '(':
+ res = nexttoken() != MODIFIER;
+ break;
+ default:
+ break;
+ }
+ break;
+ }
restore(sp);
return res;
@@ -435,7 +460,8 @@ expression()
break;
case 0:
if (verbose)
- file_error(_("unexpected end of file in expression"), 0);
+ file_error(_("unexpected end of file in expression"),
+ NULL);
return;
case IDENTIFIER:
@@ -490,17 +516,11 @@ parse_function_declaration(Ident *ident, int parm)
nexttoken();
else {
if (verbose)
- file_error(_("expected `;'"), 1);
+ file_error(_("expected `;'"), &tok);
error_recovery = 1;
}
goto restart;
-
- case PARM_WRAPPER:
- if (skip_balanced('(', ')', 0) == -1)
- file_error(_("unexpected end of file in wrapper"), 0);
- goto restart;
-
case ';':
case ',':
break;
@@ -513,7 +533,7 @@ parse_function_declaration(Ident *ident, int parm)
break;
case 0:
if (verbose)
- file_error(_("unexpected end of file in declaration"), 0);
+ file_error(_("unexpected end of file in declaration"), NULL);
}
}
@@ -543,10 +563,10 @@ fake_struct(Ident *ident)
tos = curs + 1;
}
tokpush(hold.type, hold.line, hold.token);
- } else {
- if (tok.type != ';')
- file_error(_("missing `;' after struct declaration"), 0);
- }
+ } else if (tok.type == '(')
+ return 0;
+ else if (tok.type != ';')
+ file_error(_("missing `;' after struct declaration"), &tok);
return 1;
}
return 0;
@@ -565,7 +585,7 @@ parse_variable_declaration(Ident *ident, int parm)
}
putback();
skip_struct();
- while (tok.type == MODIFIER)
+ while (tok.type == MODIFIER || tok.type == QUALIFIER)
nexttoken();
if (tok.type == IDENTIFIER) {
TOKSTK hold = tok;
@@ -597,7 +617,7 @@ parse_variable_declaration(Ident *ident, int parm)
/*FALLTHROUGH*/
default:
if (verbose)
- file_error(_("expected `;'"), 1);
+ file_error(_("expected `;'"), &tok);
/* FIXME: should putback() here */
/* FALLTHRU */
case ';':
@@ -622,7 +642,7 @@ parse_variable_declaration(Ident *ident, int parm)
break;
case 0:
if (verbose)
- file_error(_("unexpected end of file in declaration"), 0);
+ file_error(_("unexpected end of file in declaration"), NULL);
}
}
@@ -644,7 +664,8 @@ initializer_list()
}
break;
case 0:
- file_error(_("unexpected end of file in initializer list"), 0);
+ file_error(_("unexpected end of file in initializer list"),
+ NULL);
return;
case ',':
break;
@@ -666,34 +687,21 @@ parse_knr_dcl(Ident *ident)
void
skip_struct()
{
- int lev = 0;
-
if (nexttoken() == IDENTIFIER) {
nexttoken();
} else if (tok.type == ';')
return;
if (tok.type == LBRACE || tok.type == LBRACE0) {
- do {
- switch (tok.type) {
- case 0:
- file_error(_("unexpected end of file in struct"), 0);
- return;
- case LBRACE:
- case LBRACE0:
- lev++;
- break;
- case RBRACE:
- case RBRACE0:
- lev--;
- }
- nexttoken();
- } while (lev);
+ if (skip_balanced('{', '}', 1) == -1) {
+ file_error(_("unexpected end of file in struct"), NULL);
+ return;
+ }
}
while (tok.type == PARM_WRAPPER) {
if (skip_balanced('(', ')', 0) == -1)
- file_error(_("unexpected end of file in struct"), 0);
+ file_error(_("unexpected end of file in struct"), NULL);
}
}
@@ -734,13 +742,19 @@ parse_dcl(Ident *ident, int maybe_knr)
int
dcl(Ident *idptr)
{
- int type;
-
while (nexttoken() != 0 && tok.type != '(') {
if (tok.type == MODIFIER) {
if (idptr && idptr->type_end == -1)
idptr->type_end = curs-1;
+ } else if (tok.type == PARM_WRAPPER) {
+ if (skip_balanced('(', ')', 0) == -1) {
+ file_error(_("unexpected end of file in function declaration"),
+ NULL);
+ return 1;
+ }
} else if (tok.type == IDENTIFIER) {
+ int type;
+
while (tok.type == IDENTIFIER)
nexttoken();
type = tok.type;
@@ -749,7 +763,7 @@ dcl(Ident *idptr)
continue;
else if (type != MODIFIER)
break;
- } else if (tok.type == ')') {
+ } else if (tok.type == ')' || tok.type == ';') {
return 1;
}
}
@@ -767,7 +781,7 @@ dirdcl(Ident *idptr)
if (tok.type == '(') {
dcl(idptr);
if (tok.type != ')' && verbose) {
- file_error(_("expected `)'"), 1);
+ file_error(_("expected `)'"), &tok);
return 1;
}
} else if (tok.type == IDENTIFIER) {
@@ -790,7 +804,7 @@ dirdcl(Ident *idptr)
else {
maybe_parm_list(parm_ptr);
if (tok.type != ')' && verbose) {
- file_error(_("expected `)'"), 1);
+ file_error(_("expected `)'"), &tok);
return 1;
}
}
@@ -798,26 +812,12 @@ dirdcl(Ident *idptr)
if (wrapper)
nexttoken(); /* read ')' */
- if (tok.type == PARM_WRAPPER) {
- if (nexttoken() == '(') {
- int level = 0;
- while (nexttoken()) {
- if (tok.type == 0) {
- file_error(_("unexpected end of file in function declaration"),
- 0);
- return 1;
- } else if (tok.type == '(')
- level++;
- else if (tok.type == ')') {
- if (level-- == 0) {
- nexttoken();
- break;
- }
- }
- }
- } else
- putback();
+ while (tok.type == PARM_WRAPPER) {
+ if (skip_balanced('(', ')', 0) == -1)
+ file_error(_("unexpected end of file in function declaration"),
+ NULL);
}
+
return 0;
}
@@ -863,7 +863,9 @@ maybe_parm_list(int *parm_cnt_return)
return;
case ',':
break;
+ case QUALIFIER:
case IDENTIFIER:
+ case MODIFIER: /* unsigned * */
case STRUCT:
case UNION:
case TYPE:
@@ -874,7 +876,8 @@ maybe_parm_list(int *parm_cnt_return)
break;
default:
if (verbose)
- file_error(_("unexpected token in parameter list"), 1);
+ file_error(_("unexpected token in parameter list"),
+ &tok);
level = 0;
do {
if (tok.type == '(')
@@ -889,7 +892,7 @@ maybe_parm_list(int *parm_cnt_return)
}
}
if (verbose)
- file_error(_("unexpected end of file in parameter list"), 0);
+ file_error(_("unexpected end of file in parameter list"), NULL);
}
void
@@ -927,7 +930,7 @@ func_body()
case RBRACE0:
if (use_indentation) {
if (verbose && level != 1)
- file_error(_("forced function body close"), 0);
+ file_error(_("forced function body close"), NULL);
for ( ; level; level--) {
delete_autos(level);
}
@@ -941,7 +944,8 @@ func_body()
break;
case 0:
if (verbose)
- file_error(_("unexpected end of file in function body"), 0);
+ file_error(_("unexpected end of file in function body"),
+ NULL);
caller = NULL;
return;
}
@@ -1021,7 +1025,8 @@ declare(Ident *ident, int maybe_knr)
if ((ident->parmcnt >= 0
&& (!maybe_knr || get_knr_args(ident) == 0)
- && !(tok.type == LBRACE || tok.type == LBRACE0 || tok.type == TYPE))
+ && !(tok.type == LBRACE || tok.type == LBRACE0 || tok.type == TYPE
+ || tok.type == PARM_WRAPPER))
|| (ident->parmcnt < 0 && ident->storage == ExplicitExternStorage)) {
undo_save_stack();
/* add_external()?? */
@@ -1075,7 +1080,7 @@ declare_type(Ident *ident)
if (sp->type == SymToken && sp->token_type == TYPE)
break;
if (!sp)
- sp = install(ident->name, 1);
+ sp = install(ident->name, INSTALL_UNIT_LOCAL);
sp->type = SymToken;
sp->token_type = TYPE;
sp->source = filename;
diff --git a/src/symbol.c b/src/symbol.c
index e26e9c5..567e458 100644
--- a/src/symbol.c
+++ b/src/symbol.c
@@ -63,23 +63,29 @@ hash_symbol_compare(void const *data1, void const *data2)
}
Symbol *
-lookup(char *name)
+lookup(const char *name)
{
- Symbol s;
+ Symbol s, *sym;
struct table_entry t, *tp;
if (!symbol_table)
return NULL;
- s.name = name;
+ s.name = (char*) name;
t.sym = &s;
tp = hash_lookup(symbol_table, &t);
- return tp ? tp->sym : NULL;
+ if (tp) {
+ sym = tp->sym;
+ while (sym->type == SymToken && sym->flag == symbol_alias)
+ sym = sym->alias;
+ } else
+ sym = NULL;
+ return sym;
}
/* Install a new symbol `NAME'. If UNIT_LOCAL is set, this symbol can
be local to the current compilation unit. */
Symbol *
-install(char *name, int unit_local)
+install(char *name, int flags)
{
Symbol *sym;
struct table_entry *tp, *ret;
@@ -92,8 +98,9 @@ install(char *name, int unit_local)
tp = xmalloc(sizeof(*tp));
tp->sym = sym;
- if (unit_local &&
- canonical_filename && strcmp(filename, canonical_filename)) {
+ if (((flags & INSTALL_CHECK_LOCAL) &&
+ canonical_filename && strcmp(filename, canonical_filename)) ||
+ (flags & INSTALL_UNIT_LOCAL)) {
sym->flag = symbol_temp;
append_symbol(&static_symbol_list, sym);
} else
@@ -107,6 +114,11 @@ install(char *name, int unit_local)
xalloc_die ();
if (ret != tp) {
+ if (flags & INSTALL_OVERWRITE) {
+ free(sym);
+ free(tp);
+ return ret->sym;
+ }
if (ret->sym->type != SymUndefined)
sym->next = ret->sym;
ret->sym = sym;
@@ -142,7 +154,9 @@ install_ident(char *name, enum storage storage)
{
Symbol *sp;
- sp = install(name, storage != AutoStorage);
+ sp = install(name,
+ storage != AutoStorage ?
+ INSTALL_CHECK_LOCAL : INSTALL_DEFAULT);
sp->type = SymIdentifier;
sp->arity = -1;
sp->storage = ExternStorage;
diff --git a/tests/nfparg.at b/tests/nfparg.at
index ead82f8..ff94124 100644
--- a/tests/nfparg.at
+++ b/tests/nfparg.at
@@ -26,6 +26,6 @@ int main(int (*) ())
{
}
],
-[main() <int main (int (*)()) at prog:2>])
+[main() <int main (int (*) ()) at prog:2>])
AT_CLEANUP

Return to:

Send suggestions and report system problems to the System administrator.