+++ /dev/null
-/* 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 PPCLIB
-int _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"
-
-#else
-static 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 -2
-
-
-int 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;
-}
-
-
-#endif
-
-static 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 2
-
-typedef 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 1
-
-static 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
-#endif
-
-static 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;
- if (lp != line)
- break;
- if (EiC_Infile->next) {
- NextInfile();
- if(EiC_Infile->next)
- continue;
- }else if(!EiC_Interact) {
- int EiC_exit_EiC();
- EiC_exit_EiC();
- }
-
- break;
- case '/':
- if (cmode == 0) { /* check for comment*/
- if((c = Rgetc()) == '*' || c == '/') {
- int i = 0;
- void (*sC) (char *s);
- char *comment = NULL;
-
- if(c == '/') /* Allow for C++ style comments */
- lcom = 1;
- /* strip comment out */
- c = Rgetc();
- sC = EiC_saveComment();
- if(lp != line)
- in(' '); /* replace comment with space */
- while(c != EOF) {
- if(sC)
- comment = outChar(comment,c,5,i++);
- if(c == '\n') {
- if(lcom == 1) {
- Ugetc(c);
- lcom = 0;
- break;
- } else
- ++EiC_Infile->lineno;
- }
- if(c == '*' && !lcom) {
- if((c = Rgetc()) == '/')
- break;
- } else if (c == '\\' && lcom) {
- /* allow for line splicing */
- c = Rgetc(); /* waste next char */
- if(c=='\r')
- c=Rgetc();
- c = Rgetc();
- } else
- c = Rgetc();
- }
- if(sC) {
- comment = outChar(comment,'\0',5,i++);
- sC(comment);
- }
-
- } else {
- in('/');
- if(c == '\n')
- ++EiC_Infile->lineno;
- if(c != EOF)
- in(c);
- }
- } else
- in('/');
- continue;
- case '\"': /* " */
- if (cmode == 0)
- cmode = CMstr;
- else if (cmode == CMstr)
- cmode = 0;
- in('\"'); /* " */
- continue;
- case '\'':
- if (cmode == 0)
- cmode = CMchr;
- else if (cmode == CMchr)
- cmode = 0;
- in('\'');
- continue;
- case '\r': /* ignore carriage returns */
- continue;
- case '\n':
- ++EiC_Infile->lineno;
- if(lp == line && EiC_Infile->next ) {
- continue;
- }
- if (cmode == CMstr) {
- if (!skip)
- EiC_pre_error("unbalanced \""); /* " */
- else
- in('\"'); /* " */
- cmode = 0;
- } else if (cmode == CMchr) {
- if (!skip)
- EiC_pre_error("unbalanced \'");
- else
- in('\'');
- cmode = 0;
- }
- }
- break;
- }
- *lp = '\0';
-
- return 1;
-}
-
-static void expr_list(eicstack_t *parms, char **p,int more)
-{
- extern char *EiC_strsave(char *);
- int c = 0, b = 0;
-
- char *s = *p;
- static unsigned sz =BUFSIZE;
- static char *str = NULL;
-
- val_t v;
- if(!str)
- str = (char*)malloc(BUFSIZE);
- while (1) {
- for (; *s; ++s) {
- if(isspace(*s) && !cmode) {
- while(*s && isspace(*s)) s++;
- if(!*s)
- break;
- s--;
- }
- if(c == sz) {
- sz += BUFSIZE;
- str = realloc(str,sz);
- }
- str[c++] = *s;
- switch (*s) {
- case '\\':
- str[c++] = *++s; /*get next char */
- continue;
- case '{': case '(':
- if (cmode == 0) ++b;
- continue;
- case ',':
- if (cmode || b) continue;
- --c;
- break;
- case '}': case ')':
- if(b) {b--;continue;}
- if (cmode) continue;
- --c;
- break;
- case '\'':
- switch (cmode) {
- case 0: cmode = CMchr;
- case CMstr: continue;
- }
- cmode = 0;
- continue;
- case '\"': /* " */
- switch (cmode) {
- case 0: cmode = CMstr;
- case CMchr: continue;
- }
- cmode = 0;
- continue;
- default: continue;
- } /* end switch */
- break;
- } /* end for loop */
-
- if(!b && *s) {
- str[c] = '\0';
- /*strip leading white space */
- c = 0;
- while(str[c] && isspace(str[c]))
- c++;
- v.p.p = EiC_strsave(&str[c]);
- EiC_eicpush(parms, v);
- }
- if(!*s && more) { /*need more input*/
- if(EiC_Infile->fd == STDIN) {
- EiC_pre_error("Illegal line continuation during macro expansion");
- break;
- }
- getline();
- if(c && !isspace(str[c-1]) && !isspace(*line))
- str[c++] = ' '; /* need white space */
- s = line;
- continue;
- }
-
- if (*s == ')')
- break;
- if (*s != ',') {
- EiC_pre_error("Illegal macro definition");
- break;
- }
- c = 0;
- s++;
- } /* end while */
- *p = ++s;
- if(sz > BUFSIZE << 2) {
- sz = BUFSIZE;
- str = realloc(str,sz);
- }
-
-}
-
-static int findparm(eicstack_t *parms,char *name, size_t len)
-{
- int i;
- val_t *v;
- for (v = parms->val, i = 1; i <= parms->n; i++, v++)
- if (strncmp(v->p.p, name, len) == 0)
- return i;
- return 0;
-}
-
-static void mergeTokens(macro_t *mac)
-{
- char * s, *seq;
- int left, right;
-
- if(mac->nparms) {
- mac->protect = xcalloc(mac->nparms + 1,sizeof(char));
- /*printf("%s id %ld\n",mac->id,tot_seen);*/
- }
-
- s = seq = mac->tok_seq;
- while(*s) {
- if(!cmode && *s == '#' && *(s+1) == '#') {
- int d = (int)(s - seq) - 1;
- while(d >= 0 && seq[d] > 0 && isspace(seq[d]))
- d--;
- if(d < 0)
- EiC_pre_error("macro definition begins with ##");
- left = d;
- d = (int)(s - seq) + 2;
- while(seq[d] > 0 && isspace(seq[d]))
- d++;
- if(!seq[d])
- EiC_pre_error("macro definition ends with ##");
- right = d;
- s = seq + left + 1;
-
-
- if(seq[left] < 0)
- mac->protect[-seq[left]] = 1;
- if(seq[right] < 0)
- mac->protect[-seq[right]] = 1;
-
- while(seq[left] != 0)
- seq[++left] = seq[right++];
- } else if (*s == '"') {
- if (!cmode)
- cmode = CMstr;
- else if (cmode == CMstr)
- cmode = 0;
- } else if (*s == '\'') {
- if (!cmode)
- cmode = CMchr;
- else if (cmode == CMchr)
- cmode = 0;
- }
- s++;
- }
-}
-
-static void parameterise(eicstack_t *parms)
-{
- char *s, *id, *op;
- int i;
-
- cmode = 0;
-
- op = s = defmacro.tok_seq;
-
- while (*s) {
- if (!cmode && (isalpha(*s) || *s == '_')) {
- id = s++;
- while (isalnum(*s) || *s == '_')
- ++s;
- if ((i = findparm(parms, id, (size_t) (s - id))) != 0)
- *op++ = -i;
- else
- while (id < s)
- *op++ = *id++;
- } else {
- if (*s == '"') {
- if (!cmode)
- cmode = CMstr;
- else if (cmode == CMstr)
- cmode = 0;
- } else if (*s == '\'') {
- if (!cmode)
- cmode = CMchr;
- else if (cmode == CMchr)
- cmode = 0;
- } else if (isspace(*s) && !cmode) {
- do
- s++;
- while(*s && isspace(*s));
- *--s = ' ';
- }
- *op++ = *s++;
- }
- }
- *op = '\0';
- if (cmode) {
- if (cmode == CMstr)
- EiC_pre_error("Missing end \" in macro token sequence");
- else
- EiC_pre_error("Missing end ' in macro token sequence");
- } else
- mergeTokens(&defmacro);
-}
-
-#ifndef _STANDALONE
-static void markmacro(macro_t * mac, char mark)
-{
- xmark(mac, mark);
- xmark(mac->id, mark);
- if(mac->protect)
- xmark(mac->protect,mark);
- if(mac->tok_seq != empty_string)
- xmark(mac->tok_seq, mark);
- EiC_stab_Mark(&FileNames,mark);
-}
-
-void EiC_markmacros(char mark)
-{
- macro_t *mac;
- val_t *v;
- int i;
-
- if (macros.n) {
- xmark(macros.val, mark);
- v = macros.val;
- for (i = 0; i < macros.n; ++i, ++v) {
- mac = v->p.p;
- markmacro(mac, mark);
- }
- }
-
- for(i=0;i<NINCLUDES;++i)
- xmark(Include_prefixes[i],mark);
-}
-#endif
-
-static void Check4Res(macro_t * mac)
-{
- char str[20];
- char * itoa(int,char *s, int);
- int c = 0, q = 1;
- char * s = NULL;
- if(mac->id[0] == '_' && mac->id[1] == '_') {
- switch(mac->id[2]) {
- case 'F':
- if(strcmp(mac->id,"__FILE__") == 0) {
- c = 1; s = EiC_Infile->fname;
- if(strcmp(s,mac->tok_seq) == 0)
- return;
- }
- break;
- case 'L':
- if(strcmp(mac->id,"__LINE__")== 0) {
- sprintf(str,"%d",EiC_Infile->lineno);
- s = str;
- c = 1;
- q = 0;
- }
- break;
- case 'D':
- case 'T':
- if(strcmp(mac->id,"__DATE__") == 0 ||
- strcmp(mac->id,"__TIME__") == 0) {
- time_t t = time(NULL);
- char * ct = ctime(&t);
- c = 1; s = str;
- if(mac->id[2] == 'D') {
- strncpy(str, ct+4, 7);
- strncpy(&str[7], ct+20, 4);
- str[11] = 0;
- } else {
- strncpy(str, ct+11, 8);
- str[8] = 0;
- }
- }
- break;
-/* case 'S':
- if(strcmp(mac->id,"__STDC__")== 0) {
- str[0] = '1'; str[1] = 0;
- s = str;
- c = 1;
- }
- break;
-*/
- }
- if(c && s) {
- char * p;
- xfree(mac->tok_seq);
- p = mac->tok_seq = (char*)xmalloc(strlen(s) + 3);
- xmark(mac->tok_seq,eicstay);
- if(q)
- *p++ = '\"';
- while(*s)
- *p++ = *s++;
- if(q)
- *p++ ='\"';
- *p='\0';
- }
-
- }
-}
-
-static void displayMacro(int k, char *id)
-{
- macro_t *mac = macros.val[k].p.p;
- char *s = mac->tok_seq;
- int c,p;
- printf("%s -> #define %s",id,id);
- if(mac->nparms) {
- putchar('(');
- for(p = 0;*s != 0;++s)
- if(*s < p)
- p = *s;
- s = mac->tok_seq;
- p = abs(p);
- for(k=0; k<p;++k) {
- c = 'a'+k;
- putchar(c);
- if(k+1 < mac->nparms)
- putchar(',');
- }
- putchar(')');
- }
- putchar('\t');
- for(k = 0;*s != 0;++s,++k)
- if(*s < 0) {
- if(k)
- if(*(s-1) > EOF && isalnum(*(s-1)))
- printf(" ## ");
- c = 'a' - *s - 1;
- putchar(c);
- if(*(s+1) && (*(s+1) < 0 || isalnum(*(s+1))))
- printf(" ## ");
- } else
- putchar(*s);
-
- putchar('\n');
-}
-
-int EiC_showMacro(char * id)
-{
- int k;
- if((k = EiC_ismacroid(id)) >= 0) {
- displayMacro(k,id);
- return 1;
- }
-
- return 0;
-}
-
-void EiC_showFileMacros(char *fname)
-{
- macro_t *mac;
- val_t *v;
- int i;
- v = macros.val;
- for (i = 0; i < macros.n; ++i, ++v) {
- mac = v->p.p;
- if (strcmp(mac->fname, fname) == 0)
- displayMacro(i,mac->id);
- }
-}
-
-
-void EiC_ClearFileMacros(char *fname)
-{
- /* clear all the macros from the macro lut
- * that were entered via file `fname'
- */
- macro_t *mac;
- val_t *v;
- int i, *ind = NULL, cnt = 0;
-
- v = macros.val;
- for (i = 0; i < macros.n; ++i, ++v) {
- mac = v->p.p;
- if (strcmp(mac->fname, fname) == 0) {
- if(cnt)
- ind = xrealloc(ind,sizeof(int) * (cnt + 1));
- else
- ind = xmalloc(sizeof(int));
- ind[cnt++] = i;
- }
- }
- for(i = cnt; i>0;i--)
- remmacroid(ind[i-1]);
- if(ind)
- xfree(ind);
-}
-
-int EiC_ismacroid(char *id)
-{
- unsigned long hc;
- macro_t *mac;
- val_t *v;
- int i;
- v = macros.val;
- hc = get_hcode((unsigned char *)id);
- for (i = 0; i < macros.n; ++i, ++v) {
- mac = v->p.p;
- if (hc == mac->hcode && strcmp(mac->id, id) == 0) {
- Check4Res(mac);
- return i;
- }
- }
- return -1;
-}
-
-static void kill_Items(eicstack_t *parms)
-{
- if (parms->n) {
- int i;
- for (i = 0; i < parms->n; i++)
- xfree(parms->val[i].p.p);
- xfree(parms->val);
- parms->n = 0;
- }
- parms->val = NULL;
-}
-
-static void freemacro(macro_t * mac)
-{
- if (mac->id) {
- xfree(mac->id);
- mac->id = NULL;
- }
- if (mac->tok_seq) {
- if(mac->tok_seq != empty_string)
- xfree(mac->tok_seq);
- mac->tok_seq = NULL;
- }
- if(mac->protect)
- xfree(mac->protect);
-}
-
-static void remmacroid(int k)
-{
- val_t v;
- macro_t *mac;
-
- mac = macros.val[k].p.p;
- freemacro(mac);
- if(macros.n) {
- if(k < macros.n-1) {
- memmove(¯os.val[k],
- ¯os.val[k + 1],
- ((macros.n-1) - k) * sizeof(val_t));
- }
- /* Throw away last item on stack*/
- EiC_eicpop(¯os,&v);
- }
- xfree(mac);
-}
-
-
-static void newmacro(eicstack_t *parms)
-{
-
- macro_t *new;
- int k;
- k = EiC_ismacroid(defmacro.id);
- if (k > -1) {
- macro_t *old;
- old = macros.val[k].p.p;
- if ((old->nparms != parms->n) ||
- !((old->tok_seq == empty_string && !*defmacro.tok_seq) ||
- strcmp(old->tok_seq, defmacro.tok_seq) == 0)) {
- EiC_pre_error("Re-declaration of macro %s",defmacro.id);
- }
- if(defmacro.protect)
- xfree(defmacro.protect);
- } else {
- val_t v;
- new = (macro_t *) xcalloc(1, sizeof(macro_t));
- defmacro.id = EiC_strsave(defmacro.id);
- defmacro.hcode = get_hcode((unsigned char *)defmacro.id);
- defmacro.fname = CurrentFileName();
- if(*defmacro.tok_seq)
- defmacro.tok_seq = EiC_strsave(defmacro.tok_seq);
- else /* allow for empty macro */
- defmacro.tok_seq = empty_string;
- defmacro.nparms = parms->n;
- *new = defmacro;
- v.p.p = new;
- EiC_eicpush(¯os, v);
- }
- defmacro.protect = defmacro.id = defmacro.tok_seq = NULL;
-}
-
-extern void dodefine(char *def)
-{
- /*
- * for processing -Dname[=value] switch
- * def = name[=value]
- */
- if(def) {
- char * p;
- int i = strlen(def);
- char * str = xmalloc(i+3);
- memcpy(str,def,i+1);
- for(p = str;*p && *p != '=';++p)
- ;
- if(*p) {
- *p = ' ';
- str[i] = 0;
- }else {
- str[i] = ' ';
- str[i+1] = '1';
- str[i+2] = 0;
- }
- dodefmacro(str);
- xfree(str);
- }
-}
-
-static void dodefmacro(char *s)
-{
- eicstack_t parms = {0, NULL};
- skipfws(s);
- defmacro.id = s;
- while (*s && !isspace(*s) && *s != '(')
- ++s;
- if (*s == '(') {
- *s++ = '\0';
- expr_list(&parms,&s,0);
- } else
- if(*s)
- *s++ = '\0';
- skipfws(s);
- defmacro.tok_seq = s;
- defmacro.nparms = parms.n;
- skipall(s);
- --s;
- skipbws(s);
- *++s = '\0';
- if (parms.n != 0)
- parameterise(&parms);
- newmacro(&parms);
- kill_Items(&parms);
-}
-
-int EiC_Include_file(char *e, /* name of file to Include for */
- int mode) /* if 1, look locally first */
-{ /* returns 1 on success else it returns 0 */
-
- int i,fd;
- char fname[512] = {0};
- if(mode == 1) /* look in current directory first */
- fd = open(e,O_RDONLY);
- else
- fd = -1;
- for(i=0;i<NINCLUDES && fd < 0;i++) {
- strcpy(fname,Include_prefixes[i]);
- strcat(fname,"/");
- strcat(fname,e);
- if(EiC_verboseON)
- printf("looking for %s:%d\n",fname,file_cnt);
- fd = open(fname, O_RDONLY);
- }
- if (fd >= 0)
- NewInfile(fd,e,fname);
- else
- return 0;
- return fd;
-}
-
-static int control_line(void)
-{
- char key[25];
- int k;
- char *s, *e;
- if (*line == '#') {
- s = line + 1;
-
- skipfws(s);
-
- if(!*s) /* test for null directive */
- return 1;
-
- for(k=0;isalpha(*s);k++)
- key[k] = *s++;
-
- key[k] = '\0';
- k = EiC_iskeyword(pwords, key, sizeof(pwords)
- / sizeof(keyword_t));
- skipfws(s);
- switch (k) {
- case DEFINE:
- if (!skip) {
- if(*s)
- dodefmacro(s);
- else
- EiC_pre_error("empty '#define' directive");
- }
- break;
- case ELIF:
- if(skip && skip == iflevel) {
- if(EiC_cpp_parse(s))
- skip = 0;
- } else if(!skip && iflevel)
- skip = iflevel + 1;
- break;
- case ELSE:
- if (iflevel == 0)
- EiC_pre_error("Unmatched #else");
- else if (skip == iflevel)
- skip = 0;
- else if (skip == 0)
- skip = iflevel;
- break;
- case ENDIF:
- if (iflevel == 0)
- EiC_pre_error("Unmatched #endif");
- else {
- if (skip >= iflevel)
- skip = 0;
- --iflevel;
- }
- break;
- case IF:
- ++iflevel;
- if(!skip) {
- if(*s) {
- if(!EiC_cpp_parse(s))
- skip = iflevel;
- } else
- EiC_pre_error("empty '#if' directive");
- }
- break;
- case IFDEF:
- case IFNDEF:
- ++iflevel;
- if (!skip) {
- if (isalpha(*s) || *s == '_') {
- e = s;
- skipnws(s);
- *s = '\0';
- if (EiC_ismacroid(e) > -1) {
- if (k == IFNDEF)
-
- skip = iflevel;
- } else if (k == IFDEF)
- skip = iflevel;
- } else
- EiC_pre_error("Illegal macro identifier");
- }
- break;
- case INCLUDE:
- {
- if(skip) break;
- if(!*s) {
- EiC_pre_error("empty '#include' directive");
- break;
- }
- if (*s == '\"') /* " */
- s++, cmode = CMstr;
- else if (*s == '<')
- s++, cmode = CMang;
- else
- cmode = 0;
- e = s;
- skipnws(s);
- if (cmode) {
- if (cmode == CMstr && *(s - 1) != '\"')
- EiC_pre_error("Missing \"");
- else if (cmode == CMang && *(s - 1) != '>')
- EiC_pre_error("Missing >");
- *--s = '\0';
- } else { /* token_sequence */
- lp = line;
- while (e != s)
- *lp++ = *e++;
- *lp = '\0';
- process();
- e = oline;
- }
-
- if(!EiC_Include_file(e,(cmode != CMang)))
- EiC_pre_error("failed to open include file %s",e);
- cmode = 0;
- }
- case UNDEF:
- if (!skip) {
- e = s;
- skipnws(s);
- *s = '\0';
- k = EiC_ismacroid(e);
- if (k > -1)
- remmacroid(k);
- }
- break;
- case ERROR:
- if(!skip) {
- char *S = EiC_process2(s,0,0);
- EiC_pre_error(S);
- if(S)
- xfree(S);
- }
- break;
- case PRAGMA:
- if(!skip) {
- char *S = EiC_process2(s,0,0);
- if(S) {
- doPragma(S);
- xfree(S);
- }
- }
-
- break;
- default: {
- extern int ScriptMode;
- if(!ScriptMode)
- EiC_pre_error("undefined or invalid # directive");
- }
- break;
- }
- return 1;
- }
- return skip;
-}
-
-#define TopMax 256
-#define MoD 10
-static int forbid[TopMax];
-
-static char * stringise(char * seq)
-{
- int i = 0;
- char *S=NULL;
-
- S = outChar(S,'\"',MoD,i++); /* " */
- while(*seq) {
- if(*seq == '\"' || *seq == '\\') /* " */
- S = outChar(S,'\\',MoD,i++);
- S = outChar(S,*seq++,MoD,i++);
- }
- S = outChar(S,'\"',MoD,i++); /* " */
- S[i]='\0';
- return S;
-}
-
-static char * EiC_expand(char *fld,char **end, int bot, int top)
-{
- char word[128];
- int i = 0, k;
- char *p, *p2;
- macro_t *mac;
- char *S =NULL;
- eicstack_t parms = {0, NULL};
-
- for(i=0;*fld && (isalnum(*fld) || *fld == '_');++i)
- word[i] = *fld++;
- word[i]=0;
-
- if(end)
- *end = fld;
- if ((k = EiC_ismacroid(word)) < 0)
- return NULL;
- for(i=bot;i<top;i++)
- if(k == forbid[i])
- return NULL;
- forbid[top++] = k;
- skipfws(fld);
- mac = macros.val[k].p.p;
- if (mac->nparms > 0) {
- if (*fld != '(')
- return NULL; /**/
- else { /* collect arguments */
- ++fld;
- expr_list(&parms,&fld,1);
- }
- if(end)
- *end = fld;
- }
- if (parms.n != mac->nparms)
- EiC_pre_error("Macro syntax error");
- else {
- char * t, *s;
- p = mac->tok_seq;
- /* Now substitute in arguments and
- * expand as necessary
- */
- i = 0; S = NULL;
- while (*p) {
- if (*p < 0) {
- if(mac->protect && mac->protect[-*p] == 1)
- p2 = NULL;
- else if((i && S[i-1] == '#') || (i >= 2 && S[i-2] == '#')) {
- p2 = stringise(Item(&parms,-*p - 1,p.p));
- if(S[i-1] == '#')
- i--;
- else
- i -= 2;
- } else
- p2 = EiC_process2(Item(&parms,-*p-1,p.p),top,top);
- if(p2) {
- char *p = p2;
- while (*p2)
- S = outChar(S,*p2++,MoD,i++);
- xfree(p);
- } else {
- p2 = Item(&parms,-*p - 1,p.p);
- while (*p2)
- S = outChar(S,*p2++,MoD,i++);
- }
- p++;
- } else
- S = outChar(S,*p++,MoD,i++);
-
- }
- if(S) { /* Now rescan macro definition */
- char *S2=NULL;
- int k = 0;
- if(mac->nparms > 0)
- do {
- /* catch possible new macro funcs */
- /* bit of hack, but seems to work */
- /* should really check also for */
- /* brackets in strings and char literals */
- while(*fld && isspace(*fld))
- fld++;
- while(*fld == '(') {
- int parens = 0;
- do {
- S = outChar(S,*fld,MoD,i++);
- if(*fld == '(')
- parens++;
- else if(*fld == ')')
- parens--;
- if(! *++fld && parens) {
- /* need more input */
- if(EiC_Infile->fd == STDIN) {
- EiC_pre_error("Illegal line continuation "
- "during macro expansion");
- break;
- }
- getline();
- fld = line;
- }
- } while(*fld && parens);
- if(parens)
- EiC_pre_error("Missing `)'");
- *end = fld;
- }
- } while(isspace(*fld));
-
- s = S;
- S[i] = 0;
- while(*s) {
- if (*s == '"') {
- if (!cmode)
- cmode = CMstr;
- else if (cmode == CMstr)
- cmode = 0;
- } else if (*s == '\'') {
- if (!cmode)
- cmode = CMchr;
- else if (cmode == CMchr)
- cmode = 0;
- } else if(*s == '\\')
- S2 = outChar(S2,*s++,MoD,k++);
- else if((isalpha(*s) || *s == '_') && !cmode) {
- t = EiC_expand(s,&p,bot,top);
- if(t) {
- char * h = t;
- while(*t)
- S2 = outChar(S2,*t++,MoD,k++);
- xfree(h);
- s = p;
- } else
- while(s < p)
- S2 = outChar(S2,*s++,MoD,k++);
- continue;
- }
- S2 = outChar(S2,*s++,MoD,k++);
- }
- S2[k] = 0;
- xfree(S);
- S = S2;
- }
- }
- kill_Items(&parms);
- return S;
-}
-
-
-char * EiC_process2(char * line,int bot,int top)
-{
- int k = 0;
- char *p, *s, *S = NULL;
- char * lp = line;
-
- while (*lp)
- if (!cmode && (isalpha(*lp) || *lp == '_')) {
- s = lp;
- p = EiC_expand(lp, &lp,bot,top);
- if(p) {
- s = p;
- while(*p)
- S = outChar(S,*p++,MoD,k++);
- xfree(s);
- } else
- while(s != lp)
- S = outChar(S,*s++,MoD,k++);
- } else {
- if(*lp == '\'') {
- if (cmode == 0)
- cmode = CMchr;
- else if (cmode == CMchr)
- cmode = 0;
- }
- if (*lp == '\"') { /* " */
- if (cmode == 0)
- cmode = CMstr;
- else if(cmode == CMstr)
- cmode = 0;
- } else if (*lp == '\\' && (cmode == CMstr || cmode == CMchr) ) {
- S = outChar(S,*lp++,MoD,k++);
- if (!*lp) /* get second char */
- break;
- }
- S = outChar(S,*lp++,MoD,k++);
- }
- if(S)
- S[k] = '\0';
- return S;
-}
-
-static void cp2out(char *S)
-{
- if(S) {
- while(*S)
- out(*S++);
- }
-}
-
-static void process(void)
-{
- char *S;
- *(olp = oline) = '\0';
- S = EiC_process2(line,0,0);
- if(S) {
- cp2out(S);
- xfree(S);
- }
- cmode = 0;
-}
-
-int EiC_setinfile(char * fname)
-{
- /* look in current directory */
- char name[100] = {0,};
- int fd = open(fname,O_RDONLY);
-
- if(fd < 0) {
- sprintf(name,"%s/%s",getenv("HOME"),fname);
- fd = open(name,O_RDONLY);
- if(fd < 0) {
- /* look in search path include directories */
- fd = EiC_Include_file(fname,0);
- return fd;
- }
- }
- if(fd > 0)
- NewInfile(fd,fname,name);
- return fd;
-}
-
-extern char *EiC_nextproline(void)
-{
- extern int EiC_SHOWLINE;
-
- while (1) {
- getline();
- if(line[0] != ':') {
- if (!control_line()) {
- process();
- break;
- } else if (EiC_Infile->fd == STDIN) {
- olp = oline;
- break;
- }
- } else if(!skip) { /* else got an EiC command line */
- *(olp = oline) = '\0';
- cp2out(line);
- break;
- }
- }
- if (EiC_Infile->fd == STDIN)
- out(EOF);
- if (EiC_SHOWLINE && !showON) {
- out('\0');
- fputs(oline,stdout);
- fputc('\n',stdout);
- }
- return oline;
-}
-
-int EiC_insertpath(char *path)
-{
- /* Adds path to include path list */
-
- int i;
- /*
- * don't append the same path more than once
- */
- for(i=0;i<NINCLUDES;++i)
- if(strcmp(path,Include_prefixes[i]) == 0)
- return 1;
- Include_prefixes = realloc(Include_prefixes,
- sizeof(char*)*(NINCLUDES+1));
- Include_prefixes[NINCLUDES] = EiC_strsave(path);
- if(!Include_prefixes[NINCLUDES])
- return 0;
- NINCLUDES++;
- return 1;
-
-}
-
-int EiC_removepath(char *path)
-{
- int i,k;
- for(i=0;i<NINCLUDES;++i)
- if(Include_prefixes[i] &&
- strcmp(path,Include_prefixes[i])==0) {
- xfree(Include_prefixes[i]);
- for(k=i;k<NINCLUDES-1;k++)
- Include_prefixes[k] = Include_prefixes[k+1];
- NINCLUDES--;
- return 1;
- }
- return 0;
-}
-
-void EiC_listpath(void)
-{
- int i;
- for(i=0;i<NINCLUDES;++i)
- printf("%s\n",Include_prefixes[i]);
-}
-
-int EiC_initpp(void)
-{
- static int ftime = 1;
- NewInfile(STDIN,"::EiC::","::EiC::");
- if (line)
- free(line);
- if (oline)
- free(oline);
- line = (char *) calloc(REBUFF_INCREMENT, sizeof(char));
- oline = (char *) calloc(REBUFF_INCREMENT, sizeof(char));
- linelen = olinelen = REBUFF_INCREMENT;
- if (!line || !oline)
- return 0;
- if(ftime) {
- dodefine("__FILE__=emp");
- dodefine("__LINE__=emp");
- dodefine("__DATE__=emp");
- dodefine("__TIME__=emp");
- dodefine("__STDC__=1");
- ftime = 0;
- }
- return 1;
-}
-
-#ifdef _STANDALONE
-
-/* TODO: eicmod.c global needs header */
-extern int EiC_showIncludes = 0;
-
-static int EiC_iskeyword(keyword_t *keywords,char*id,int n)
-{
- int i;
- for(i=0;i<n;i++)
- if(strcmp(keywords[i].id,id) == 0)
- return keywords[i].token;
- return 0;
-}
-
-static void EiC_eicpush(eicstack_t *s, val_t v)
-{
- if(!(s->n%2)) {
- if(!s->n)
- s->val = (val_t*)xcalloc(sizeof(val_t),2);
- else
- s->val = (val_t*)xrealloc(s->val,(s->n+2)*sizeof(val_t));
- }
- s->val[s->n] = v;
- s->n++;
-}
-
-static int EiC_eicpop(eicstack_t *s, val_t *pop)
-{
- if(s->n == 0)
- return 0;
- s->n--;
- *pop = s->val[s->n];
- if(!(s->n%2)) {
- if(!s->n)
- xfree(s->val);
- else
- s->val = (val_t*)xrealloc(s->val,s->n*sizeof(val_t));
- }
- return 1;
-}
-
-static extern char * EiC_strsave(char *s)
-{
- char *p;
- if((p = (char*)xcalloc(strlen(s)+1,sizeof(char))) != NULL)
- strcpy(p,s);
- return(p);
-}
-
-/* TODO: eicmod.c global needs header */
-int EiC_SHOWLINE = 1;
-
-static int do_sw_commands(char *cp)
-{
- switch(*cp++) {
- case 'D': dodefine(cp); return 1;
- case 'I': EiC_insertpath(cp);return 1;
- case '\?':
- case 'r':
- case 'R': EiC_setinfile(cp); return 1;
- case 's':
- case 'S': EiC_verboseON = 0; return 1;
- default:
- return 0;
- }
-}
-
-void main(int argc, char ** argv)
-{
- char *buf;
- EiC_initpp();
- if(argc > 1)
- while(argv[1]) {
- if(argv[1][0] == '-') {
- if(!do_sw_commands(&argv[1][1])) {
- fprintf(stderr,"Unknown switch command [%s]\n",argv[1]);
- exit(0);
- }
- } else {
- fprintf(stderr,"Unknown switch command [%s]\n",argv[1]);
- exit(0);
- }
- argv++;
- }
- if(EiC_Infile->fd == STDIN) {
- fputs("testpp> ",stdout);
- fflush(stdout);
- }
- do {
- buf = EiC_nextproline();
- while(*buf && *buf != EOF)
- buf++;
- }while(*buf != EOF);
-}
-
-#endif
-
-
-
-
-
-
-
-
-
-
-
-
-