📄 ctrl.c
字号:
while ((tok = gtok()) != 0 && tok != NL) { if (tok == QNL || (!savcom && tok == COMMENT)) { /* ignore the token */ } else { /* * if this token is a formal parameter name, * add its parameter number & an ATTN byte * to the macro value. Otherwise add the * token's value (less ATTN bytes) to the value. */ formp = formtop; if (tok == IDENT) { arg = findmac(curtext, nxtout); for (formp = &form[0]; formp < formtop && formp->fm_sym != arg; ++formp) ; } if (formp < formtop) { if (valend + 2 >= &valbuf[VALLEN]) { bombf("macro value too long"); } *valend++ = (char) ((formp - &form[0]) + 1); *valend++ = ATTN; *valend = '\0'; } else { if (valend + (nxtout - curtext) >= &valbuf[VALLEN]) { bombf("macro value too long"); } while (curtext < nxtout) { if (*curtext == ATTN) { curtext += 2; } else { *valend++ = *curtext++; } } *valend = '\0'; } } } (void) dispose(f); }rollback: /* * restore the formal parameter's original values * (in reverse order to take care of duplicate formal parameters). */ while (--formtop >= &form[0]) { free(formtop->fm_sym->am_name); formtop->fm_sym->am_name = formtop->fm_copy.am_name; formtop->fm_sym->am_npar = formtop->fm_copy.am_npar; formtop->fm_sym->am_val = formtop->fm_copy.am_val; } /* * (finally) define the macro (if there was no problem), * stripping whitespace where appropriate. */ if (defok) { if (!savcom) { stripwhite(&valbuf[0]); } defmac(maccopy.am_name, maccopy.am_name + strlen(maccopy.am_name), maccopy.am_npar, &valbuf[0]); } return(tok);}intdo_undef(f)char *f;{ int tok; /* the current token's type */ struct amacro *mac; /* the macro to be undefined */ char *cp; /* * find the macro to be undefined (it is legal to undef an undefined * macro, a non "-M"ed macro, or a preprocessor keyword); * Read the rest of the "#undef" line; * If this macro is one of the magic preprocessor macros * (e.g. "defined()"), it cannot be undef'ed. * Otherwise, find the beginning of the value and free it, * then zero the value, undefining the macro. * Destroy the original text of the #undef. */ if ((tok = nonwhite(gtok)) != IDENT) { warnf("illegal macro name"); tok = endline(); return(tok); } mac = findmac(curtext, nxtout); if (!mac->am_name) { tok = endline(); return(tok); } if (mac->am_val) { if (mac->am_val == &magicval) { warnf("cannot undef implicit macro"); tok = endline(); return(tok); } cp = mac->am_val; while (*--cp != '\0') ; free(cp); mac->am_val = (char *) 0; } tok = endline(); (void) dispose(f); return(tok);}intdo_ifdef(f)char *f;{ return(ifdorn(f,TRUE));}intdo_ifndef(f)char *f;{ return(ifdorn(f, FALSE));}/* * ifdorn() - "if defined or not defined" -- this is the common code for * ifdef and ifndef processing. */intifdorn(f, defed)char *f; /* points to the beginning of the command in pend[] */int defed; /* "the if is true if the macro is defined" */{ int tok; /* the current token's type */ struct amacro *mac; /* the macro in question */ if (++curif >= &ifstk[IFSIZ]) { bombf("too many nested if's"); } *curif = IF_INIF; tok = nonwhite(gtok); if (tok != IDENT) { warnf("illegal macro name"); tok = endline(); return(tok); } mac = findmac(curtext, nxtout); tok = endline(); if (!mac->am_name) { return(tok); } if ((mac->am_val && defed) || (!mac->am_val && !defed)) { *curif |= IF_TRUE; } else { *curif |= IF_FALSE; ift_f(); } (void) dispose(f); return(tok);}intdo_if(f)char *f;{ int tok; int oldnint; /* interp' count prior to parsing the exp */ int wasraw; /* the state of interpretation prior to parse */ if (++curif >= &ifstk[IFSIZ]) { bombf("too many nested if's"); } *curif = IF_INIF; /* in #if part rather than #else */ wasraw = curfile->af_raw; oldnint = ninterp; expparse = TRUE; if (yyparse() != 0) { /* syntax error - don't interpret this 'if' */ *curif &= ~(IF_TRUE | IF_FALSE); tok = endline(); expparse = FALSE; return(tok); } tok = endline(); expparse = FALSE; if (!(*curif & (IF_TRUE | IF_FALSE)) || (wasraw && oldnint == ninterp)) { /* * either the truth is not known or * no macro interpretation was performed; * Don't interpret the #if. */ *curif &= ~(IF_TRUE | IF_FALSE); return(tok); } if (*curif & IF_FALSE) { ift_f(); } (void) dispose(f); return(tok);}intdo_else(f)char *f;{ int tok; if (curif < &ifstk[0] || !(*curif & IF_INIF)) { warnf("if-less else"); tok = endline(); return(tok); } tok = endline(); *curif &= ~IF_INIF; if (*curif & IF_TRUE) { *curif &= ~IF_TRUE; *curif |= IF_FALSE; ift_f(); (void) dispose(f); return(tok); } if (*curif & IF_FALSE) { *curif &= ~IF_FALSE; *curif |= IF_TRUE; iff_t(); (void) dispose(f); return(tok); } /* this is the 'else' of an uninterpreted if */ return(tok);}/* #elif is just like #if except that it doesn't push anything * on the stack, it just overwrites what must already be there. */intdo_elif(f)char *f;{ int tok; int oldnint; /* interp' count prior to parsing the exp */ int wasraw; /* the state of interpretation prior to parse */ if (curif < &ifstk[0] || !(*curif & IF_INIF)) { warnf("if-less else"); tok = endline(); return(tok); } *curif = IF_INIF; /* in #if part rather than #else */ wasraw = curfile->af_raw; oldnint = ninterp; expparse = TRUE; if (yyparse() != 0) { /* syntax error - don't interpret this 'if' */ *curif &= ~(IF_TRUE | IF_FALSE); tok = endline(); expparse = FALSE; return(tok); } tok = endline(); expparse = FALSE; if (!(*curif & (IF_TRUE | IF_FALSE)) || (wasraw && oldnint == ninterp)) { /* * either the truth is not known or * no macro interpretation was performed; * Don't interpret the #if. */ *curif &= ~(IF_TRUE | IF_FALSE); return(tok); } if (*curif & IF_FALSE) { ift_f(); } (void) dispose(f); return(tok);}intdo_endif(f)char *f;{ int tok; if (curif < &ifstk[0]) { warnf("if-less endif"); tok = endline(); return(tok); } tok = endline(); if (!(*curif & (IF_TRUE | IF_FALSE))) { /* this is the 'endif' of an uninterpreted if */ --curif; return(tok); } if (*curif & IF_FALSE) { iff_t(); } --curif; (void) dispose(f); return(tok);}/* * ift_f(), iff_t() - #if statement transitions which may affect output. * Ift_f() is called whenever an #if statement makes a transition from * from true (or non-existent) to false; * Iff_t() is called whenever one goes from false to true (or non-existent). */ift_f(){ if (falsecnt++ == 0 && hidecnt == 0) { quec(ATTN); quec(AT_OUTOFF); }}iff_t(){ if (--falsecnt == 0 && hidecnt == 0) { quec(ATTN); quec(AT_OUTON); }}/* * stripwhite() - given a pointer to a (possibly dynamically allocated) * string which is to become the value of a macro, strip the leading * and trailing whitespace from the value. */stripwhite(s)char *s;{ char *cp; char *nb; /* * points to the char beyond the last non-blank * character in the string. */ /* * skip the initial whitespace, but don't count as whitespace a * parameter number which preceeds an ATTN byte. */ for (cp = s; *cp == ' ' || *cp == '\t'; ++cp) ; if (*cp == ATTN) { if (cp == s) { bombf("INTERNAL: ATTN at beginning of string"); } else { --cp; } } /* * slide the string into its new position, noting the position of * the char beyond the final non-white character so that the final * whitespace can be eliminated. */ for (nb = cp; (*s++ = *cp) != '\0'; ++cp) { if (*cp != ' ' && *cp != '\t') { nb = s; } } *nb = '\0';}/* * nonwhite() - read until the next non-white (and non-comment) token, * using the scanner provided. * This routine is used only to skip whitespace within preprocessor command * lines. */int /* the non-white, non-comment token */nonwhite(scan)int (*scan)(); /* token scanner - either gtok() or gintok() */{ int tok; while ((tok = (*scan)()) == WHITE || tok == COMMENT) ; if (tok == 0) { warnf("unterminated preprocessor command"); } return(tok);}/* * endline() - if not already at the end of the line, read tokens to get there. * return the final token (either NL or 0). * Used only to read the ends of preprocessor command lines. * For the benefit of uninterpreted command lines, macros are interpreted. * * Endline should be called as late as possible in processing a line * so that error messages will be correlated to the offending line rather * than the following line. */intendline(){ int tok; /* the current token */ char *cp; /* the current character in a backward search */ /* * if the last character read (less ATTN byte pairs) * was an unescaped newline, return; * Otherwise, skip tokens until the end of the line or * the end of the file. */ for (cp = nxtout - 1; cp >= &pend[1]; cp -= 2) { if (*(cp - 1) != ATTN) { break; } } if (cp >= &pend[0] && *cp == '\n' && (cp == &pend[0] || *(cp - 1) != '\\')) { /* an unescaped newline has already been read */ return(NL); } while ((tok = gintok()) != NL) { if (tok == 0) { warnf("unterminated preprocessor command"); return(tok); } } return(tok);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -