📄 cpp2.c
字号:
if(ret) return(ret); break; } cfatal(global, FATAL_TOO_MANY_NESTINGS, global->tokenbuf); return(FPP_TOO_MANY_NESTED_STATEMENTS); case L_endif: if (global->ifptr == &global->ifstack[0]) { cerror(global, ERROR_STRING_MUST_BE_IF, global->tokenbuf); dump_line(global, counter); return(FPP_OK); } if (!compiling && (*global->ifptr & WAS_COMPILING) != 0) global->wrongline = TRUE; compiling = ((*global->ifptr & WAS_COMPILING) != 0); --global->ifptr; break; case L_assert: { int result; ret=eval(global, &result); if(ret) return(ret); if (result == 0) cerror(global, ERROR_PREPROC_FAILURE); } break; case L_pragma: /* * #pragma is provided to pass "options" to later * passes of the compiler. cpp doesn't have any yet. */ Putstring(global, "#pragma "); while ((c = get(global)) != '\n' && c != EOF_CHAR) Putchar(global, c); unget(global); Putchar(global, '\n'); break; default: /* * Undefined #control keyword. * Note: the correct behavior may be to warn and * pass the line to a subsequent compiler pass. * This would allow #asm or similar extensions. */ if(global->warnillegalcpp) cwarn(global, WARN_ILLEGAL_COMMAND, global->tokenbuf); Putchar(global, '#'); Putstring(global, global->tokenbuf); Putchar(global, ' '); while ((c = get(global)) != '\n' && c != EOF_CHAR) Putchar(global, c); unget(global); Putchar(global, '\n'); break; } if (hash != L_include) {#if OLD_PREPROCESSOR /* * Ignore the rest of the #control line so you can write * #if foo * #endif foo */ dump_line(global, counter); /* Take common exit */ return(FPP_OK);#else if (skipws(global) != '\n') { cwarn(global, WARN_UNEXPECTED_TEXT_IGNORED); skipnl(global); }#endif } (*counter)++; return(FPP_OK);}FILE_LOCALvoid dump_line(struct Global *global, int *counter){ skipnl(global); /* Ignore rest of line */ (*counter)++;}FILE_LOCALReturnCode doif(struct Global *global, int hash){ /* * Process an #if, #ifdef, or #ifndef. The latter two are straightforward, * while #if needs a subroutine of its own to evaluate the expression. * * doif() is called only if compiling is TRUE. If false, compilation * is always supressed, so we don't need to evaluate anything. This * supresses unnecessary warnings. */ int c; int found; ReturnCode ret; if ((c = skipws(global)) == '\n' || c == EOF_CHAR) { unget(global); cerror(global, ERROR_MISSING_ARGUMENT);#if !OLD_PREPROCESSOR skipnl(global); /* Prevent an extra */ unget(global); /* Error message */#endif return(FPP_OK); } if (hash == L_if) { unget(global); ret=eval(global, &found); if(ret) return(ret); found = (found != 0); /* Evaluate expr, != 0 is TRUE */ hash = L_ifdef; /* #if is now like #ifdef */ } else { if (type[c] != LET) { /* Next non-blank isn't letter */ /* ... is an error */ cerror(global, ERROR_MISSING_ARGUMENT);#if !OLD_PREPROCESSOR skipnl(global); /* Prevent an extra */ unget(global); /* Error message */#endif return(FPP_OK); } found = (lookid(global, c) != NULL); /* Look for it in symbol table */ } if (found == (hash == L_ifdef)) { compiling = TRUE; *global->ifptr |= TRUE_SEEN; } else compiling = FALSE; return(FPP_OK);}INLINE FILE_LOCALReturnCode doinclude(struct Global *global){ /* * Process the #include control line. * There are three variations: * #include "file" search somewhere relative to the * current source file, if not found, * treat as #include <file>. * #include <file> Search in an implementation-dependent * list of places. * #include token Expand the token, it must be one of * "file" or <file>, process as such. * * Note: the November 12 draft forbids '>' in the #include <file> format. * This restriction is unnecessary and not implemented. */ int c; int delim; ReturnCode ret; delim = skipws(global); if(ret=macroid(global, &delim)) return(ret); if (delim != '<' && delim != '"') { cerror(global, ERROR_INCLUDE_SYNTAX); return(FPP_OK); } if (delim == '<') delim = '>'; global->workp = global->work; while ((c = get(global)) != '\n' && c != EOF_CHAR) if(ret=save(global, c)) /* Put it away. */ return(ret); unget(global); /* Force nl after includee */ /* * The draft is unclear if the following should be done. */ while (--global->workp >= global->work && (*global->workp == ' ' || *global->workp == '\t')) ; /* Trim blanks from filename */ if (*global->workp != delim) { cerror(global, ERROR_INCLUDE_SYNTAX); return(FPP_OK); } *global->workp = EOS; /* Terminate filename */ ret=openinclude(global, global->work, (delim == '"')); if(ret && global->warnnoinclude) { /* * Warn if #include file isn't there. */ cwarn(global, WARN_CANNOT_OPEN_INCLUDE, global->work); } return(FPP_OK);}ReturnCode openinclude(struct Global *global, char *filename, /* Input file name */ int searchlocal) /* TRUE if #include "file" */{ /* * Actually open an include file. This routine is only called from * doinclude() above, but was written as a separate subroutine for * programmer convenience. It searches the list of directories * and actually opens the file, linking it into the list of * active files. Returns ReturnCode. No error message is printed. */ char **incptr; char tmpname[NWORK]; /* Filename work area */ int len;#if HOST == SYS_AMIGADOS if(strchr (filename, ':') != NULL) { if(! openfile (global, filename)) return(FPP_OK); }#else if (filename[0] == '/') { if(! openfile(global, filename)) return(FPP_OK); }#endif if (searchlocal) { /* * Look in local directory first. * Try to open filename relative to the directory of the current * source file (as opposed to the current directory). (ARF, SCK). * Note that the fully qualified pathname is always built by * discarding the last pathname component of the source file * name then tacking on the #include argument. */ if(hasdirectory(global->infile->filename, tmpname)) strcat(tmpname, filename); else strcpy(tmpname, filename); if(! openfile(global, tmpname)) return(FPP_OK); } /* * Look in any directories specified by -I command line * arguments, then in the builtin search list. */ for (incptr = global->incdir; incptr < global->incend; incptr++) { len = strlen(*incptr); if (len + strlen(filename) >= sizeof(tmpname)) { cfatal(global, FATAL_FILENAME_BUFFER_OVERFLOW); return(FPP_FILENAME_BUFFER_OVERFLOW); } else {#if HOST == SYS_AMIGADOS if((*incptr)[len-1] != '/' && (*incptr)[len-1] != ':') sprintf(tmpname, "%s/%s", *incptr, filename);#else if((*incptr)[len-1] != '/') sprintf(tmpname, "%s/%s", *incptr, filename);#endif else sprintf(tmpname, "%s%s", *incptr, filename); if (!openfile(global, tmpname)) return(FPP_OK); } } return(FPP_NO_INCLUDE);}INLINE FILE_LOCALint hasdirectory(char *source, /* Directory to examine */ char *result) /* Put directory stuff here */{ /* * If a device or directory is found in the source filename string, the * node/device/directory part of the string is copied to result and * hasdirectory returns TRUE. Else, nothing is copied and it returns FALSE. */ char *tp2;#if HOST == SYS_AMIGADOS char *tp1; if ((tp1 = strrchr(source, ':')) == NULL) tp1 = source; if ((tp2 = strrchr(tp1, '/')) == NULL) tp2 = tp1; if (tp2 == source) return (FALSE);#else if ((tp2 = strrchr(source, '/')) == NULL) return(FALSE);#endif strncpy(result, source, tp2 - source + 1); result[tp2 - source + 1] = EOS; return(TRUE);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -