📄 preproc.c
字号:
/* preproc.c * * (C) Copyright Apr 15 1995, Edmond J. Breen. * ALL RIGHTS RESERVED. * This code may be copied for personal, non-profit use only. * * Developed initially from * p -- Small-C preprocessor by A.T. Schreiner 6/83. * DDJ #93 (July) 1984. * * However, many changes have been implemented and * extensions made. * * Grammar * #define identifier token-sequence * #define identifier(arg-list) token-sequence * #undef identifier * #include <file-name> * #include "file-name" * #include token-sequence * #if constant-expr * #elif constant-expr * #ifdef identifier * #ifndef identifier * #else * #endif * #error token-sequence # #pragma token-sequence # #pragma * * The defined operator can be used in #if and #elif * expressions only: * #if defined(_EiC) && !defined(UNIX) * ... * #elif defined(MSDOS) * ... * #endif * * token-sequence: * [token-sequence] #token [token-sequence] * [token-sequence] token##token [token-sequence] * token-sequence token * * arg-list: * identifier [,identifier]* * * Predefined Macros: * * __LINE__ The line number of the current source program, expressed * as an integer. * __FILE__ The name of the current source file, expressed as a * string. * __DATE__ resolves to a string literal containing the calender * date in the form: Mmm dd yyyy. * __TIME__ resolves to a string literal containing the current time * in the form hh:mm:ss. * __STDC__ resolves to 1. * */#include <stdio.h>#include <ctype.h>#include <string.h>#include <stdlib.h>#ifndef WIN32#include <unistd.h>#endif#include <fcntl.h>#include <time.h>#include <sys/types.h>#ifndef WIN32#include <unistd.h>#endif#include <stddef.h>#include <stdarg.h>#include "stab.h"#include "error.h"#include "func.h"#ifdef PPCLIBint _stsptr,persist;char *startstr;char *ppcgets(char *str);#endif#ifdef _STANDALONE#include "preproc.h"int EiC_verboseON=1;int showON = 1;#define xmalloc(x) malloc(x)#define xcalloc(x,y) calloc(x,y)#define xrealloc(x,y) realloc(x,y)#define xfree(x) free(x)#define xmark(x,y)union VaL { char cval; /* char value */ int ival; /* integer value */ char *cpval; void *pval;};typedef union VaL val_t;typedef struct { int n; val_t * val;}eicstack_t;typedef struct { char *id; int token;} keyword_t;#include "preexpr.c"#elsestatic int showON = 0;#include "global.h"#include "xalloc.h"#include "preproc.h"#include "symbol.h"#endif/* TODO: constant from eicmod.c needs header */extern int EiC_showIncludes;fitem_t *EiC_Infile = NULL;int EiC_ptrSafe = 1;static int file_cnt = 0;static stab_t FileNames = {NULL,0};#define crt_fitem() (fitem_t*)calloc(sizeof(fitem_t),1)#define free_fitem(x) free(x)#define STRINGID -2int EiC_IsIncluded(char *fname){ return EiC_stab_FindString(&FileNames,fname) >= 0;}void EiC_showIncludedFiles(void){ EiC_stab_ShowStrings(&FileNames);}void EiC_rmIncludeFileName(char *fname){ EiC_stab_RemoveString(&FileNames,fname);}#if 0/* this is the start of getting the :clear * command to recursively remove the contents * of an include file */typedef struct nameTab { char * fname; char * inc; struct nameTab *nxt;};static struct nameTab *incTab = NULL;static void EiC_addIncAssoc(char *fname, char *inc){ struct nameTab *new = xcalloc(sizeof(new), 1); new->fname = fname; new->inc = inc; new->nxt = incTab; incTab = new;}#endifstatic void NewInfile(int fd, char * fname, char *filep){ fitem_t * f = crt_fitem(); f->fd = fd; f->fname = EiC_stab_SaveString(&FileNames,fname); f->next = EiC_Infile; EiC_Infile = f; if(EiC_showIncludes) { int k = file_cnt; while(--k) fputs(" ",stdout); if((filep && !*filep) || !filep) filep = fname; fprintf(stdout,"%d:%s\n",file_cnt,filep); } file_cnt++;}static void NextInfile(){ if(EiC_Infile->next) { fitem_t * h = EiC_Infile->next; if(EiC_Infile->fd != STRINGID) { close(EiC_Infile->fd); if(EiC_Infile->buf) free(EiC_Infile->buf); } free(EiC_Infile); EiC_Infile = h; file_cnt--; }} static eicstack_t macros = {0, NULL};#define Item(stack,i,item) ((stack)->val[i].item) #define STDIN 0#define STDOUT 1#define STDERR 2typedef struct { char * line; char * lp; unsigned len;}Line;static size_t NINCLUDES = 0;static char **Include_prefixes = NULL;static char *empty_string = " ";typedef struct { char *id; /* token name */ char *tok_seq; /* token replacement sequence */ int nparms; /* number of parameters */ char *protect; /* if one then no expansion before replacement for a given parameter*/ long unsigned hcode; /* `id' string hash code */ char *fname; /* file name pointer */} macro_t;static macro_t defmacro = {NULL, NULL, 0, NULL};static int skip = 0;char cmode;static int linelen, olinelen, iflevel =0;static char *line = NULL, *lp, *oline = NULL, *olp;enum { DEFAULT, DEFINE, ELIF, ELSE, ENDIF, IF, IFDEF, IFNDEF, INCLUDE, UNDEF, ERROR, PRAGMA};static keyword_t pwords[] ={{"define", DEFINE,},{"elif", ELIF,},{"else", ELSE,},{"endif",ENDIF,},{"error", ERROR,},{"if", IF,}, {"ifdef", IFDEF,},{"ifndef",IFNDEF,},{"include",INCLUDE,},{"pragma", PRAGMA,},{"undef", UNDEF,}, };/** PROTOTYPES from preproc.c **/static int Rgetc();static void rebuff(char **buf, int *len);static void in(char c);static char *out(char c);static char *outChar(char *s, char c, int mod, int i);static int getline();static void expr_list(eicstack_t *parms, char **p,int more);static int findparm(eicstack_t *parms,char *name, size_t len);static void mergeTokens(macro_t *mac);static void parameterise(eicstack_t *parms);static void markmacro(macro_t * mac, char mark);static void kill_Items(eicstack_t *parms);static void freemacro(macro_t * mac);static void remmacroid(int k);static void newmacro(eicstack_t *parms);static void dodefmacro(char *s);static int control_line(void);static char * stringise(char * seq);static char * EiC_expand(char *fld,char **end, int bot, int top);static void process(void);/* TODO: extern from eicmod.c needs header */extern int EiC_verboseON;static unsigned long get_hcode(unsigned char *s){ unsigned long t, h,i; h = 0; while(*s) { for(t = i=0;*s && i<32;i+=8) t |= (*s++ << i); h += t; } return h;} /*CUT preprocerror.cut*/extern void EiC_pre_error(char *msg, ...){ char *buff1, *buff2; va_list args; va_start(args,msg); buff1 = malloc(strlen(msg) + 256); buff2 = malloc(strlen(msg) + 512); EiC_errs++; EiC_ParseError = 1; sprintf(buff1,"Error in %s near line %d: %s\n", CurrentFileName(), CurrentLineNo(), msg); vsprintf(buff2,buff1,args); EiC_messageDisplay(buff2); free(buff1); free(buff2); va_end(args);} /*END CUT*/static size_t ninclude = 0;static size_t bot_stab = 0;size_t EiC_pp_NextEntryNum(void){ ninclude = NINCLUDES; bot_stab = EiC_stab_NextEntryNum(&FileNames); return macros.n;}size_t EiC_get_EiC_PP_NINCLUDES(void){ return NINCLUDES;}size_t EiC_get_EiC_bot_stab(void) {return EiC_stab_NextEntryNum(&FileNames);}void EiC_set_EiC_PPtoStart(int bot_stab, int ninclude){ NINCLUDES = ninclude; FileNames.n = bot_stab;}void EiC_pp_CleanUp(size_t bot){ iflevel = 0; skip = 0; /* clean up macros */ while(macros.n > bot) remmacroid(macros.n-1); /* close opened files */ while(EiC_Infile->next) NextInfile(); /* clean up path inclusion */ while(NINCLUDES > ninclude) EiC_removepath(Include_prefixes[NINCLUDES - 1]); /* remove included file names */ EiC_stab_CleanUp(&FileNames,bot_stab);}static unsigned putback = 0;#define Ugetc(x) (putback = x)#define BUFSIZE 512#if 1static void doPragma(char *s){ static char * Stack = NULL; static int N = 0; if(strstr(s,"push_safeptr")) { Stack = realloc(Stack,++N); Stack[N-1] = EiC_ptrSafe = 1; } else if(strstr(s,"push_unsafeptr")) { Stack = realloc(Stack,++N); Stack[N-1] = EiC_ptrSafe = 0; } else if(strstr(s,"pop_ptr") ) { if(N-2 >= 0) { N--; EiC_ptrSafe = Stack[N-1]; } else EiC_ptrSafe = 1; } else EiC_formatMessage("Warning: Unrecognised pragma (%s): %s line %d\n", s,EiC_Infile->fname, EiC_Infile->lineno);}#endif#if defined(_STANDALONE)#define gchar(fd,c) (c = (read(fd,&c,1) > 0)? c : EOF)static int rline(int fd, char *s, int limit){ int c =0, i; limit--; for(i=0;i<limit && gchar(fd,c) != EOF && c != '\n';i++) s[i] = c; if(c == '\n') s[i++] = c; s[i] = '\0'; return i;}static int Rgetc(){ int c; static int lastln = 0; if(putback) { c = putback; putback = 0; } else { if(EiC_Infile->n <= 0) { if(showON && lastln && !skip && EiC_Infile->buf) fputs(EiC_Infile->buf,stdout); EiC_Infile->n = 0; if(EiC_Infile->buf == NULL) EiC_Infile->buf = (char *)malloc(BUFSIZE+1); EiC_Infile->n = rline(EiC_Infile->fd, EiC_Infile->buf, BUFSIZE); EiC_Infile->bufp = EiC_Infile->buf; if(showON) { lastln = 0; if(!skip) fprintf(stdout,"%s",EiC_Infile->buf); else { lastln = 1; putchar('\n'); } } } c = ((EiC_Infile->n-- > 0) ? *EiC_Infile->bufp++ : EOF); } return c;}#else/* TODO: global from starteic.c needs header */extern int EiC_Interact;static int Rgetc(){ static char prompt[20]; unsigned char * EiC_readline(char *); void EiC_add_history(unsigned char *); int c; #ifdef PPCLIB void prs(char *str); static char getsbuf[120]; #endif#ifdef WIN32#define SBUFSIZE 120 static char getsbuf[SBUFSIZE];#endif if(putback) { c = putback; putback = 0; } else { if(EiC_Infile->n <= 0) { if(EiC_Infile->fd != STDIN || !EiC_Interact) { if(EiC_Infile->buf == NULL) EiC_Infile->buf = malloc(BUFSIZE+1); if(EiC_Infile->fd != STRINGID) EiC_Infile->n = read(EiC_Infile->fd, EiC_Infile->buf,BUFSIZE); } else { #ifdef NO_READLINE fflush(stdout); fflush(stderr); sprintf(prompt,"\nEiC %d> ",EiC_Infile->lineno+1); #ifdef PPCLIB prs(prompt); if(_stsptr!=-1) { EiC_Infile->buf=startstr; _stsptr=-1; } else #endif EiC_Infile->buf = ppcgets(getsbuf); if(EiC_Infile->buf && *EiC_Infile->buf) { EiC_Infile->n = strlen(EiC_Infile->buf); EiC_Infile->buf[EiC_Infile->n] = '\n'; EiC_Infile->n++; } else EiC_Infile->n = 0; #else if(EiC_Infile->buf) { free(EiC_Infile->buf); EiC_Infile->buf = NULL; } sprintf(prompt,"EiC %d> ",EiC_Infile->lineno+1); EiC_Infile->buf = EiC_readline(prompt); if(EiC_Infile->buf && *EiC_Infile->buf) { EiC_add_history(EiC_Infile->buf); EiC_Infile->n = strlen((char*)EiC_Infile->buf); EiC_Infile->buf[EiC_Infile->n] = '\n'; EiC_Infile->n++; } else EiC_Infile->n = 0; #endif } EiC_Infile->bufp = EiC_Infile->buf; } c = ((EiC_Infile->n-- > 0) ? *EiC_Infile->bufp++ : EOF); } return c;}#endif /* _STANDALONE */char *EiC_prolineString(char *str){ NewInfile(STRINGID,"STRING","::EiC::"); EiC_Infile->n = strlen(str); EiC_Infile->buf=EiC_Infile->bufp=(unsigned char*)str; return str;}static void rebuff(char **buf, int *len){ *buf = (char *) realloc(*buf, (*len + REBUFF_INCREMENT) * sizeof(char)); *len += REBUFF_INCREMENT;}static void in(char c){ *lp++ = c; if (lp >= line + linelen) { ptrdiff_t d; d = lp - line; rebuff(&line, &linelen); lp = line + (size_t) d; }}static char *out(char c){ *olp++ = c; if (olp >= oline + olinelen) { ptrdiff_t d; d = olp - oline; rebuff(&oline, &olinelen); olp = oline + (size_t) d; } *olp = '\0'; return olp - 1;}static char *outChar(char *s, char c, int mod, int i){ if(!(i%mod)) { if(!s) s = (char *)xmalloc(sizeof(char)*(i+mod + 1)); else s = (char *)xrealloc(s,sizeof(char)*(i+mod + 1)); } s[i] = c; return s;}#ifdef _STANDALONE#define EiC_saveComment() NULL#endifstatic int getline(){ /* automatically strips out comments and * performs line splicing. */ char c; int lcom = 0; lp = line; while(1) { switch ((c = Rgetc())) { case '\\': /* look for line continuation */ switch ((c = Rgetc())) { case EOF: EiC_pre_error("Unexpected end of file"); case '\n': ++EiC_Infile->lineno; continue; case '\r': /* ignore carriage returns */ if((c = Rgetc()) == '\n') { ++EiC_Infile->lineno; continue; } } in('\\'); default: if(!isspace(c) || lp != line) /* skip leading white */ in(c); /* space */ continue; case EOF: if(iflevel && file_cnt == 2) EiC_pre_error("unterminated `#if' conditional"); ++EiC_Infile->lineno;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -