/* * Free all storage associated with a dyn-string. */ DYN * dyn_free(DYN * p) { if (p != 0) { if (p->text != 0) dofree(p->text); dofree((char *) p); } return 0; }
/* * Expand the macro whose name is np, at token trp->tp, in the tokenrow. * Return trp->tp at the first token next to be expanded * (ordinarily the beginning of the expansion) */ void expand(Tokenrow *trp, Nlist *np) { Tokenrow ntr; int ntokc, narg, i; Token *tp; int hs; #ifdef __ORCAC__ Tokenrow **atr; atr = domalloc(sizeof(Tokenrow *) * (NARG+1)); #define RETURN free(atr);return #else Tokenrow *atr[NARG+1]; #define RETURN return; #endif copytokenrow(&ntr, np->vp); /* copy macro value */ if (np->ap==NULL) /* parameterless */ ntokc = 1; else { ntokc = gatherargs(trp, atr, &narg); if (narg<0) { /* not actually a call (no '(') */ trp->tp++; RETURN; } if (narg != rowlen(np->ap)) { error(ERROR, "Disagreement in number of macro arguments"); trp->tp->hideset = newhideset(trp->tp->hideset, np); trp->tp += ntokc; RETURN; } substargs(np, &ntr, atr); /* put args into replacement */ for (i=0; i<narg; i++) { dofree(atr[i]->bp); dofree(atr[i]); } } doconcat(&ntr); /* execute ## operators */ hs = newhideset(trp->tp->hideset, np); for (tp=ntr.bp; tp<ntr.lp; tp++) { /* distribute hidesets */ if (tp->type==NAME) { if (tp->hideset==0) tp->hideset = hs; else tp->hideset = unionhideset(tp->hideset, hs); } } ntr.tp = ntr.bp; insertrow(trp, ntokc, &ntr); trp->tp -= rowlen(&ntr); dofree(ntr.bp); RETURN; }
void unsetsource(void) { Source *s = cursource; if (s->fd != NULL) { fclose(s->fd); dofree(s->inb); } cursource = s->next; dofree(s); }
void unsetsource(void) { Source *s = cursource; if (s->fd>=0) { close(s->fd); dofree(s->inb); } cursource = s->next; dofree(s); }
/* * substitute the argument list into the replacement string * This would be simple except for ## and # */ void substargs(Nlist* np, Tokenrow* rtr, Tokenrow** atr) { Tokenrow tatr; Token* tp; int ntok, argno; for (rtr->tp = rtr->bp; rtr->tp < rtr->lp;) { if (rtr->tp->type == SHARP) { /* string operator */ tp = rtr->tp; rtr->tp += 1; if ((argno = lookuparg(np, rtr->tp)) < 0) { error(ERROR, "# not followed by macro parameter"); continue; } ntok = 1 + (rtr->tp - tp); rtr->tp = tp; insertrow(rtr, ntok, stringify(atr[argno])); continue; } if (rtr->tp->type == NAME && (argno = lookuparg(np, rtr->tp)) >= 0) { if ((rtr->tp + 1)->type == DSHARP || (rtr->tp != rtr->bp && (rtr->tp - 1)->type == DSHARP)) insertrow(rtr, 1, atr[argno]); else { copytokenrow(&tatr, atr[argno]); expandrow(&tatr, "<macro>"); insertrow(rtr, 1, &tatr); dofree(tatr.bp); } continue; } rtr->tp++; } }
void output_file_directive(const struct place *p, bool is_new) { output("# ", 2); char linenum[10]; snprintf(linenum, sizeof(linenum), "%u", p->line); output(linenum, strlen(linenum)); output(" \"", 2); char *fname = place_filename(p); output(fname, strlen(fname)); dofree(fname, strlen(fname) + 1); output("\" ", 2); if (is_new) output("1", 1); else output("2", 1); const char * suffix = "\n"; output(suffix, strlen(suffix)); }
static void placefile_destroy(struct placefile *pf) { dostrfree(pf->name); dofree(pf, sizeof(*pf)); }
void mvl_check( MacroValidatorList * inout_pValidators, Token * inout_pTokenToCheck) { MacroValidator * pV; /* Running pointer */ MacroValidator * pCheckedOnes; /* Here new list is built. */ pCheckedOnes = NULL; for ( pV = inout_pValidators->pFirst; pV != NULL; pV = inout_pValidators->pFirst ) { inout_pValidators->pFirst = pV->pNext; if (pV->nTokenWhereMacroBecomesValid == inout_pTokenToCheck->identifier) { pV->pMacro->flag &= (~ISACTIVE); dofree(pV); } else { pV->pNext = pCheckedOnes; pCheckedOnes = pV; } } /* end for */ /* Assign new built list (too old ones were removed) to original list: */ inout_pValidators->pFirst = pCheckedOnes; }
/* * Expand the macro whose name is np, at token trp->tp, in the tokenrow. * Return trp->tp at the first token next to be expanded * (ordinarily the beginning of the expansion) */ void expand(Tokenrow *trp, Nlist *np) { Tokenrow ntr; int ntokc, narg, i; Token *tp; Tokenrow *atr[NARG+1]; int hs; copytokenrow(&ntr, np->vp); /* copy macro value */ if (np->ap==NULL) /* parameterless */ ntokc = 1; else { ntokc = gatherargs(trp, atr, &narg); if (narg<0) { /* not actually a call (no '(') */ /* gatherargs has already pushed trp->tr to the next token */ return; } if (narg != rowlen(np->ap)) { error(ERROR, "Disagreement in number of macro arguments"); trp->tp->hideset = newhideset(trp->tp->hideset, np); trp->tp += ntokc; return; } substargs(np, &ntr, atr); /* put args into replacement */ for (i=0; i<narg; i++) { dofree(atr[i]->bp); dofree(atr[i]); } } doconcat(&ntr); /* execute ## operators */ hs = newhideset(trp->tp->hideset, np); for (tp=ntr.bp; tp<ntr.lp; tp++) { /* distribute hidesets */ if (tp->type==NAME) { if (tp->hideset==0) tp->hideset = hs; else tp->hideset = unionhideset(tp->hideset, hs); } } ntr.tp = ntr.bp; insertrow(trp, ntokc, &ntr); trp->tp -= rowlen(&ntr); dofree(ntr.bp); return; }
void mvl_destruct(MacroValidatorList * out_pValidators) { MacroValidator * pV = out_pValidators->pFirst; MacroValidator * pDel; for ( pDel = out_pValidators->pFirst; pDel != NULL; pDel = pV ) { pV = pV->pNext; pDel->pMacro->flag &= (~ISACTIVE); dofree(pDel); } }
static void commandline_macros_cleanup(void) { unsigned i, num; struct commandline_macro *cm; num = array_num(&commandline_macros); for (i=0; i<num; i++) { cm = array_get(&commandline_macros, i); dofree(cm, sizeof(*cm)); } array_setsize(&commandline_macros, 0); array_cleanup(&commandline_macros); }
static void commandline_files_cleanup(void) { unsigned i, num; struct commandline_file *cf; num = array_num(&commandline_files); for (i=0; i<num; i++) { cf = array_get(&commandline_files, i); if (cf != NULL) { dofree(cf, sizeof(*cf)); } } array_setsize(&commandline_files, 0); array_cleanup(&commandline_files); }
static void apply_commandline_macros(void) { struct commandline_macro *cm; unsigned i, num; num = array_num(&commandline_macros); for (i=0; i<num; i++) { cm = array_get(&commandline_macros, i); if (cm->expansion != NULL) { macro_define_plain(&cm->where, cm->macro, &cm->where2, cm->expansion); } else { macro_undef(cm->macro); } dofree(cm, sizeof(*cm)); } array_setsize(&commandline_macros, 0); }
/* * Evaluate the ## operators in a tokenrow */ void doconcat(Tokenrow *trp) { Token *ltp, *ntp; STATIC Tokenrow ntr; int len; CHECKIN(); for (trp->tp=trp->bp; trp->tp<trp->lp; trp->tp++) { if (trp->tp->type==DSHARP1) trp->tp->type = DSHARP; else if (trp->tp->type==DSHARP) { STATIC char tt[128]; ltp = trp->tp-1; ntp = trp->tp+1; if (ltp<trp->bp || ntp>=trp->lp) { error(ERROR, "## occurs at border of replacement"); continue; } len = ltp->len + ntp->len; strncpy((char*)tt, (char*)ltp->t, ltp->len); strncpy((char*)tt+ltp->len, (char*)ntp->t, ntp->len); tt[len] = '\0'; setsource("<##>", -1, tt); maketokenrow(3, &ntr); gettokens(&ntr, 1); unsetsource(); if (ntr.lp-ntr.bp!=2 || ntr.bp->type==UNCLASS) error(WARNING, "Bad token %r produced by ##", &ntr); ntr.lp = ntr.bp+1; trp->tp = ltp; makespace(&ntr); insertrow(trp, (ntp-ltp)+1, &ntr); dofree(ntr.bp); trp->tp--; } } CHECKOUT(); }
static void read_commandline_files(void) { struct commandline_file *cf; unsigned i, num; bool save = false; num = array_num(&commandline_files); for (i=0; i<num; i++) { cf = array_get(&commandline_files, i); array_set(&commandline_files, i, NULL); if (cf->suppress_output) { save = mode.do_output; mode.do_output = false; file_readquote(&cf->where, cf->name); mode.do_output = save; } else { file_readquote(&cf->where, cf->name); } dofree(cf, sizeof(*cf)); } array_setsize(&commandline_files, 0); }
void vecfree(char **s) { dofree((char *) s); }
/* top_output() - Screen output function. Parameters: outmode - Output mode (OUT_ constant). string - String to output. ... - Language item parameter(s) (see notes). Returns: Pointer to global outputstr variable. Notes: This is a variable-parameter function. After string (the main output string, up to 9 additional strings may be specified. These will be inserted into the output wherever language parameter tokens (@1, @2, etc.) appear. They may not be used at all depending on the contents of string. Integers or other number CANNOT BE SPECIFIED! To include an int as a parameter, convert it with itoa() or a similar function. The global array of outnum strings can be used to hold these conversions without having to allocate extra space. Only two parameters are required. Although this function always returns a pointer to outputstr, outputstr will only be updated with the new output if OUT_STRING or OUT_STRINGNF modes were specified. This function uses the outproc... global flags to control code output. */ unsigned char *top_output(char outmode, unsigned char *string, ...) { va_list oap; /* System pointer to variable arguments. */ unsigned char *argptrs[9] = /* Variable argument holders. */ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; /* Counter, number of variable arguments, argument number holder. */ char odd, nargs, argnum; /* Counter, counter, word wrap counter, memory/length counter, temporary attribute holder. */ XINT d, e, owwc, uu, tatr; unsigned long lentmp; /* Temporary length holder. */ unsigned char oww[55]; /* Output word wrap buffer. */ unsigned char *lenbuf = NULL; /* Parameter length restriction buffer. */ XINT tmulti; /* Not used. */ struct text_info ti; /* Screen attribute information. */ /* OUT_STRINGNF mode flag, OUT_EMULATE mode flag. */ char stringnf = 0, emu = 0; /* This is a complicated and extemely lengthy function that should not be messed with unless you have a thorough understanding of all of TOP's codes, the door kit output functions, and string and memory handling. */ /* OUT_STRINGNF functions identically to OUT_STRING in most places so a flag is set and OUT_STRING mode is forced. */ if (outmode == OUT_STRINGNF) { stringnf = 1; outmode = OUT_STRING; } /* OUT_EMULATE functions identically to OUT_SCREEN in most places so a flag is set and OUT_SCREEN mode is forced. */ if (outmode == OUT_EMULATE) { emu = 1; outmode = OUT_SCREEN; } /* Initialize the argument holders. */ for (d = 0; d < 9; d++) { argptrs[d] = NULL; } /* This loop ascertains the highest number argument the output string requires. */ for (d = 0, nargs = 0; d < strlen(string); d++) { /* Look for @# codes that are higher than the current highest known code to exist. */ if (string[d] == '@' && isdigit(string[d + 1]) && (string[d + 1] - '0' > nargs)) { /* Set the new high arg number. */ nargs = string[d + 1] - '0'; } } /* Grab all of the arguments. */ va_start(oap, string); for (odd = 0; odd < nargs; odd++) { argptrs[odd] = va_arg(oap, unsigned char *); } va_end(oap); /* Clear the word wrap buffer if a screen mode or local mode is being used. */ if (outmode == OUT_SCREEN || outmode == OUT_LOCAL) { memset(oww, 0, 55); } /* Clear the output string if a string mode is being used. */ if (outmode == OUT_STRING) { memset(outputstr, 0, 513); } /* Loop through and process the entire string. */ for (d = 0, owwc = 0; d < strlen(string); d++) { /* PubColour codes. Only process if the global flag is on. */ if (string[d] == '^' && outproccol) { /* Copy the ^ character in non-filtered mode. */ if (outmode == OUT_STRING && stringnf) { strncat(outputstr, &string[d], 1); } /* We're now working with the character after the ^. */ d++; /* Foreground colour change (lower case). */ if (string[d] >= 'a' && string[d] <= 'p') { /* Change the screen colour in screen mode, preserving the current background. */ if (outmode == OUT_SCREEN) { od_set_attrib((od_control.od_cur_attrib & 0xF0) + (string[d] - 'a')); } /* Force the attribute colour in local mode, preserving the current background. */ if (outmode == OUT_LOCAL) { gettextinfo(&ti); textattr((ti.attribute & 0xF0) + (string[d] - 'a')); } /* Copy the code in non-filtered mode. */ if (outmode == OUT_STRING && stringnf) { strncat(outputstr, &string[d], 1); } continue; } /* Background colour change (upper case). */ if (string[d] >= 'A' && string[d] <= 'P') { /* Change the screen colour in screen mode, preserving the current foreground. */ if (outmode == OUT_SCREEN) { od_set_attrib((od_control.od_cur_attrib & 0x0F) + ((string[d] - 'A') << 4)); } /* Force the attribute colour in local mode, preserving the current foreground. */ if (outmode == OUT_LOCAL) { gettextinfo(&ti); textattr((ti.attribute & 0x0F) + ((string[d] - 'A') << 4)); } /* Copy the code in non-filtered mode. */ if (outmode == OUT_STRING && stringnf) { strncat(outputstr, &string[d], 1); } continue; } if (string[d] != '^') { /* Any character but another ^ forces the default attribute. The default attribute is not configurable at this time. */ if (outmode == OUT_SCREEN) { od_set_attrib(outdefattrib); } continue; } /* A second ^ passes through to be displayed to the screen. */ } /* Language codes. Only process if the global flag is on. */ if (string[d] == '@' && outproclang) { /* We're now working with the character after the @. */ d++; /* Language parameter. */ if (string[d] >= '1' && string[d] <= '9') { /* Grab the requested parameter number. */ argnum = string[d] - '1'; /* By definition argnum will be less than nargs because we tested all @# codes above, but it's checked in case. */ if (argnum < nargs) { /* Process all following & codes which control code processing during parameter display. */ while(string[d + 1] == '&' && d < strlen(string)) { /* Jump to the character after the &. */ d += 2; /* String modes copy the & code directly. */ if (outmode == OUT_STRING) { char ttss[5]; sprintf(ttss, "%c%c", string[d - 1], string[d]); strcat(outputstr, ttss); } else { /* Action code disable (not currently used in this function). */ if (toupper(string[d]) == 'A') outprocact = FALSE; /* Language code disable. */ if (toupper(string[d]) == 'L') outproclang = FALSE; /* PubColour code disable. */ if (toupper(string[d]) == 'C') outproccol = FALSE; } } /* Find out if the language item calls for a fixed or limited length. */ lentmp = outchecksuffix(&string[d + 1]); if (lentmp > 0L) { /* Length wanted. */ unsigned XINT lenwant = lentmp & 0x000000FFL; XINT xmem = 0; /* Extra memory counter. */ /* Loop through the parameter string and count all of the colour codes, adding 2 extra memory bytes for each. */ for (uu = 0; uu < strlen(argptrs[argnum]); uu++) { if (argptrs[argnum][uu] == '^') { /* Skip to the character after the ^. */ uu++; xmem += 2; } } /* Increase the size of the wanted length. */ lenwant += xmem; /* Grab the requested length of memory. */ lenbuf = malloc(lenwant + 1); if (lenbuf) { /* Clear the temporary buffer. It's filled with zeros if that was requested, otherwise spaces are used. */ if (lentmp & 0x00020000L) { memset(lenbuf, '0', lenwant); } else { memset(lenbuf, ' ', lenwant); } lenbuf[lenwant] = '\0'; if (lentmp & 0x00010000L) { /* Left justification. */ if (strlen(argptrs[argnum]) > lenwant) { /* Truncate the parameter string if it is too long. */ memcpy(lenbuf, argptrs[argnum], lenwant); } else { /* Copy the string in its entirety. memcpy() is used because we don't want a \0 after the string is copied. */ memcpy(lenbuf, argptrs[argnum], strlen(argptrs[argnum])); } } else { /* Right justification. */ if (strlen(argptrs[argnum]) > 7 lenwant) { /* Truncate the parameter string if it is too long. No compensation for right justification is needed since the parameter will fill the entire buffer. */ memcpy(lenbuf, argptrs[argnum], lenwant); } else { /* Copy the entire string right justified. */ memcpy(&lenbuf[lenwant - strlen(argptrs[argnum])], argptrs[argnum], strlen(argptrs[argnum])); } } /* Screen and local modes make a recursive call to top_output() to output the parameter. */ if (outmode == OUT_SCREEN) { top_output(OUT_SCREEN, lenbuf); } if (outmode == OUT_LOCAL) { top_output(OUT_LOCAL, lenbuf); } /* String modes copy the parameter directly. */ if (outmode == OUT_STRING) { strcat(outputstr, lenbuf); } dofree(lenbuf); } /* Increment the counter the length of the actual parameter code. */ d += ((lentmp & 0xFF00) >> 8); /* Reactivate all code processing flags. */ outproccol = outproclang = outprocact = TRUE; continue; } else { /* User doesn't care about length. */ /* Screen and local modes make a recursive call to top_output() to output the parameter. */ if (outmode == OUT_SCREEN) { top_output(OUT_SCREEN, argptrs[argnum]); } if (outmode == OUT_LOCAL) { top_output(OUT_LOCAL, argptrs[argnum]); } /* String modes copy the parameter directly. */ if (outmode == OUT_STRING) { strcat(outputstr, argptrs[argnum]); } /* Reactivate all code processing flags. */ outproccol = outproclang = outprocact = TRUE; continue; } }
/* * do a macro definition. tp points to the name being defined in the line */ void dodefine(Tokenrow *trp) { Token *tp; Nlist *np; Tokenrow *def, *args; tp = trp->tp+1; if (tp>=trp->lp || tp->type!=NAME) { error(ERROR, "#defined token is not a name"); return; } np = lookup(tp, 1); if (np->flag&ISUNCHANGE) { error(ERROR, "#defined token %t can't be redefined", tp); return; } /* collect arguments */ tp += 1; args = NULL; if (tp<trp->lp && tp->type==LP && tp->wslen==0) { /* macro with args */ int narg = 0; tp += 1; args = new(Tokenrow); maketokenrow(2, args); if (tp->type!=RP) { int err = 0; for (;;) { Token *atp; if (tp->type!=NAME) { err++; break; } if (narg>=args->max) growtokenrow(args); for (atp=args->bp; atp<args->lp; atp++) if (atp->len==tp->len && strncmp((char*)atp->t, (char*)tp->t, tp->len)==0) error(ERROR, "Duplicate macro argument"); *args->lp++ = *tp; narg++; tp += 1; if (tp->type==RP) break; if (tp->type!=COMMA) { err++; break; } tp += 1; } if (err) { error(ERROR, "Syntax error in macro parameters"); return; } } tp += 1; } trp->tp = tp; if (((trp->lp)-1)->type==NL) trp->lp -= 1; def = normtokenrow(trp); if (np->flag&ISDEFINED) { if (comparetokens(def, np->vp) || (np->ap==NULL) != (args==NULL) || np->ap && comparetokens(args, np->ap)) error(ERROR, "Macro redefinition of %t", trp->bp+2); } if (args) { Tokenrow *tap; tap = normtokenrow(args); dofree(args->bp); args = tap; } np->ap = args; np->vp = def; np->flag |= ISDEFINED; }
/* * Expand the macro whose name is np, at token trp->tp, in the tokenrow. * Return trp->tp at the first token next to be expanded * (ordinarily the beginning of the expansion) * I.e.: the same position as before! * Only one expansion is performed, then we return to the expandrow() * loop and start at same position. */ void expand(Tokenrow * trp, Nlist * np, MacroValidatorList * pValidators) { Tokenrow ntr; int ntokc, narg; Tokenrow *atr[NARG + 1]; if (Mflag == 2) { if (np->ap) error(INFO, "Macro expansion of %t with %s(%r)", trp->tp, np->name, np->ap); else error(INFO, "Macro expansion of %t with %s", trp->tp, np->name); } copytokenrow(&ntr, np->vp); /* copy macro value */ if (np->ap == NULL) /* parameterless */ ntokc = 1; else { int i; ntokc = gatherargs(trp, atr, &narg); if (narg < 0) { /* not actually a call (no '(') */ trp->tp++; return; } if (narg != rowlen(np->ap)) { error(ERROR, "Disagreement in number of macro arguments"); trp->tp += ntokc; return; } /** If gatherargs passed a macro validating token, this token must become valid here. trp->tp+0 was checked in expandrow(), so we don't need to do it again here: */ for (i = 1; i < ntokc; i++) { mvl_check(pValidators,trp->tp+i); } substargs(np, &ntr, atr); /* put args into replacement */ for (i = 0; i < narg; i++) { dofree(atr[i]->bp); dofree(atr[i]); } } doconcat(&ntr); /* execute ## operators */ ntr.tp = ntr.bp; makespace(&ntr, trp->tp); tokenrow_zeroTokenIdentifiers(&ntr); insertrow(trp, ntokc, &ntr); /* add validator for just invalidated macro: */ np->flag |= ISACTIVE; if (trp->tp != trp->lp) { /* tp is a valid pointer: */ mvl_add(pValidators,np,trp->tp); } else { /* tp is == lp, therefore does not point to valid memory: */ mvl_add(pValidators,np,0); } /* reset trp->tp to original position: */ trp->tp -= ntr.lp - ntr.bp; /* so the result will be tested for macros from the same position again */ dofree(ntr.bp); return; }
/* * do a macro definition. tp points to the name being defined in the line */ void dodefine(Tokenrow * trp) { Token *tp; Nlist *np; Source *s; Tokenrow *def, *args; static uchar location[(PATH_MAX + 8) * NINC], *cp; tp = trp->tp + 1; if (tp >= trp->lp || tp->type != NAME) { error(ERROR, "#defined token is not a name"); return; } np = lookup(tp, 1); if (np->flag & ISUNCHANGE) { error(ERROR, "#defined token %t can't be redefined", tp); return; } /* collect arguments */ tp += 1; args = NULL; if (tp < trp->lp && tp->type == LP && tp->wslen == 0) { tp += 1; args = new(Tokenrow); maketokenrow(2, args); if (tp->type != RP) { /* macro with args */ size_t narg = 0; int err = 0; for (;;) { Token *atp; if (tp->type != NAME) { err++; break; } if (narg >= args->max) growtokenrow(args); for (atp = args->bp; atp < args->lp; atp++) if (atp->len == tp->len && strncmp((char *) atp->t, (char *) tp->t, tp->len) == 0) error(ERROR, "Duplicate macro argument"); *args->lp++ = *tp; narg++; tp += 1; if (tp->type == RP) break; if (tp->type != COMMA) { err++; break; } tp += 1; } if (err) { error(ERROR, "Syntax error in macro parameters"); return; } } tp += 1; } trp->tp = tp; if (((trp->lp) - 1)->type == NL) trp->lp -= 1; def = normtokenrow(trp); if (np->flag & ISDEFINED) { if (comparetokens(def, np->vp) || (np->ap == NULL) != (args == NULL) || (np->ap && comparetokens(args, np->ap))) { if ( np->loc ) error(ERROR, "Macro redefinition of %t (already defined at %s)", trp->bp + 2, np->loc); else error(ERROR, "Macro redefinition of %t (already defined at %s)", trp->bp + 2, "commandline" ); } } if (args) { Tokenrow *tap; tap = normtokenrow(args); dofree(args->bp); dofree(args); args = tap; } np->ap = args; np->vp = def; np->flag |= ISDEFINED; /* build location string of macro definition */ for (cp = location, s = cursource; s; s = s->next) if (*s->filename) { if (cp != location) *cp++ = ' '; sprintf((char *)cp, "%s:%d", s->filename, s->line); cp += strlen((char *)cp); } np->loc = newstring(location, strlen((char *)location), 0); if (Mflag) { if (np->ap) error(INFO, "Macro definition of %s(%r) [%r]", np->name, np->ap, np->vp); else error(INFO, "Macro definition of %s [%r]", np->name, np->vp); } }
/* * Evaluate the ## operators in a tokenrow */ void doconcat(Tokenrow * trp) { Token *ltp, *ntp; Tokenrow ntr; size_t len; for (trp->tp = trp->bp; trp->tp < trp->lp; trp->tp++) { if (trp->tp->type == DSHARP1) trp->tp->type = DSHARP; else if (trp->tp->type == DSHARP) { int i; char tt[NCONCAT]; ltp = trp->tp - 1; ntp = trp->tp + 1; if (ltp < trp->bp || ntp >= trp->lp) { error(ERROR, "## occurs at border of replacement"); continue; } ntp = ltp; i = 1; len = 0; do { if (len + ntp->len + ntp->wslen > sizeof(tt)) { error(ERROR, "## string concatination buffer overrun"); break; } if (ntp != trp->tp + 1) { strncpy((char *) tt + len, (char *) ntp->t - ntp->wslen, ntp->len + ntp->wslen); len += ntp->len + ntp->wslen; } else // Leerzeichen um ## herum entfernen: { strncpy((char *) tt + len, (char *) ntp->t, ntp->len); len += ntp->len; } ntp = trp->tp + i; i++; } while (ntp < trp->lp); tt[len] = '\0'; setsource("<##>", -1, -1, tt, 0); maketokenrow(3, &ntr); gettokens(&ntr, 1); unsetsource(); if (ntr.bp->type == UNCLASS) error(WARNING, "Bad token %r produced by ##", &ntr); while ((ntr.lp-1)->len == 0 && ntr.lp != ntr.bp) ntr.lp--; doconcat(&ntr); trp->tp = ltp; makespace(&ntr, ltp); insertrow(trp, (int)(ntp - ltp), &ntr); dofree(ntr.bp); trp->tp--; } } }
void setup(int argc, char **argv) { int c, fd, i, n; char *fp, *dp; Tokenrow tr; setup_kwtab(); #if defined(MACOSX) || defined(AIX) || defined(_WIN32) while ((c = stgetopt(argc, argv, "NOPV:I:D:U:F:A:X:u:l:+")) != -1) #else while ((c = getopt(argc, argv, "NOPV:I:D:U:F:A:X:u:l:+")) != -1) #endif switch (c) { case 'N': for (i = 0; i < NINCLUDE; i++) if (includelist[i].always == 1) includelist[i].deleted = 1; break; case 'I': for (i = NINCLUDE - 2; i >= 0; i--) { if (includelist[i].file == NULL) { includelist[i].always = 1; includelist[i].file = optarg; break; } } if (i < 0) error(FATAL, "Too many -I directives"); break; case 'D': case 'U': case 'A': setsource("<cmdarg>", -1, -1, optarg, 0); maketokenrow(3, &tr); gettokens(&tr, 1); doadefine(&tr, c); dofree(tr.bp); unsetsource(); break; case 'P': /* Lineinfo */ Pflag++; break; case 'V': for (n = 0; (c = optarg[n]) != '\0'; n++) switch (c) { case 'i': Iflag++; break; case 'm': Mflag = 1; break; case 'x': Mflag = 2; break; case 't': Vflag++; break; case 'v': fprintf(stderr, "%s\n", argv[0]); break; default: error(WARNING, "Unknown verbose option %c", c); } break; case 'X': for (n = 0; (c = optarg[n]) != '\0'; n++) switch (c) { case 'a': Aflag++; break; case 'i': Xflag++; break; case 'c': Cflag++; break; case 'd': Dflag++; break; case 'w': dp = &optarg[n + 1]; n += (int)strlen(dp); while (isspace(*dp)) dp++; for (i = NINCLUDE - 1; i >= 0; i--) { if (wraplist[i].file == NULL) { wraplist[i].file = dp; break; } } if (i < 0) error(WARNING, "Too many -Xw directives"); break; default: error(WARNING, "Unknown extension option %c", c); } break; case '+': Cplusplus++; break; case 'u': /* -undef fuer GCC (dummy) */ case 'l': /* -lang-c++ fuer GCC (dummy) */ break; default: break; } dp = "."; fp = "<stdin>"; fd = 0; if (optind < argc) { if ((fp = strrchr(argv[optind], '/')) != NULL) { int len = (int)(fp - argv[optind]); dp = (char *) newstring((uchar *) argv[optind], len + 1, 0); dp[len] = '\0'; } fp = (char *) newstring((uchar *) argv[optind], strlen(argv[optind]), 0); if ((fd = open(fp, O_RDONLY)) <= 0) error(FATAL, "Can't open input file %s", fp); } if (optind + 1 < argc) { int fdo = creat(argv[optind + 1], 0666); if (fdo < 0) error(FATAL, "Can't open output file %s", argv[optind + 1]); dup2(fdo, 1); } includelist[NINCLUDE - 1].always = 0; includelist[NINCLUDE - 1].file = dp; setsource(fp, -1, fd, NULL, 0); }
void dostrfree(char *s) { dofree(s, strlen(s)+1); }