cpp6.c
来自「类PASCAL语言的编译器,LINUX环境的,我没试过是否正确.」· C语言 代码 · 共 1,221 行 · 第 1/3 页
C
1,221 行
if (file->fp == NULL) { /* NULL if macro */ popped++; global->recursion -= file->unrecur; if (global->recursion < 0) global->recursion = 0; global->infile = file->parent; /* Unwind file chain */ } else { /* Else get from a file */ /* * If a input routine has been specified in the initial taglist, * we should get the next line from that function IF we're reading * from that certain file! */ if(global->input && global->first_file && !strcmp(global->first_file, file->filename)) file->bptr = global->input(file->buffer, NBUFF, global->userdata); else file->bptr = fgets(file->buffer, NBUFF, file->fp); if(file->bptr != NULL) { goto newline; /* process the line */ } else { if(!(global->input && global->first_file && !strcmp(global->first_file, file->filename))) /* If the input function isn't user supplied, close the file! */ fclose(file->fp); /* Close finished file */ if ((global->infile = file->parent) != NULL) { /* * There is an "ungotten" newline in the current * infile buffer (set there by doinclude() in * cpp1.c). Thus, we know that the mainline code * is skipping over blank lines and will do a * #line at its convenience. */ global->wrongline = TRUE; /* Need a #line now */ } } } /* * Free up space used by the (finished) file or macro and * restart input from the parent file/macro, if any. */ Freemem(file->filename); /* Free name and */ if (file->progname != NULL) /* if a #line was seen, */ Freemem(file->progname); /* free it, too. */ Freemem(file); /* Free file space */ if (global->infile == NULL) /* If at end of file */ return (EOF_CHAR); /* Return end of file */ global->line = global->infile->line; /* Reset line number */ goto get_from_file; /* Get from the top. */ } /* * Common processing for the new character. */ if (c == DEF_MAGIC && file->fp != NULL) /* Don't allow delete */ goto newline; /* from a file */ if (file->parent != NULL) { /* Macro or #include */ if (popped != 0) file->parent->unrecur += popped; else { global->recursion -= file->parent->unrecur; if (global->recursion < 0) global->recursion = 0; file->parent->unrecur = 0; } } if (c == '\n') /* Maintain current */ ++global->line; /* line counter */ if (global->instring) /* Strings just return */ return (c); /* the character. */ else if (c == '/') { /* Comment? */ global->instring = TRUE; /* So get() won't loop */ /* Check next byte for '*' and if(cplusplus) also '/' */ if ( (c = get(global)) != '*' ) if(!global->cplusplus || (global->cplusplus && c!='/')) { global->instring = FALSE; /* Nope, no comment */ unget(global); /* Push the char. back */ return ('/'); /* Return the slash */ } comments = 1; if (global->keepcomments) { /* If writing comments */ global->comment = TRUE; /* information that a comment has been output */ if(global->showspace) { /* Show all whitespaces! */ global->spacebuf[global->chpos] = '\0'; Putstring(global, global->spacebuf); } if(c=='*') { Putchar(global, '/'); /* Write out the */ Putchar(global, '*'); /* initializer */ } else { /* C++ style comment */ Putchar(global, '/'); /* Write out the */ Putchar(global, '/'); /* initializer */ } } if(global->cplusplus && c=='/') { /* Eat C++ comment! */ do { c=get(global); if(global->keepcomments) Putchar(global, c); } while(c!='\n' && c!=EOF_CHAR); /* eat all to EOL or EOF */ global->instring = FALSE; /* End of comment */ return(c); /* Return the end char */ } for (;;) { /* Eat a comment */ c = get(global); test: if (global->keepcomments && c != EOF_CHAR) Putchar(global, c); switch (c) { case EOF_CHAR: cerror(global, ERROR_EOF_IN_COMMENT); return (EOF_CHAR); case '/': if(global->nestcomments || global->warnnestcomments) { if((c = get(global)) != '*') goto test; if(global->warnnestcomments) { cwarn(global, WARN_NESTED_COMMENT); } if(global->nestcomments) comments++; } break; case '*': if ((c = get(global)) != '/') /* If comment doesn't */ goto test; /* end, look at next */ if (global->keepcomments) { /* Put out the comment */ Putchar(global, c); /* terminator, too */ } if(--comments) /* nested comment, continue! */ break; global->instring = FALSE; /* End of comment, */ /* * A comment is syntactically "whitespace" -- * however, there are certain strange sequences * such as * #define foo(x) (something) * foo|* comment *|(123) * these are '/' ^ ^ * where just returning space (or COM_SEP) will cause * problems. This can be "fixed" by overwriting the * '/' in the input line buffer with ' ' (or COM_SEP) * but that may mess up an error message. * So, we peek ahead -- if the next character is * "whitespace" we just get another character, if not, * we modify the buffer. All in the name of purity. */ if (*file->bptr == '\n' || type[*file->bptr & 0xFF] == SPA) goto newline;#if COMMENT_INVISIBLE /* * Return magic (old-fashioned) syntactic space. */ return ((file->bptr[-1] = COM_SEP));#else return ((file->bptr[-1] = ' '));#endif case '\n': /* we'll need a #line */ if (!global->keepcomments) global->wrongline = TRUE; /* later... */ default: /* Anything else is */ break; /* Just a character */ } /* End switch */ } /* End comment loop */ } /* End if in comment */ else if (!global->inmacro && c == '\\') { /* If backslash, peek */ if ((c = get(global)) == '\n') { /* for a <nl>. If so, */ global->wrongline = TRUE; goto newline; } else { /* Backslash anything */ unget(global); /* Get it later */ return ('\\'); /* Return the backslash */ } } else if (c == '\f' || c == VT) /* Form Feed, Vertical */ c = ' '; /* Tab are whitespace */ return (c); /* Just return the char */}void unget(struct Global *global){ /* * Backup the pointer to reread the last character. Fatal error * (code bug) if we backup too far. unget() may be called, * without problems, at end of file. Only one character may * be ungotten. If you need to unget more, call ungetstring(). */ FILEINFO *file; if ((file = global->infile) == NULL) return; /* Unget after EOF */ if (--file->bptr < file->buffer) { cfatal(global, FATAL_TOO_MUCH_PUSHBACK); /* This happens only if used the wrong way! */ return; } if (*file->bptr == '\n') /* Ungetting a newline? */ --global->line; /* Unget the line number, too */}ReturnCode ungetstring(struct Global *global, char *text){ /* * Push a string back on the input stream. This is done by treating * the text as if it were a macro. */ FILEINFO *file; ReturnCode ret; ret = getfile(global, strlen(text) + 1, "", &file); if(!ret) strcpy(file->buffer, text); return(ret);}int cget(struct Global *global){ /* * Get one character, absorb "funny space" after comments or * token concatenation */ int c; do { c = get(global);#if COMMENT_INVISIBLE } while (c == TOK_SEP || c == COM_SEP);#else } while (c == TOK_SEP);#endif return (c);}/* * Error messages and other hacks. */INLINE FILE_LOCALvoid domsg(struct Global *global, ErrorCode error, /* error message number */ va_list arg) /* Something for the message */{ /* * Print filenames, macro names, and line numbers for error messages. */ static char *ErrorMessage[]={ /* * ERRORS: */ "#%s must be in an #if", "#%s may not follow #else", "#error directive encountered", "Preprocessor assertion failure", "#if, #ifdef, or #ifndef without an argument", "#include syntax error", "#define syntax error", "Redefining defined variable \"%s\"", "Illegal #undef argument", "Recursive macro definition of \"%s\"(Defined by \"%s\")", "end of file within macro argument", "misplaced constant in #if", "#if value stack overflow", "Illegal #if line", "Operator %s in incorrect context", "expression stack overflow at op \"%s\"", "unbalanced paren's, op is \"%s\"", "Misplaced '?' or ':', previous operator is %s", "Can't use a string in an #if", "Bad #if ... defined() syntax", "= not allowed in #if", "Unexpected \\ in #if", "#if ... sizeof() syntax error", "#if sizeof, unknown type \"%s\"", "#if ... sizeof: illegal type combination", "#if sizeof() error, no type specified", "Unterminated string", "EOF in comment", "Inside #ifdef block at end of input, depth = %d", "illegal character '%c' in #if", "illegal character (%d decimal) in #if", "#if ... sizeof: bug, unknown type code 0x%x", "#if bug, operand = %d.", "Strange character '%c' after ##", "Strange character (%d.) after ##", "", /* Dummy, to visualize the border between errors and warnings */ /* * WARNINGS: */ "Control line \"%s\" within macro expansion", "Illegal # command \"%s\"", "Unexpected text in #control line ignored", "too few values specified to sizeof", "too many values specified to sizeof! Not used.", "\"%s\" wasn't defined", "Internal error!", "Macro \"%s\" needs arguments", "Wrong number of macro arguments for \"%s\"", "%s by zero in #if, zero result assumed", "Illegal digit in octal number", "multi-byte constant '%c' isn't portable", "Cannot open include file \"%s\"", "Illegal bracket '[]' balance, depth = %d", "Illegal parentheses '()' balance, depth = %d", "Illegal brace '{}' balance, depth = %d", "Nested comment", "", /* Dummy, to visualize the border between warnings and fatals */ /* * FATALS: */ "Too many nested #%s statements", "Filename work buffer overflow", "Too many include directories", "Too many include files", "Too many arguments for macro", "Macro work area overflow", "Bug: Illegal __ macro \"%s\"", "Too many arguments in macro expansion", "Out of space in macro \"%s\" arg expansion", "work buffer overflow doing %s ##", "Work buffer overflow", "Out of memory", "Too much pushback", /* internal */ }; char *tp; FILEINFO *file; char *severity=error<BORDER_ERROR_WARN?"Error": error<BORDER_WARN_FATAL?"Warning": "Fatal"; for (file = global->infile; file && !file->fp; file = file->parent) ; tp = file ? file->filename : 0; Error(global, "%s\"%s\", line %d: %s: ", MSG_PREFIX, tp, global->infile->fp?global->line:file->line, severity); if(global->error) global->error(global->userdata, ErrorMessage[error], arg);#if defined(UNIX) else vfprintf(stderr, ErrorMessage[error], arg);#elif defined(AMIGA) else return;#endif Error(global, "\n"); if (file) /*OIS*0.92*/ while ((file = file->parent) != NULL) { /* Print #includes, too */ tp = file->parent ? "," : "."; if (file->fp == NULL) Error(global, " from macro %s%s\n", file->filename, tp); else Error(global, " from file %s, line %d%s\n", (file->progname != NULL) ? file->progname : file->filename, file->line, tp); } if(error<BORDER_ERROR_WARN) /* Error! Increase error counter! */ global->errors++;}void cerror(struct Global *global, ErrorCode message, ...) /* arguments */{ /* * Print a normal error message, string argument. */ va_list arg; va_start(arg, message); domsg(global, message, arg);}void Error(struct Global *global, char *format, ...){ /* * Just get the arguments and send a decent string to the user error * string handler or to stderr. */ va_list arg; va_start(arg, format); if(global->error) global->error(global->userdata, format, arg);#if defined(UNIX) else vfprintf(stderr, format, arg);#endif}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?