diff --git a/compiler/libpc300/sc1.c b/compiler/libpc300/sc1.c index ff17d875..82ad38c3 100755 --- a/compiler/libpc300/sc1.c +++ b/compiler/libpc300/sc1.c @@ -105,7 +105,7 @@ static void doarg(char *name,int ident,int offset,int tags[],int numtags, int fpublic,int fconst,arginfo *arg); static void make_report(symbol *root,FILE *log,char *sourcefile); static void reduce_referrers(symbol *root); -static long max_stacksize(symbol *root); +static long max_stacksize(symbol *root, int *recursion); static int testsymbols(symbol *root,int level,int testlabs,int testconst); static void destructsymbols(symbol *root,int level); static constvalue *find_constval_byval(constvalue *table,cell val); @@ -718,7 +718,8 @@ cleanup: #if !defined SC_LIGHT if (errnum==0 && strlen(errfname)==0) { - long stacksize=max_stacksize(&glbtab); + int recursion; + long stacksize=max_stacksize(&glbtab,&recursion); int flag_exceed=0; if (sc_amxlimit > 0 && (long)(hdrsize+code_idx+glb_declared*sizeof(cell)+sc_stksize*sizeof(cell)) >= sc_amxlimit) flag_exceed=1; @@ -4247,29 +4248,47 @@ static void reduce_referrers(symbol *root) } #if !defined SC_LIGHT -static long max_stacksize_recurse(symbol *sourcesym, symbol *sym, long basesize, int *pubfuncparams) +static long max_stacksize_recurse(symbol **sourcesym,symbol *sym,long basesize,int *pubfuncparams,int *recursion) { long size,maxsize; - int i; + int i,stkpos; + assert(sourcesym!=NULL); assert(sym!=NULL); assert(sym->ident==iFUNCTN); assert((sym->usage & uNATIVE)==0); + assert(recursion!=NULL); maxsize=sym->x.stacksize; for (i=0; inumrefers; i++) { if (sym->refer[i]!=NULL) { assert(sym->refer[i]->ident==iFUNCTN); assert((sym->refer[i]->usage & uNATIVE)==0); /* a native function cannot refer to a user-function */ - if (sym->refer[i] == sourcesym) - return -1; /* recursion detection */ - size = max_stacksize_recurse(sourcesym, sym->refer[i], sym->x.stacksize, pubfuncparams); - if (size<0) - return size; /* recursion was detected, quit */ + for (stkpos=0; sourcesym[stkpos]!=NULL; stkpos++) { + if (sym->refer[i]==sourcesym[stkpos]) { /* recursion detection */ + if ((sc_debug & sSYMBOLIC)!=0 || verbosity>=2) { + char symname[2*sNAMEMAX+16];/* allow space for user defined operators */ + funcdisplayname(symname,sym->name); + errorset(sSETFILE,sym->fnumber); + errorset(sSETLINE,sym->lnumber); + error(237,symname); /* recursive function */ + } /* if */ + *recursion=1; + goto break_recursion; /* recursion was detected, quit loop */ + } /* if */ + } /* for */ + /* add this symbol to the stack */ + sourcesym[stkpos]=sym; + sourcesym[stkpos+1]=NULL; + /* check size of callee */ + size=max_stacksize_recurse(sourcesym,sym->refer[i],sym->x.stacksize,pubfuncparams,recursion); if (maxsizeusage & uPUBLIC)!=0) { /* Find out how many parameters a public function has, then see if this @@ -4287,10 +4306,13 @@ static long max_stacksize_recurse(symbol *sourcesym, symbol *sym, long basesize, *pubfuncparams=count; } /* if */ + errorset(sEXPRRELEASE,0); /* clear error data */ + errorset(sRESET,0); + return maxsize+basesize; } -static long max_stacksize(symbol *root) +static long max_stacksize(symbol *root,int *recursion) { /* Loop over all non-native functions. For each function, loop * over all of its referrers, accumulating the stack requirements. @@ -4303,29 +4325,44 @@ static long max_stacksize(symbol *root) * stack requirements are thus only an estimate. */ long size,maxsize; - int maxparams; + int maxparams,numfunctions; symbol *sym; + symbol **symstack; - #if !defined NDEBUG - for (sym=root->next; sym!=NULL; sym=sym->next) - if (sym->ident==iFUNCTN) - assert(sym->compound==0); - #endif + assert(root!=NULL); + assert(recursion!=NULL); + /* count number of functions (for allocating the stack for recursion detection) */ + numfunctions=0; + for (sym=root->next; sym!=NULL; sym=sym->next) { + if (sym->ident==iFUNCTN) { + assert(sym->compound==0); + if ((sym->usage & uNATIVE)==0) + numfunctions++; + } /* if */ + } /* if */ + /* allocate function symbol stack */ + symstack=(symbol **)malloc((numfunctions+1)*sizeof(symbol*)); + if (symstack==NULL) + error(103); /* insufficient memory (fatal error) */ + memset(symstack,0,(numfunctions+1)*sizeof(symbol*)); maxsize=0; maxparams=0; + *recursion=0; /* assume no recursion */ for (sym=root->next; sym!=NULL; sym=sym->next) { /* drop out if this is not a user-implemented function */ if (sym->ident!=iFUNCTN || (sym->usage & uNATIVE)!=0) continue; /* accumulate stack size for this symbol */ - size=max_stacksize_recurse(sym,sym,0L,&maxparams); - if (size<0) - return size; /* recursion was detected */ + symstack[0]=sym; + assert(symstack[1]==NULL); + size=max_stacksize_recurse(symstack,sym,0L,&maxparams,recursion); + assert(size>=0); if (maxsize