/* stgout * * Writes the staging buffer to the output file via stgstring() (for * reversing expressions in the buffer) and stgopt() (for optimizing). It * resets "stgidx". * * Global references: stgidx (altered) * stgbuf (referred to only) * staging (referred to only) */ SC_FUNC void stgout(int index) { int reordered=0; int idx; if (!staging) return; assert(pipeidx==0); /* first pass: sub-expressions */ if (sc_status==statWRITE) reordered=stgstring(&stgbuf[index],&stgbuf[stgidx]); stgidx=index; /* second pass: optimize the buffer created in the first pass */ if (sc_status==statWRITE) { if (reordered) { stgopt(stgpipe,stgpipe+pipeidx,filewrite); } else { /* there is no sense in re-optimizing if the order of the sub-expressions * did not change; so output directly */ for (idx=0; idx<pipeidx; idx+=strlen(stgpipe+idx)+1) filewrite(stgpipe+idx); } /* if */ } /* if */ pipeidx=0; /* reset second pipe */ }
/* stgstring * * Analyses whether code strings should be output to the file as they appear * in the staging buffer or whether portions of it should be re-ordered. * Re-ordering takes place in function argument lists; Pawn passes arguments * to functions from right to left. When arguments are "named" rather than * positional, the order in the source stream is indeterminate. * This function calls itself recursively in case it needs to re-order code * strings, and it uses a private stack (or list) to mark the start and the * end of expressions in their correct (reversed) order. * In any case, stgstring() sends a block as large as possible to the * optimizer stgopt(). * * In "reorder" mode, each set of code strings must start with the token * sEXPRSTART, even the first. If the token sSTARTREORDER is represented * by '[', sENDREORDER by ']' and sEXPRSTART by '|' the following applies: * '[]...' valid, but useless; no output * '[|...] valid, but useless; only one string * '[|...|...] valid and usefull * '[...|...] invalid, first string doesn't start with '|' * '[|...|] invalid */ static void stgstring(char *start,char *end) { char *ptr; int nest,argc,arg; argstack *stack; while (start<end) { if (*start==sSTARTREORDER) { start+=1; /* skip token */ /* allocate a argstack with sMAXARGS items */ stack=(argstack *)malloc(sMAXARGS*sizeof(argstack)); if (stack==NULL) error(103); /* insufficient memory */ nest=1; /* nesting counter */ argc=0; /* argument counter */ arg=-1; /* argument index; no valid argument yet */ do { switch (*start) { case sSTARTREORDER: nest++; start++; break; case sENDREORDER: nest--; start++; break; default: if ((*start & sEXPRSTART)==sEXPRSTART) { if (nest==1) { if (arg>=0) stack[arg].end=start-1; /* finish previous argument */ arg=(unsigned char)*start - sEXPRSTART; stack[arg].start=start+1; if (arg>=argc) argc=arg+1; } /* if */ start++; } else { start+=strlen(start)+1; } /* if */ } /* switch */ } while (nest); /* enddo */ if (arg>=0) stack[arg].end=start-1; /* finish previous argument */ while (argc>0) { argc--; stgstring(stack[argc].start,stack[argc].end); } /* while */ free(stack); } else { ptr=start; while (ptr<end && *ptr!=sSTARTREORDER) ptr+=strlen(ptr)+1; stgopt(start,ptr); start=ptr; } /* if */ } /* while */ }