From 27e0842899c6d2a674d95d888e10d0b036e27753 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Mon, 10 Oct 2011 23:41:40 +0300 Subject: 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): 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. --- src/Makefile.am | 9 +-- src/c.l | 95 ++++++++++++++++++------------ src/cflow.h | 16 +++++- src/cflow.rc | 20 +++++-- src/main.c | 45 ++++++++++----- src/parser.c | 175 +++++++++++++++++++++++++++++--------------------------- src/symbol.c | 30 +++++++--- 7 files changed, 234 insertions(+), 156 deletions(-) (limited to 'src') 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; -- cgit v1.2.1