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 + -
显示快捷键?