diff --git a/xa/src/xap.c b/xa/src/xap.c index 29fd0d3..7ffc3e0 100644 --- a/xa/src/xap.c +++ b/xa/src/xap.c @@ -40,7 +40,7 @@ #include "xap.h" /* define this for recursive evaluation output */ -/* #define DEBUG_RECMAC */ +#undef DEBUG_RECMAC char s[MAXLINE]; Datei *filep; @@ -434,78 +434,85 @@ int tcompare(char s[],char *v[], int n) return((i==n)? -1 : i); } -int pp_replace(char *to, char *ti, int a,int b) +static int check_name(char *t, int n) { + + int i=0; + { + char *x=liste[n].search; + while(t[i]==*x++ && t[i]) + i++; + } + + return i == liste[n].s_len; +} + +/** + * this is a break out of the original pp_replace code, as this code + * was basically duplicated for initial and recursive calls. + */ +static int pp_replace_part(char *to, char *t, int n, int sl, int recursive, int *l, int blist) { - char *t=to,c,*x,*y,*mx,*rs; - int i,l,n,sl,d,ld,er=E_OK,hkfl,klfl; - char fti[MAXLINE],fto[MAXLINE]; -/* - int flag=!strncmp(ti,"TOUT",4); - if(flag) printf("flag=%d\n",flag); -*/ - (void)strcpy(t,ti); + int er = E_OK; - if(rlist) - { - while(t[0]!='\0') - { - while(!isalpha(t[0]) && t[0]!='_') - if(t[0]=='\0') - break; /*return(E_OK);*/ - else - { - t++; - ti++; - } - - for(l=0;isalnum(t[l])||t[l]=='_';l++); - ld=l; -/* - if(flag) printf("l=%d,a=%d,t=%s\n",l,a,t); -*/ - if(a<0) - { - n=hashindex[hashcode(t,l)]; - - do - { - sl=liste[n].s_len; - - if(sl && (sl==l)) - { - i=0; - x=liste[n].search; - while(t[i]==*x++ && t[i]) - i++; + // save mem, to restore it when we don't need the pseudo replacements anymore + // Note: in a real version, that should probably be a parameter, and not fiddling + // with global variables... + char *saved_mem = mem; - if(i==sl) - { - rs=liste[n].replace; - + // yes, mark replacement string + char *rs=liste[n].replace; + + // does it have parameters? if(liste[n].p_anz) { + // yes, we have parameters, so we need to pp_replace them + // as well. + char fti[MAXLINE],fto[MAXLINE]; + + // copy replacement into temp buffer (void)strcpy(fti,liste[n].replace); - if(rlist+liste[n].p_anz>=ANZDEF || memfre=ANZDEF || memfre10) + if (++j>10) { + // we ran into 10 recursions deep - that does not look sound, bail out errout(E_ORECMAC); + } } - (void)strcpy(liste[rlist+i].replace, nfto); +#endif + // copy over the replacement string into free memory (using mx as pointer) + (void)strcpy(mx, nfto); + // replace the pointer to the (now obsolete) old replacement with the one we just created + // Note that due to the nature of the (more or less static) memory allocation, this is not + // being freed. Oh well... + liste[blist+i].replace = mx; + mx += strlen(mx)+1; + #ifdef DEBUG_RECMAC printf("FINAL: -%s=%s\n",liste[rlist+i].search,liste[rlist+i].replace); #endif } - if(!er) - er=pp_replace(fto,fti,rlist,rlist+i); + + if(!er) { + // safe-guard our memory allocations + mem = mx; + // only change (of two) from recursive: rlist is 0 there + er=pp_replace(fto,fti,recursive ? 0 : blist,blist+liste[n].p_anz); + } /* if(flag) printf("sl=%d,",sl);*/ sl=(int)((long)y+1L-(long)t); /* if(flag) printf("sl=%d\n",sl);*/ @@ -575,14 +633,18 @@ int pp_replace(char *to, char *ti, int a,int b) /* printf("->%s\n",fto);*/ } } - if(er) + if(er) { + mem = saved_mem; return(er); + } } - d=(int)strlen(rs)-sl; + int d=(int)strlen(rs)-sl; - if(strlen(to)+d>=MAXLINE) + if(strlen(to)+d>=MAXLINE) { + mem = saved_mem; return(E_NOMEM); + } /* if(d<0) @@ -597,129 +659,125 @@ int pp_replace(char *to, char *ti, int a,int b) t[ll+d]=t[ll]; } */ - if(d) - (void)strcpy(t+sl+d,ti+sl); + if(d) { + // d can be positive or negative, so strcpy cannot be used, use memmove instead + (void)memmove(t+sl+d,t+sl, strlen(t) - sl + 1); + } - i=0; + int i=0; + char c; while((c=rs[i])) t[i++]=c; - l=sl+d;/*=0;*/ - break; - } + // other change from recursive. there sl is missing from add + *l=(recursive ? 0 : sl) + d;/*=0;*/ + + mem = saved_mem; + + return (er); +} + +/** + * copy the input string pointed to by ti into + * an output string buffer pointed to by to, replacing all + * preprocessor definitions in the process. + * + * Note: this method is called recursively, with "a" being -1 + * when called from the "outside" respectively in a new context + * (like macro parameters) + * + * The "b" parameter denotes the index in the list from which on + * pseudo replacement entries are being created for replacement + * parameters + * + */ +int pp_replace(char *to, char *ti, int a,int b) +{ + char *t=to; + int l,n,sl,er=E_OK; + int ld; // length of name/token to analyse +/* + int flag=!strncmp(ti,"TOUT",4); + if(flag) printf("flag=%d\n",flag); +*/ + // t points to to, so copy input to output 1:1 + // then below work on the copy in-place + (void)strcpy(t,ti); + + // if there are replacements in the list of replacements + if(rlist) + { + // loop over the whole input + while(t[0]!='\0') + { + // skip over the whitespace + while(!isalpha(t[0]) && t[0]!='_') { + if(t[0]=='\0') + break; /*return(E_OK);*/ + else + { + t++; + ti++; + } + } + + // determine the length of the name + for(l=0;isalnum(t[l])||t[l]=='_';l++); + // store in ld + ld=l; +/* + if(flag) printf("l=%d,a=%d,t=%s\n",l,a,t); +*/ + // the following if() is executed when being called from an + // 'external' context, i.e. not from a recursion + if(a<0) + { + // when called from an external context, not by recursion + + // compute hashcode for the name for the search index entry (liste[n]) + n=hashindex[hashcode(t,l)]; + + // loop over all entries in linked list for hash code (think: hash collisions) + do // while(1); + { + // length of name of pp definition + sl=liste[n].s_len; + + // does pp definition match what we have found? + if(sl && (sl==l) && check_name(t, n)) + { + er = pp_replace_part(to, t, n, sl, 0, &l, b); + break; } if(!n) break; - + + // next index in linked list for given hash code n=liste[n].nextindex; } while(1); } else { + // called when in recursive call + // loop over all the replacement entries from the given b down to 0 + // that allows to replace the parameters first (as they were added at + // the end of the list) for(n=b-1;n>=a;n--) { sl=liste[n].s_len; - if(sl && (sl==l)) + if(sl && (sl==l) && check_name(t, n)) { - i=0; - x=liste[n].search; - while(t[i]==*x++ && t[i]) - i++; - - if(i==sl) - { - rs=liste[n].replace; - if(liste[n].p_anz) - { - (void)strcpy(fti,liste[n].replace); - if(rlist+liste[n].p_anz>=ANZDEF || memfre=MAXLINE) - return(E_NOMEM); -/* - if(d<0) - { - y=t+sl+d; - x=t+sl; - while(*y++=*x++); - } - if(d>0) - { - for(ll=strlen(t);ll>=sl;ll--) - t[ll+d]=t[ll]; - } -*/ - if(d) - (void)strcpy(t+sl+d,ti+sl); - - i=0; - while((c=rs[i])) - t[i++]=c; - l+=d;/*0;*/ - break; - } + er = pp_replace_part(to, t, n, sl, 1, &l, b); + break; } } } + // advance input by length of name ti+=ld; + // advance output by l t+=l; - } - } + } /* end while(t[0] != 0) */ + } /* end if(rlist) */ return(E_OK); } @@ -916,8 +974,15 @@ int pgetline(char *t) er= (er==1) ? E_OK : er ; - if(!er) + if(!er) { +#ifdef DEBUG_RECMAC + printf("<<<: %s\n", in_line); +#endif er=pp_replace(t,in_line,-1,rlist); +#ifdef DEBUG_RECMAC + printf(">>>: %s\n", t); +#endif + } if(!er && nff) er=E_NEWFILE;