⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpp4.c

📁 类PASCAL语言的编译器,LINUX环境的,我没试过是否正确.
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifdef RCSstatic char rcsid[]="$Id: cpp4.c,v 1.3 1994/06/02 08:50:52 start Exp $";#endif/****************************************************************************** *                               FREXXWARE * ---------------------------------------------------------------------------- * * Project: Frexx C Preprocessor * $Source: /home/user/start/cpp/RCS/cpp4.c,v $ * $Revision: 1.3 $ * $Date: 1994/06/02 08:50:52 $ * $Author: start $ * $State: Exp $ * $Locker:  $ * * ---------------------------------------------------------------------------- * $Log: cpp4.c,v $ * Revision 1.3  1994/06/02  08:50:52  start * Changed a few things to make the initial function routine to run * * Revision 1.2  1994/01/24  09:34:03  start * Made a bunch of functions FILE_LOCAL and INLINE. * * Revision 1.1  1993/11/03  09:13:08  start * Initial revision * * *****************************************************************************//* *			    C P P 4 . C *		M a c r o  D e f i n i t i o n s * * Edit History * 31-Aug-84	MM	USENET net.sources release * 04-Oct-84	MM	__LINE__ and __FILE__ must call ungetstring() *			so they work correctly with token concatenation. *			Added string formal recognition. * 25-Oct-84	MM	"Short-circuit" evaluate #if's so that we *			don't print unnecessary error messages for *			#if !defined(FOO) && FOO != 0 && 10 / FOO ... * 31-Oct-84	ado/MM	Added token concatenation *  6-Nov-84	MM	Split off eval stuff * 21-Oct-85	RMS	Rename `token' to `tokenbuf'. *			In doundef, don't complain if arg already not defined. * 14-Mar-86	FNF	Incorporate macro based C debugging package. *			Port to Commodore AMIGA. * 21-Aug-88	Ois	Changed concatenation operator to ##. Changed hand- *			ling of tokens following ##. Added new meaning of #. */#include	<stdio.h>#include	<ctype.h>#include	"cppdef.h"#include	"cpp.h"INLINE FILE_LOCAL ReturnCode checkparm(struct Global *, int, DEFBUF *, int);INLINE FILE_LOCAL ReturnCode stparmscan(struct Global *, int);INLINE FILE_LOCAL ReturnCode textput(struct Global *, char *);FILE_LOCAL ReturnCode charput(struct Global *, int);INLINE FILE_LOCAL ReturnCode expcollect(struct Global *);INLINE FILE_LOCAL char *doquoting(char *, char *);ReturnCode dodefine(struct Global *global){  /*   * Called from control when a #define is scanned.  This module   * parses formal parameters and the replacement string.  When   * the formal parameter name is encountered in the replacement   * string, it is replaced by a character in the range 128 to   * 128+NPARAM (this allows up to 32 parameters within the   * Dec Multinational range).  If cpp is ported to an EBCDIC   * machine, you will have to make other arrangements.   *   * There is some special case code to distinguish   *	#define foo	bar   * from #define foo()   bar   *   * Also, we make sure that   *	#define foo	foo   * expands to "foo" but doesn't put cpp into an infinite loop.   *   * A warning message is printed if you redefine a symbol to a   * different text.  I.e,   *	#define foo	123   *	#define foo	123   * is ok, but   *	#define foo	123   *	#define foo	+123   * is not.   *   * The following subroutines are called from define():   * checkparm	called when a token is scanned.  It checks through the   *		array of formal parameters.  If a match is found, the   *		token is replaced by a control byte which will be used   *		to locate the parameter when the macro is expanded.   * textput	puts a string in the macro work area (parm[]), updating   *		parmp to point to the first free byte in parm[].   *		textput() tests for work buffer overflow.   * charput	puts a single character in the macro work area (parm[])   *		in a manner analogous to textput().   */  int c;  DEFBUF *dp;	/* -> new definition	*/  int isredefine;	/* TRUE if redefined	*/  char *old;		/* Remember redefined	*/  ReturnCode ret;#if OK_CONCAT  int quoting;	/* Remember we saw a #	*/#endif    if (type[(c = skipws(global))] != LET) {    cerror(global, ERROR_DEFINE_SYNTAX);    global->inmacro = FALSE;		/* Stop <newline> hack	*/    return(FPP_OK);  }  isredefine = FALSE;			/* Set if redefining	*/  if ((dp = lookid(global, c)) == NULL) { /* If not known now     */    dp = defendel(global, global->tokenbuf, FALSE); /* Save the name  */    if(!dp)      return(FPP_OUT_OF_MEMORY);  } else {				/* It's known:          */    isredefine = TRUE;			/* Remember this fact	*/    old = dp->repl;			/* Remember replacement */    dp->repl = NULL;			/* No replacement now	*/  }  global->parlist[0] = global->parmp = global->parm; /* Setup parm buffer */  if ((c = get(global)) == '(') {       /* With arguments?      */    global->nargs = 0;			/* Init formals counter */    do {				/* Collect formal parms */      if (global->nargs >= LASTPARM) {	cfatal(global, FATAL_TOO_MANY_ARGUMENTS_MACRO);	return(FPP_TOO_MANY_ARGUMENTS);      } else if ((c = skipws(global)) == ')')	break;			/* Got them all 	*/      else if (type[c] != LET) {         /* Bad formal syntax    */	cerror(global, ERROR_DEFINE_SYNTAX);	global->inmacro = FALSE;		/* Stop <newline> hack	*/	return(FPP_OK);      }      scanid(global, c);                        /* Get the formal param */      global->parlist[global->nargs++] = global->parmp; /* Save its start */      ret=textput(global, global->tokenbuf); /* Save text in parm[]  */      if(ret)	return(ret);    } while ((c = skipws(global)) == ',');    /* Get another argument */    if (c != ')') {                     /* Must end at )        */      cerror(global, ERROR_DEFINE_SYNTAX);      global->inmacro = FALSE;		/* Stop <newline> hack	*/      return(FPP_OK);    }    c = ' ';                            /* Will skip to body    */  }  else {    /*     * DEF_NOARGS is needed to distinguish between     * "#define foo" and "#define foo()".     */    global->nargs = DEF_NOARGS;		/* No () parameters     */  }  if (type[c] == SPA)                   /* At whitespace?       */    c = skipws(global);                 /* Not any more.        */  global->workp = global->work;		/* Replacement put here */  global->inmacro = TRUE;		/* Keep \<newline> now	*/  quoting = 0;				/* No # seen yet.	*/  while (c != EOF_CHAR && c != '\n') {  /* Compile macro body   */#if OK_CONCAT    if (c == '#') {                     /* Token concatenation? */      if ((c = get(global)) != '#') {   /* No, not really       */	quoting = 1;		        /* Maybe quoting op.	*/	continue;      }      while (global->workp > global->work && type[global->workp[-1]] == SPA)	--global->workp;		/* Erase leading spaces */      if(ret=save(global, TOK_SEP))     /* Stuff a delimiter    */	return(ret);      c = skipws(global);               /* Eat whitespace       */      continue;    }#endif    switch (type[c]) {    case LET:#if OK_CONCAT      ret=checkparm(global, c, dp, quoting);      /* Might be a formal    */#else      ret=checkparm(c, dp);               /* Might be a formal    */#endif      if(ret)	return(ret);      break;	    case DIG:				/* Number in mac. body	*/    case DOT:				/* Maybe a float number */      ret=scannumber(global, c, save);  /* Scan it off          */      if(ret)	return(ret);      break;	    case QUO:				/* String in mac. body	*/      ret=stparmscan(global, c);      if(ret)	return(ret);      break;	    case BSH:				/* Backslash		*/      ret=save(global, '\\');      if(ret)	return(ret);      if ((c = get(global)) == '\n')	global->wrongline = TRUE;      ret=save(global, c);      if(ret)	return(ret);      break;          case SPA:				/* Absorb whitespace	*/      /*       * Note: the "end of comment" marker is passed on       * to allow comments to separate tokens.       */      if (global->workp[-1] == ' ')   /* Absorb multiple      */	break;			/* spaces		*/      else if (c == '\t')	c = ' ';                      /* Normalize tabs       */      /* Fall through to store character			*/    default:				/* Other character	*/      ret=save(global, c);      if(ret)	return(ret);      break;    }    c = get(global);    quoting = 0;			/* Only when immediately*/    /* preceding a formal	*/  }  global->inmacro = FALSE;		/* Stop newline hack	*/  unget(global);                            /* For control check    */  if (global->workp > global->work && global->workp[-1] == ' ') /* Drop trailing blank  */    global->workp--;  *global->workp = EOS;		/* Terminate work	*/  dp->repl = savestring(global, global->work); /* Save the string      */  dp->nargs = global->nargs;			/* Save arg count	*/  if (isredefine) {                   /* Error if redefined   */    if ((old != NULL && dp->repl != NULL && !streq(old, dp->repl))	|| (old == NULL && dp->repl != NULL)	|| (old != NULL && dp->repl == NULL)) {      cerror(global, ERROR_REDEFINE, dp->name);    }    if (old != NULL)                  /* We don't need the    */      Freemem(old);                   /* old definition now.  */  }  return(FPP_OK);}INLINE FILE_LOCALReturnCode checkparm(struct Global *global,		     int c,		     DEFBUF *dp,		     int quoting)	/* Preceded by a # ?	*/{  /*   * Replace this param if it's defined.  Note that the macro name is a   * possible replacement token. We stuff DEF_MAGIC in front of the token   * which is treated as a LETTER by the token scanner and eaten by   * the output routine. This prevents the macro expander from   * looping if someone writes "#define foo foo".   */    int i;  char *cp;  ReturnCode ret=FPP_OK;        scanid(global, c);                /* Get parm to tokenbuf */  for (i = 0; i < global->nargs; i++) {     /* For each argument    */    if (streq(global->parlist[i], global->tokenbuf)) {  /* If it's known */#if OK_CONCAT      if (quoting) {                    /* Special handling of  */	ret=save(global, QUOTE_PARM);     /* #formal inside defn  */	if(ret)	  return(ret);      }#endif      ret=save(global, i + MAC_PARM);     /* Save a magic cookie  */      return(ret);		      /* And exit the search	*/    }  }  if (streq(dp->name, global->tokenbuf))    /* Macro name in body?  */    ret=save(global, DEF_MAGIC);            /* Save magic marker    */  for (cp = global->tokenbuf; *cp != EOS;)  /* And save             */    ret=save(global, *cp++);                /* The token itself     */  return(ret);}INLINE FILE_LOCALReturnCode stparmscan(struct Global *global, int delim){  /*   * Normal string parameter scan.   */    unsigned char	*wp;  int i;  ReturnCode ret;        wp = (unsigned char *)global->workp;	/* Here's where it starts       */  ret=scanstring(global, delim, save);  if(ret)    return(ret);		/* Exit on scanstring error	*/  global->workp[-1] = EOS;		/* Erase trailing quote 	*/  wp++;				/* -> first string content byte */  for (i = 0; i < global->nargs; i++) {    if (streq(global->parlist[i], (char *)wp)) {      *wp++ = MAC_PARM + PAR_MAC;	/* Stuff a magic marker */      *wp++ = (i + MAC_PARM);         /* Make a formal marker */      *wp = wp[-3];			/* Add on closing quote */      global->workp = (char *)wp + 1; 	/* Reset string end	*/      return(FPP_OK);    }  }  global->workp[-1] = wp[-1];	/* Nope, reset end quote.	*/  return(FPP_OK);}  void doundef(struct Global *global)  /*   * Remove the symbol from the defined list.   * Called from the #control processor.   */{  int c;  if (type[(c = skipws(global))] != LET)    cerror(global, ERROR_ILLEGAL_UNDEF);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -