📄 cpp2.c
字号:
#ifdef RCSstatic char rcsid[]="$Id: cpp2.c,v 1.5 1994/01/24 09:32:54 start Exp start $";#endif/****************************************************************************** * FREXXWARE * ---------------------------------------------------------------------------- * * Project: Frexx C Preprocessor * $Source: /home/user/start/cpp/RCS/cpp2.c,v $ * $Revision: 1.5 $ * $Date: 1994/01/24 09:32:54 $ * $Author: start $ * $State: Exp $ * $Locker: start $ * * ---------------------------------------------------------------------------- * $Log: cpp2.c,v $ * Revision 1.5 1994/01/24 09:32:54 start * Fixed AmigaDOS include file routine. * * Revision 1.4 1993/12/06 13:50:39 start * A lot of new stuff (too much to mention) * * Revision 1.4 1993/12/06 13:50:39 start * A lot of new stuff (too much to mention) * * Revision 1.3 1993/11/29 14:00:32 start * new * * Revision 1.2 1993/11/11 07:16:39 start * New stuff * * Revision 1.1 1993/11/03 09:13:08 start * Initial revision * * *****************************************************************************//* * C P P 2 . C * * Process #control lines * * Edit history * 13-Nov-84 MM Split from cpp1.c * 21-Oct-85 RMS Do not turn on `instring' while reading #include arg. * Rename `token' to `tokenbuf'. * Flush tabs at end of #include line, like spaces. * 14-Mar-86 FNF Incorporate macro based C debugging package. * Port to Commodore AMIGA. * 25-May-86 FNF Change handling of fully qualified include file * pathnames (like "/usr/include/stdio.h" for unix, * or "df0:include/stdio.h" for the Amiga) to be * used verbatum in the first open attempt. * 20-Aug-88 Ois Added #error. Passed unrecognized # commands. * Added \n when those lines are passed. */#include <stdio.h>#include <ctype.h>#include "cppdef.h"#include "cpp.h"FILE_LOCAL void dump_line(struct Global *, int *);FILE_LOCAL ReturnCode doif(struct Global *, int);INLINE FILE_LOCAL ReturnCode doinclude(struct Global *);INLINE FILE_LOCAL int hasdirectory(char *, char *);/* * Generate (by hand-inspection) a set of unique values for each control * operator. Note that this is not guaranteed to work for non-Ascii * machines. CPP won't compile if there are hash conflicts. */#define L_assert ('a' + ('s' << 1))#define L_define ('d' + ('f' << 1))#define L_elif ('e' + ('i' << 1))#define L_else ('e' + ('s' << 1))#define L_endif ('e' + ('d' << 1))#define L_error ('e' + ('r' << 1))#define L_if ('i' + (EOS << 1))#define L_ifdef ('i' + ('d' << 1))#define L_ifndef ('i' + ('n' << 1))#define L_include ('i' + ('c' << 1))#define L_line ('l' + ('n' << 1))#define L_nogood (EOS + (EOS << 1)) /* To catch #i */#define L_pragma ('p' + ('a' << 1))#define L_undef ('u' + ('d' << 1))ReturnCode control(struct Global *global, int *counter) /* Pending newline counter */{ /* * Process #control lines. Simple commands are processed inline, * while complex commands have their own subroutines. * * The counter is used to force out a newline before #line, and * #pragma commands. This prevents these commands from ending up at * the end of the previous line if cpp is invoked with the -C option. */ int c; char *tp; int hash; char *ep; ReturnCode ret; c = skipws(global); if (c == '\n' || c == EOF_CHAR) { (*counter)++; return(FPP_OK); } if (!isdigit(c)) scanid(global, c); /* Get #word to tokenbuf */ else { unget(global); /* Hack -- allow #123 as a */ strcpy(global->tokenbuf, "line"); /* synonym for #line 123 */ } hash = (global->tokenbuf[1] == EOS) ? L_nogood : (global->tokenbuf[0] + (global->tokenbuf[2] << 1)); switch (hash) { case L_assert: tp = "assert"; break; case L_define: tp = "define"; break; case L_elif: tp = "elif"; break; case L_else: tp = "else"; break; case L_endif: tp = "endif"; break; case L_error: tp = "error"; break; case L_if: tp = "if"; break; case L_ifdef: tp = "ifdef"; break; case L_ifndef: tp = "ifndef"; break; case L_include: tp = "include"; break; case L_line: tp = "line"; break; case L_pragma: tp = "pragma"; break; case L_undef: tp = "undef"; break; default: hash = L_nogood; case L_nogood: tp = ""; break; } if (!streq(tp, global->tokenbuf)) hash = L_nogood; /* * hash is set to a unique value corresponding to the * control keyword (or L_nogood if we think it's nonsense). */ if (global->infile->fp == NULL) cwarn(global, WARN_CONTROL_LINE_IN_MACRO, global->tokenbuf); if (!compiling) { /* Not compiling now */ switch (hash) { case L_if: /* These can't turn */ case L_ifdef: /* compilation on, but */ case L_ifndef: /* we must nest #if's */ if (++global->ifptr >= &global->ifstack[BLK_NEST]) { cfatal(global, FATAL_TOO_MANY_NESTINGS, global->tokenbuf); return(FPP_TOO_MANY_NESTED_STATEMENTS); } *global->ifptr = 0; /* !WAS_COMPILING */ case L_line: /* Many */ /* * Are pragma's always processed? */ case L_pragma: /* options */ case L_include: /* are uninteresting */ case L_define: /* if we */ case L_undef: /* aren't */ case L_assert: /* compiling. */ case L_error: dump_line(global, counter); /* Ignore rest of line */ return(FPP_OK); } } /* * Make sure that #line and #pragma are output on a fresh line. */ if (*counter > 0 && (hash == L_line || hash == L_pragma)) { Putchar(global, '\n'); (*counter)--; } switch (hash) { case L_line: /* * Parse the line to update the line number and "progname" * field and line number for the next input line. * Set wrongline to force it out later. */ c = skipws(global); global->workp = global->work; /* Save name in work */ while (c != '\n' && c != EOF_CHAR) { if(ret=save(global, c)) return(ret); c = get(global); } unget(global); if(ret=save(global, EOS)) return(ret); /* * Split #line argument into <line-number> and <name> * We subtract 1 as we want the number of the next line. */ global->line = atoi(global->work) - 1; /* Reset line number */ for (tp = global->work; isdigit(*tp) || type[*tp] == SPA; tp++) ; /* Skip over digits */ if (*tp != EOS) { /* Got a filename, so: */ if (*tp == '"' && (ep = strrchr(tp + 1, '"')) != NULL) { tp++; /* Skip over left quote */ *ep = EOS; /* And ignore right one */ } if (global->infile->progname != NULL) /* Give up the old name */ Freemem(global->infile->progname); /* if it's allocated. */ global->infile->progname = savestring(global, tp); } global->wrongline = TRUE; /* Force output later */ break; case L_include: ret=doinclude(global); if(ret) return(ret); break; case L_define: ret=dodefine(global); if(ret) return(ret); break; case L_undef: doundef(global); break; case L_else: if (global->ifptr == &global->ifstack[0]) { cerror(global, ERROR_STRING_MUST_BE_IF, global->tokenbuf); dump_line(global, counter); return(FPP_OK); } else if ((*global->ifptr & ELSE_SEEN) != 0) { cerror(global, ERROR_STRING_MAY_NOT_FOLLOW_ELSE, global->tokenbuf); dump_line(global, counter); return(FPP_OK); } *global->ifptr |= ELSE_SEEN; if ((*global->ifptr & WAS_COMPILING) != 0) { if (compiling || (*global->ifptr & TRUE_SEEN) != 0) compiling = FALSE; else { compiling = TRUE; } } break; case L_elif: if (global->ifptr == &global->ifstack[0]) { cerror(global, ERROR_STRING_MUST_BE_IF, global->tokenbuf); dump_line(global, counter); return(FPP_OK); } else if ((*global->ifptr & ELSE_SEEN) != 0) { cerror(global, ERROR_STRING_MAY_NOT_FOLLOW_ELSE, global->tokenbuf); dump_line(global, counter); return(FPP_OK); } if ((*global->ifptr & (WAS_COMPILING | TRUE_SEEN)) != WAS_COMPILING) { compiling = FALSE; /* Done compiling stuff */ dump_line(global, counter); /* Skip this clause */ return(FPP_OK); } ret=doif(global, L_if); if(ret) return(ret); break; case L_error: cerror(global, ERROR_ERROR); break; case L_if: case L_ifdef: case L_ifndef: if (++global->ifptr < &global->ifstack[BLK_NEST]) { *global->ifptr = WAS_COMPILING; ret=doif(global, hash);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -