cpp6.c
来自「类PASCAL语言的编译器,LINUX环境的,我没试过是否正确.」· C语言 代码 · 共 1,221 行 · 第 1/3 页
C
1,221 行
#ifdef RCSstatic char rcsid[]="$Id: cpp6.c,v 1.5 1994/01/24 09:35:17 start Exp $";#endif/****************************************************************************** * FREXXWARE * ---------------------------------------------------------------------------- * * Project: Frexx C Preprocessor * $Source: /home/user/start/cpp/RCS/cpp6.c,v $ * $Revision: 1.5 $ * $Date: 1994/01/24 09:35:17 $ * $Author: start $ * $State: Exp $ * $Locker: $ * * ---------------------------------------------------------------------------- * $Log: cpp6.c,v $ * Revision 1.5 1994/01/24 09:35:17 start * Made the FPPTAG_RIGHTCONCAT work. * * 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 6 . C * S u p p o r t R o u t i n e s * * Edit History * 25-May-84 MM Added 8-bit support to type table. * 30-May-84 ARF sharp() should output filename in quotes * 02-Aug-84 MM Newline and #line hacking. sharp() now in cpp1.c * 31-Aug-84 MM USENET net.sources release * 11-Sep-84 ado/MM Keepcomments, also line number pathological * 12-Sep-84 ado/MM bug if comment changes to space and we unget later. * 03-Oct-84 gkr/MM Fixed scannumber bug for '.e' (as in struct.element). * 04-Oct-84 MM Added ungetstring() for token concatenation * 08-Oct-84 MM Yet another attack on number scanning * 31-Oct-84 ado Parameterized $ in identifiers * 2-Nov-84 MM Token concatenation is messier than I thought * 6-Dec-84 MM \<nl> is everywhere invisible. * 21-Oct-85 RMS Rename `token' to `tokenbuf'. * Dynamically allocate it, and make it as big as needed. * 23-Oct-85 RMS Fix bugs storing into tokenbuf as it gets bigger. * Change error msg to cpp: "FILE", line LINE: MSG * 24-Oct-85 RMS Turn off warnings about / then * inside a comment. * 16-Mar-86 FNF Incorporate macro based C debugging package. * Port to Commodore Amiga. * 20-Aug-88 Ois Added time routines (or actually deleted stubs). * 20-Aug-88 Ois Changed handling of token following ## to match Cpp4. * 16-Feb-93 DSt Changed case of getmem() to Getmem(). */#include <stdio.h>#include <ctype.h>#include "cppdef.h"#include "cpp.h"INLINE FILE_LOCAL void outadefine(struct Global *, DEFBUF *);INLINE FILE_LOCAL void domsg(struct Global *, ErrorCode, va_list);FILE_LOCAL char *incmem(struct Global *, char *, int);/* * skipnl() skips over input text to the end of the line. * skipws() skips over "whitespace" (spaces or tabs), but * not skip over the end of the line. It skips over * TOK_SEP, however (though that shouldn't happen). * scanid() reads the next token (C identifier) into tokenbuf. * The caller has already read the first character of * the identifier. Unlike macroid(), the token is * never expanded. * macroid() reads the next token (C identifier) into tokenbuf. * If it is a #defined macro, it is expanded, and * macroid() returns TRUE, otherwise, FALSE. * catenate() Does the dirty work of token concatenation, TRUE if it did. * scanstring() Reads a string from the input stream, calling * a user-supplied function for each character. * This function may be output() to write the * string to the output file, or save() to save * the string in the work buffer. * scannumber() Reads a C numeric constant from the input stream, * calling the user-supplied function for each * character. (output() or save() as noted above.) * save() Save one character in the work[] buffer. * savestring() Saves a string in malloc() memory. * getfile() Initialize a new FILEINFO structure, called when * #include opens a new file, or a macro is to be * expanded. * Getmem() Get a specified number of bytes from malloc memory. * output() Write one character to stdout (calling Putchar) -- * implemented as a function so its address may be * passed to scanstring() and scannumber(). * lookid() Scans the next token (identifier) from the input * stream. Looks for it in the #defined symbol table. * Returns a pointer to the definition, if found, or NULL * if not present. The identifier is stored in tokenbuf. * defnedel() Define enter/delete subroutine. Updates the * symbol table. * get() Read the next byte from the current input stream, * handling end of (macro/file) input and embedded * comments appropriately. Note that the global * instring is -- essentially -- a parameter to get(). * cget() Like get(), but skip over TOK_SEP. * unget() Push last gotten character back on the input stream. * cerror() This routine format an print messages to the user. *//* * This table must be rewritten for a non-Ascii machine. * * Note that several "non-visible" characters have special meaning: * Hex 1C QUOTE_PARM --a flag for # stringifying * Hex 1D DEF_MAGIC -- a flag to prevent #define recursion. * Hex 1E TOK_SEP -- a delimiter for ## token concatenation * Hex 1F COM_SEP -- a zero-width whitespace for comment concatenation */#ifndef OS9#if (TOK_SEP != 0x1E || COM_SEP != 0x1F || DEF_MAGIC != 0x1D)#error "<< error type table isn't correct >>"#endif#endif#if OK_DOLLAR#define DOL LET#else#define DOL 000#endifchar type[256] = { /* Character type codes Hex */ END, 000, 000, 000, 000, 000, 000, 000, /* 00 */ 000, SPA, 000, 000, 000, 000, 000, 000, /* 08 */ 000, 000, 000, 000, 000, 000, 000, 000, /* 10 */ 000, 000, 000, 000, 000, LET, 000, SPA, /* 18 */ SPA, OP_NOT, QUO, 000, DOL, OP_MOD,OP_AND,QUO, /* 20 !"#$%&' */ OP_LPA,OP_RPA,OP_MUL,OP_ADD, 000,OP_SUB, DOT,OP_DIV, /* 28 ()*+,-./ */ DIG, DIG, DIG, DIG, DIG, DIG, DIG, DIG, /* 30 01234567 */ DIG, DIG,OP_COL, 000, OP_LT, OP_EQ, OP_GT,OP_QUE, /* 38 89:;<=>? */ 000, LET, LET, LET, LET, LET, LET, LET, /* 40 @ABCDEFG */ LET, LET, LET, LET, LET, LET, LET, LET, /* 48 HIJKLMNO */ LET, LET, LET, LET, LET, LET, LET, LET, /* 50 PQRSTUVW */ LET, LET, LET, 000, BSH, 000,OP_XOR, LET, /* 58 XYZ[\]^_ */ 000, LET, LET, LET, LET, LET, LET, LET, /* 60 `abcdefg */ LET, LET, LET, LET, LET, LET, LET, LET, /* 68 hijklmno */ LET, LET, LET, LET, LET, LET, LET, LET, /* 70 pqrstuvw */ LET, LET, LET, 000, OP_OR, 000,OP_NOT, 000, /* 78 xyz{|}~ */ 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */ 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */ 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */ 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */ 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */ 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */ 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */ 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */};void skipnl(struct Global *global){ /* * Skip to the end of the current input line. */ int c; do { /* Skip to newline */ c = get(global); } while (c != '\n' && c != EOF_CHAR); return;}int skipws(struct Global *global){ /* * Skip over whitespace */ int c; do { /* Skip whitespace */ c = get(global);#if COMMENT_INVISIBLE } while (type[c] == SPA || c == COM_SEP);#else} while (type[c] == SPA);#endif return(c);}void scanid(struct Global *global, int c) /* First char of id */{ /* * Get the next token (an id) into the token buffer. * Note: this code is duplicated in lookid(). * Change one, change both. */ int ct; if (c == DEF_MAGIC) /* Eat the magic token */ c = get(global); /* undefiner. */ ct = 0; do { if (ct == global->tokenbsize) global->tokenbuf = incmem (global, global->tokenbuf, 1 + (global->tokenbsize *= 2)); global->tokenbuf[ct++] = c; c = get(global); } while (type[c] == LET || type[c] == DIG); unget(global); global->tokenbuf[ct] = EOS;}ReturnCode macroid(struct Global *global, int *c){ /* * If c is a letter, scan the id. if it's #defined, expand it and scan * the next character and try again. * * Else, return the character. If type[c] is a LET, the token is in tokenbuf. */ DEFBUF *dp; ReturnCode ret=FPP_OK; if (global->infile != NULL && global->infile->fp != NULL) global->recursion = 0; while (type[*c] == LET && (dp = lookid(global, *c)) != NULL) { if(ret=expand(global, dp)) return(ret); *c = get(global); } return(FPP_OK);}int catenate(struct Global *global, ReturnCode *ret){ /* * A token was just read (via macroid). * If the next character is TOK_SEP, concatenate the next token * return TRUE -- which should recall macroid after refreshing * macroid's argument. If it is not TOK_SEP, unget() the character * and return FALSE. */#if OK_CONCAT int c; char *token1;#endif #if OK_CONCAT if (get(global) != TOK_SEP) { /* Token concatenation */ unget(global); return (FALSE); } else { token1 = savestring(global, global->tokenbuf); /* Save first token */ c=get(global); if(global->rightconcat) { *ret=macroid(global, &c); /* Scan next token */ if(*ret) return(FALSE); } else lookid(global, c); switch(type[c]) { /* What was it? */ case LET: /* An identifier, ... */ if ((int)strlen(token1) + (int)strlen(global->tokenbuf) >= NWORK) { cfatal(global, FATAL_WORK_AREA_OVERFLOW, token1); *ret=FPP_WORK_AREA_OVERFLOW; return(FALSE); } sprintf(global->work, "%s%s", token1, global->tokenbuf); break; case DIG: /* A number */ case DOT: /* Or maybe a float */ strcpy(global->work, token1); global->workp = global->work + strlen(global->work); *ret=scannumber(global, c, save); if(*ret) return(FALSE); *ret=save(global, EOS); if(*ret) return(FALSE); break; default: /* An error, ... */ if (isprint(c)) cerror(global, ERROR_STRANG_CHARACTER, c); else cerror(global, ERROR_STRANG_CHARACTER2, c); strcpy(global->work, token1); unget(global); break; } /* * work has the concatenated token and token1 has * the first token (no longer needed). Unget the * new (concatenated) token after freeing token1. * Finally, setup to read the new token. */ Freemem(token1); /* Free up memory */ *ret=ungetstring(global, global->work); /* Unget the new thing, */ if(*ret) return(FALSE); return(TRUE); }#else return(FALSE); /* Not supported */#endif}ReturnCode scanstring(struct Global *global, int delim, /* ' or " */ /* Output function: */ ReturnCode (*outfun)(struct Global *, int)){ /* * Scan off a string. Warning if terminated by newline or EOF. * outfun() outputs the character -- to a buffer if in a macro. * TRUE if ok, FALSE if error. */ int c; ReturnCode ret; global->instring = TRUE; /* Don't strip comments */ ret=(*outfun)(global, delim); if(ret) return(ret); while ((c = get(global)) != delim && c != '\n' && c != EOF_CHAR) { ret=(*outfun)(global, c); if(ret) return(ret); if (c == '\\') { ret=(*outfun)(global, get(global)); if(ret) return(ret); } } global->instring = FALSE; if (c == delim) { ret=(*outfun)(global, c); return(ret); } else { cerror(global, ERROR_UNTERMINATED_STRING); unget(global); return(FPP_UNTERMINATED_STRING); }}ReturnCode scannumber(struct Global *global, int c, /* First char of number */ /* Output/store func: */ ReturnCode (*outfun)(struct Global *, int)){ /* * Process a number. We know that c is from 0 to 9 or dot. * Algorithm from Dave Conroy's Decus C. */ int radix; /* 8, 10, or 16 */ int expseen; /* 'e' seen in floater */ int signseen; /* '+' or '-' seen */ int octal89; /* For bad octal test */ int dotflag; /* TRUE if '.' was seen */ ReturnCode ret; char done=FALSE; expseen = FALSE; /* No exponent seen yet */ signseen = TRUE; /* No +/- allowed yet */ octal89 = FALSE; /* No bad octal yet */ radix = 10; /* Assume decimal */ if ((dotflag = (c == '.')) != FALSE) {/* . something? */ ret=(*outfun)(global, '.'); /* Always out the dot */ if(ret) return(ret); if (type[(c = get(global))] != DIG) { /* If not a float numb, */ unget(global); /* Rescan strange char */ return(FPP_OK); /* All done for now */ } } /* End of float test */ else if (c == '0') { /* Octal or hex? */ ret=(*outfun)(global, c); /* Stuff initial zero */ if(ret) return(ret); radix = 8; /* Assume it's octal */ c = get(global); /* Look for an 'x' */ if (c == 'x' || c == 'X') { /* Did we get one? */ radix = 16; /* Remember new radix */ ret=(*outfun)(global, c); /* Stuff the 'x' */ if(ret) return(ret); c = get(global); /* Get next character */ }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?