📄 cpp4.c
字号:
else { scanid(global, c); /* Get name to tokenbuf */ (void) defendel(global, global->tokenbuf, TRUE); }}INLINE FILE_LOCAL ReturnCode textput(struct Global *global, char *text){ /* * Put the string in the parm[] buffer. */ int size; size = strlen(text) + 1; if ((global->parmp + size) >= &global->parm[NPARMWORK]) { cfatal(global, FATAL_MACRO_AREA_OVERFLOW); return(FPP_WORK_AREA_OVERFLOW); } else { strcpy(global->parmp, text); global->parmp += size; } return(FPP_OK);}FILE_LOCALReturnCode charput(struct Global *global, int c){ /* * Put the byte in the parm[] buffer. */ if (global->parmp >= &global->parm[NPARMWORK]) { cfatal(global, FATAL_MACRO_AREA_OVERFLOW); return(FPP_WORK_AREA_OVERFLOW); } *global->parmp++ = c; return(FPP_OK);}/* * M a c r o E x p a n s i o n */ReturnCode expand(struct Global *global, DEFBUF *tokenp){ /* * Expand a macro. Called from the cpp mainline routine (via subroutine * macroid()) when a token is found in the symbol table. It calls * expcollect() to parse actual parameters, checking for the correct number. * It then creates a "file" containing a single line containing the * macro with actual parameters inserted appropriately. This is * "pushed back" onto the input stream. (When the get() routine runs * off the end of the macro line, it will dismiss the macro itself.) */ int c; FILEINFO *file; ReturnCode ret=FPP_OK; /* * If no macro is pending, save the name of this macro * for an eventual error message. */ if (global->recursion++ == 0) global->macro = tokenp; else if (global->recursion == RECURSION_LIMIT) { cerror(global, ERROR_RECURSIVE_MACRO, tokenp->name, global->macro->name); if (global->rec_recover) { do { c = get(global); } while (global->infile != NULL && global->infile->fp == NULL); unget(global); global->recursion = 0; return(FPP_OK); } } /* * Here's a macro to expand. */ global->nargs = 0; /* Formals counter */ global->parmp = global->parm; /* Setup parm buffer */ switch (tokenp->nargs) { case (-2): /* __LINE__ */ if(global->infile->fp) /* This is a file */ sprintf(global->work, "%d", global->line); else /* This is a macro! Find out the file line number! */ for (file = global->infile; file != NULL; file = file->parent) { if (file->fp != NULL) { sprintf(global->work, "%d", file->line); break; } } ret=ungetstring(global, global->work); if(ret) return(ret); break; case (-3): /* __FILE__ */ for (file = global->infile; file != NULL; file = file->parent) { if (file->fp != NULL) { sprintf(global->work, "\"%s\"", (file->progname != NULL) ? file->progname : file->filename); ret=ungetstring(global, global->work); if(ret) return(ret); break; } } break; case (-4): /* __FUNC__ */ sprintf(global->work, "\"%s\"", global->functionname[0]? global->functionname : "<unknown function>"); ret=ungetstring(global, global->work); if(ret) return(ret); break; case (-5): /* __FUNC_LINE__ */ sprintf(global->work, "%d", global->funcline); ret=ungetstring(global, global->work); if(ret) return(ret); break; default: /* * Nothing funny about this macro. */ if (tokenp->nargs < 0) { cfatal(global, FATAL_ILLEGAL_MACRO, tokenp->name); return(FPP_ILLEGAL_MACRO); } while ((c = skipws(global)) == '\n') /* Look for (, skipping */ global->wrongline = TRUE; /* spaces and newlines */ if (c != '(') { /* * If the programmer writes * #define foo() ... * ... * foo [no ()] * just write foo to the output stream. */ unget(global); cwarn(global, WARN_MACRO_NEEDS_ARGUMENTS, tokenp->name); /* fputs(tokenp->name, stdout); */ Putstring(global, tokenp->name); return(FPP_OK); } else if (!(ret=expcollect(global))) { /* Collect arguments */ if (tokenp->nargs != global->nargs) { /* Should be an error? */ cwarn(global, WARN_WRONG_NUMBER_ARGUMENTS, tokenp->name); } } else { /* Collect arguments */ return(ret); /* We failed in argument colleting! */ } case DEF_NOARGS: /* No parameters just stuffs */ ret=expstuff(global, tokenp->name, tokenp->repl); /* expand macro */ } /* nargs switch */ return(ret);}INLINE FILE_LOCALReturnCode expcollect(struct Global *global){ /* * Collect the actual parameters for this macro. */ int c; int paren; /* For embedded ()'s */ ReturnCode ret; for (;;) { paren = 0; /* Collect next arg. */ while ((c = skipws(global)) == '\n')/* Skip over whitespace */ global->wrongline = TRUE; /* and newlines. */ if (c == ')') { /* At end of all args? */ /* * Note that there is a guard byte in parm[] * so we don't have to check for overflow here. */ *global->parmp = EOS; /* Make sure terminated */ break; /* Exit collection loop */ } else if (global->nargs >= LASTPARM) { cfatal(global, FATAL_TOO_MANY_ARGUMENTS_EXPANSION); return(FPP_TOO_MANY_ARGUMENTS); } global->parlist[global->nargs++] = global->parmp; /* At start of new arg */ for (;; c = cget(global)) { /* Collect arg's bytes */ if (c == EOF_CHAR) { cerror(global, ERROR_EOF_IN_ARGUMENT); return(FPP_EOF_IN_MACRO); /* Sorry. */ } else if (c == '\\') { /* Quote next character */ charput(global, c); /* Save the \ for later */ charput(global, cget(global)); /* Save the next char. */ continue; /* And go get another */ } else if (type[c] == QUO) { /* Start of string? */ ret=scanstring(global, c, (ReturnCode (*)(struct Global *, int))charput); /* Scan it off */ if(ret) return(ret); continue; /* Go get next char */ } else if (c == '(') /* Worry about balance */ paren++; /* To know about commas */ else if (c == ')') { /* Other side too */ if (paren == 0) { /* At the end? */ unget(global); /* Look at it later */ break; /* Exit arg getter. */ } paren--; /* More to come. */ } else if (c == ',' && paren == 0) /* Comma delimits args */ break; else if (c == '\n') /* Newline inside arg? */ global->wrongline = TRUE; /* We'll need a #line */ charput(global, c); /* Store this one */ } /* Collect an argument */ charput(global, EOS); /* Terminate argument */ } /* Collect all args. */ return(FPP_OK); /* Normal return */} #if OK_CONCAT INLINE FILE_LOCALchar *doquoting(char *to, char *from){ *to++ = '"'; while (*from) { if (*from == '\\' || *from == '"') *to++ = '\\'; *to++ = *from++; } *to++ = '"'; return to;} #endif ReturnCode expstuff(struct Global *global, char *MacroName, char *MacroReplace){ /* * Stuff the macro body, replacing formal parameters by actual parameters. */ int c; /* Current character */ char *inp; /* -> repl string */ char *defp; /* -> macro output buff */ int size; /* Actual parm. size */ char *defend; /* -> output buff end */ int string_magic; /* String formal hack */ FILEINFO *file; /* Funny #include */ ReturnCode ret;#if OK_CONCAT char quoting; /* Quote macro argument */#endif ret = getfile(global, NBUFF, MacroName, &file); if(ret) return(ret); inp = MacroReplace; /* -> macro replacement */ defp = file->buffer; /* -> output buffer */ defend = defp + (NBUFF - 1); /* Note its end */ if (inp != NULL) { quoting = 0; while ((c = (*inp++ & 0xFF)) != EOS) {#if OK_CONCAT if (c == QUOTE_PARM) { /* Special token for # */ quoting = 1; /* set flag, for later */ continue; /* Get next character */ }#endif if (c >= MAC_PARM && c <= (MAC_PARM + PAR_MAC)) { string_magic = (c == (MAC_PARM + PAR_MAC)); if (string_magic) c = (*inp++ & 0xFF); /* * Replace formal parameter by actual parameter string. */ if ((c -= MAC_PARM) < global->nargs) { size = strlen(global->parlist[c]);#if OK_CONCAT if (quoting) { size++; size *= 2; /* worst case condition */ }#endif if ((defp + size) >= defend) { cfatal(global, FATAL_OUT_OF_SPACE_IN_ARGUMENT, MacroName); return(FPP_OUT_OF_SPACE_IN_MACRO_EXPANSION); } /* * Erase the extra set of quotes. */ if (string_magic && defp[-1] == global->parlist[c][0]) { strcpy(defp-1, global->parlist[c]); defp += (size - 2); }#if OK_CONCATelse if (quoting) defp = doquoting(defp, global->parlist[c]);#endifelse { strcpy(defp, global->parlist[c]); defp += size;} } } else if (defp >= defend) { cfatal(global, FATAL_OUT_OF_SPACE_IN_ARGUMENT, MacroName); return(FPP_OUT_OF_SPACE_IN_MACRO_EXPANSION); } else *defp++ = c; quoting = 0; } } *defp = EOS; return(FPP_OK);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -