diff --git a/compiler/libpc300/sc.h b/compiler/libpc300/sc.h index 359d6fc5..f0881bde 100755 --- a/compiler/libpc300/sc.h +++ b/compiler/libpc300/sc.h @@ -127,7 +127,7 @@ typedef struct s_symbol { cell codeaddr; /* address (in the code segment) where the symbol declaration starts */ char vclass; /* sLOCAL if "addr" refers to a local symbol */ char ident; /* see below for possible values */ - char usage; /* see below for possible values */ + short usage; /* see below for possible values */ char flags; /* see below for possible values */ int compound; /* compound level (braces nesting level) */ int tag; /* tagname id */ @@ -217,6 +217,7 @@ typedef struct s_symbol { #define uSTOCK 0x40 #define uENUMFIELD 0x40 #define uMISSING 0x80 +#define uVISITED 0x100 /* temporary flag, to mark fields as "visited" in recursive loops */ /* uRETNONE is not stored in the "usage" field of a symbol. It is * used during parsing a function, to detect a mix of "return;" and * "return value;" in a few special cases. diff --git a/compiler/libpc300/sc1.c b/compiler/libpc300/sc1.c index daea73a5..9fe5f005 100755 --- a/compiler/libpc300/sc1.c +++ b/compiler/libpc300/sc1.c @@ -3244,7 +3244,7 @@ static void funcstub(int native) /* attach the array to the function symbol */ if (numdim>0) { assert(sym!=NULL); - sub=addvariable(symbolname,0,iARRAY,sGLOBAL,tag,dim,numdim,idxtag); + sub=addvariable(symbolname,0,iREFARRAY,sGLOBAL,tag,dim,numdim,idxtag); sub->parent=sym; } /* if */ diff --git a/compiler/libpc300/sc2.c b/compiler/libpc300/sc2.c index 9b8e83ed..90bc1c27 100755 --- a/compiler/libpc300/sc2.c +++ b/compiler/libpc300/sc2.c @@ -2599,17 +2599,22 @@ SC_FUNC int get_actual_compound(symbol *sym) SC_FUNC void delete_symbols(symbol *root,int level,int delete_labels,int delete_functions) { - symbol *origRoot=root; - symbol *sym,*parent_sym; + symbol *base; + symbol *sym,*parent_sym,*child_sym; constvalue *stateptr; int mustdelete=0; /* erase only the symbols with a deeper nesting level than the * specified nesting level */ - while (root->next!=NULL) { - sym=root->next; + base=root; + while (base->next!=NULL) { + sym=base->next; if (get_actual_compound(sym)usage & uVISITED) != 0) { + base=sym; /* skip the symbol */ + continue; + } switch (sym->ident) { case iLABEL: mustdelete=delete_labels; @@ -2653,10 +2658,22 @@ SC_FUNC void delete_symbols(symbol *root,int level,int delete_labels,int delete_ break; } /* switch */ if (mustdelete) { - if (origRoot == &glbtab) - RemoveFromHashTable(sp_Globals, sym); - root->next=sym->next; - free_symbol(sym); + /* first delete children, if any */ + int count=0; + while ((child_sym=finddepend(sym))!=NULL) { + delete_symbol(root,child_sym); + count++; + } /* while */ + if (count==0) { + if (root == &glbtab) + RemoveFromHashTable(sp_Globals, sym); + base->next=sym->next; + free_symbol(sym); + } else { + /* chain has changed */ + delete_symbol(root,sym); + base=root; /* restart */ + } /* if */ } else { /* if the function was prototyped, but not implemented in this source, * mark it as such, so that its use can be flagged @@ -2674,9 +2691,16 @@ SC_FUNC void delete_symbols(symbol *root,int level,int delete_labels,int delete_ */ if (sym->ident==iFUNCTN && !alpha(*sym->name)) sym->usage &= ~uPROTOTYPED; - root=sym; /* skip the symbol */ + /* mark the symbol as "visited", so we won't process it twice */ + sym->usage |= uVISITED; + base=sym; /* skip the symbol */ } /* if */ } /* if */ + + + /* go through the symbols again to erase any "visited" marks */ + for (sym = root->next; sym != NULL; sym = sym->next) + sym->usage &= ~uVISITED; } static symbol *find_symbol(const symbol *root,const char *name,int fnumber,int includechildren) @@ -2869,10 +2893,12 @@ SC_FUNC symbol *addvariable(const char *name,cell addr,int ident,int vclass,int /* global variables may only be defined once * One complication is that functions returning arrays declare an array * with the same name as the function, so the assertion must allow for - * this special case. + * this special case. Another complication is that variables may be + * "redeclared" if they are local to an automaton (and findglb() will find + * the symbol without states if no symbol with states exists). */ assert(vclass!=sGLOBAL || (sym=findglb(name))==NULL || (sym->usage & uDEFINE)==0 - || (sym->ident==iFUNCTN && sym==curfunc)); + || (sym->ident==iFUNCTN && (sym==curfunc || (sym->usage & uNATIVE) != 0))); if (ident==iARRAY || ident==iREFARRAY) { symbol *parent=NULL,*top;