3 * (C) Copyright Apr 15 1995, Edmond J. Breen.
5 * This code may be copied for personal, non-profit use only.
7 * Developed initially from
8 * p -- Small-C preprocessor by A.T. Schreiner 6/83.
11 * However, many changes have been implemented and
15 * #define identifier token-sequence
16 * #define identifier(arg-list) token-sequence
18 * #include <file-name>
19 * #include "file-name"
20 * #include token-sequence
27 * #error token-sequence
28 # #pragma token-sequence
31 * The defined operator can be used in #if and #elif
33 * #if defined(_EiC) && !defined(UNIX)
35 * #elif defined(MSDOS)
40 * [token-sequence] #token [token-sequence]
41 * [token-sequence] token##token [token-sequence]
42 * token-sequence token
45 * identifier [,identifier]*
49 * __LINE__ The line number of the current source program, expressed
51 * __FILE__ The name of the current source file, expressed as a
53 * __DATE__ resolves to a string literal containing the calender
54 * date in the form: Mmm dd yyyy.
55 * __TIME__ resolves to a string literal containing the current time
56 * in the form hh:mm:ss.
57 * __STDC__ resolves to 1.
72 #include <sys/types.h>
86 char *ppcgets(char *str);
97 #define xmalloc(x) malloc(x)
98 #define xcalloc(x,y) calloc(x,y)
99 #define xrealloc(x,y) realloc(x,y)
100 #define xfree(x) free(x)
105 char cval; /* char value */
106 int ival; /* integer value */
110 typedef union VaL val_t;
125 static int showON = 0;
134 /* TODO: constant from eicmod.c needs header */
135 extern int EiC_showIncludes;
137 fitem_t *EiC_Infile = NULL;
140 static int file_cnt = 0;
141 static stab_t FileNames = {NULL,0};
142 #define crt_fitem() (fitem_t*)calloc(sizeof(fitem_t),1)
143 #define free_fitem(x) free(x)
148 int EiC_IsIncluded(char *fname)
150 return EiC_stab_FindString(&FileNames,fname) >= 0;
153 void EiC_showIncludedFiles(void)
155 EiC_stab_ShowStrings(&FileNames);
158 void EiC_rmIncludeFileName(char *fname)
160 EiC_stab_RemoveString(&FileNames,fname);
164 /* this is the start of getting the :clear
165 * command to recursively remove the contents
169 typedef struct nameTab {
175 static struct nameTab *incTab = NULL;
177 static void EiC_addIncAssoc(char *fname, char *inc)
179 struct nameTab *new = xcalloc(sizeof(new), 1);
191 static void NewInfile(int fd, char * fname, char *filep)
193 fitem_t * f = crt_fitem();
195 f->fname = EiC_stab_SaveString(&FileNames,fname);
196 f->next = EiC_Infile;
198 if(EiC_showIncludes) {
202 if((filep && !*filep) || !filep)
204 fprintf(stdout,"%d:%s\n",file_cnt,filep);
210 static void NextInfile()
212 if(EiC_Infile->next) {
213 fitem_t * h = EiC_Infile->next;
214 if(EiC_Infile->fd != STRINGID) {
215 close(EiC_Infile->fd);
217 free(EiC_Infile->buf);
225 static eicstack_t macros = {0, NULL};
228 #define Item(stack,i,item) ((stack)->val[i].item)
241 static size_t NINCLUDES = 0;
242 static char **Include_prefixes = NULL;
243 static char *empty_string = " ";
246 char *id; /* token name */
247 char *tok_seq; /* token replacement sequence */
248 int nparms; /* number of parameters */
249 char *protect; /* if one then no expansion before
250 replacement for a given parameter*/
251 long unsigned hcode; /* `id' string hash code */
252 char *fname; /* file name pointer */
255 static macro_t defmacro = {NULL, NULL, 0, NULL};
262 static int linelen, olinelen, iflevel =0;
263 static char *line = NULL, *lp, *oline = NULL, *olp;
268 IF, IFDEF, IFNDEF, INCLUDE,
272 static keyword_t pwords[] =
282 {"include",INCLUDE,},
288 /** PROTOTYPES from preproc.c **/
291 static void rebuff(char **buf, int *len);
292 static void in(char c);
293 static char *out(char c);
294 static char *outChar(char *s, char c, int mod, int i);
295 static int getline();
296 static void expr_list(eicstack_t *parms, char **p,int more);
297 static int findparm(eicstack_t *parms,char *name, size_t len);
298 static void mergeTokens(macro_t *mac);
299 static void parameterise(eicstack_t *parms);
300 static void markmacro(macro_t * mac, char mark);
301 static void kill_Items(eicstack_t *parms);
302 static void freemacro(macro_t * mac);
303 static void remmacroid(int k);
304 static void newmacro(eicstack_t *parms);
305 static void dodefmacro(char *s);
306 static int control_line(void);
307 static char * stringise(char * seq);
308 static char * EiC_expand(char *fld,char **end, int bot, int top);
309 static void process(void);
311 /* TODO: extern from eicmod.c needs header */
312 extern int EiC_verboseON;
315 static unsigned long get_hcode(unsigned char *s)
317 unsigned long t, h,i;
320 for(t = i=0;*s && i<32;i+=8)
327 /*CUT preprocerror.cut*/
328 extern void EiC_pre_error(char *msg, ...)
335 buff1 = malloc(strlen(msg) + 256);
336 buff2 = malloc(strlen(msg) + 512);
340 sprintf(buff1,"Error in %s near line %d: %s\n",
344 vsprintf(buff2,buff1,args);
345 EiC_messageDisplay(buff2);
353 static size_t ninclude = 0;
354 static size_t bot_stab = 0;
356 size_t EiC_pp_NextEntryNum(void)
358 ninclude = NINCLUDES;
359 bot_stab = EiC_stab_NextEntryNum(&FileNames);
363 size_t EiC_get_EiC_PP_NINCLUDES(void){ return NINCLUDES;}
364 size_t EiC_get_EiC_bot_stab(void) {return EiC_stab_NextEntryNum(&FileNames);}
366 void EiC_set_EiC_PPtoStart(int bot_stab, int ninclude)
368 NINCLUDES = ninclude;
369 FileNames.n = bot_stab;
372 void EiC_pp_CleanUp(size_t bot)
376 /* clean up macros */
377 while(macros.n > bot)
378 remmacroid(macros.n-1);
379 /* close opened files */
380 while(EiC_Infile->next)
383 /* clean up path inclusion */
384 while(NINCLUDES > ninclude)
385 EiC_removepath(Include_prefixes[NINCLUDES - 1]);
386 /* remove included file names */
387 EiC_stab_CleanUp(&FileNames,bot_stab);
391 static unsigned putback = 0;
392 #define Ugetc(x) (putback = x)
398 static void doPragma(char *s)
400 static char * Stack = NULL;
404 if(strstr(s,"push_safeptr")) {
405 Stack = realloc(Stack,++N);
406 Stack[N-1] = EiC_ptrSafe = 1;
407 } else if(strstr(s,"push_unsafeptr")) {
408 Stack = realloc(Stack,++N);
409 Stack[N-1] = EiC_ptrSafe = 0;
410 } else if(strstr(s,"pop_ptr") ) {
413 EiC_ptrSafe = Stack[N-1];
417 EiC_formatMessage("Warning: Unrecognised pragma (%s): %s line %d\n",
418 s,EiC_Infile->fname, EiC_Infile->lineno);
423 #if defined(_STANDALONE)
425 #define gchar(fd,c) (c = (read(fd,&c,1) > 0)? c : EOF)
427 static int rline(int fd, char *s, int limit)
431 for(i=0;i<limit && gchar(fd,c) != EOF && c != '\n';i++)
442 static int lastln = 0;
448 if(EiC_Infile->n <= 0) {
449 if(showON && lastln && !skip && EiC_Infile->buf)
450 fputs(EiC_Infile->buf,stdout);
452 if(EiC_Infile->buf == NULL)
453 EiC_Infile->buf = (char *)malloc(BUFSIZE+1);
454 EiC_Infile->n = rline(EiC_Infile->fd,
457 EiC_Infile->bufp = EiC_Infile->buf;
461 fprintf(stdout,"%s",EiC_Infile->buf);
468 c = ((EiC_Infile->n-- > 0) ? *EiC_Infile->bufp++ : EOF);
475 /* TODO: global from starteic.c needs header */
476 extern int EiC_Interact;
481 static char prompt[20];
482 unsigned char * EiC_readline(char *);
483 void EiC_add_history(unsigned char *);
487 static char getsbuf[120];
491 static char getsbuf[SBUFSIZE];
499 if(EiC_Infile->n <= 0) {
500 if(EiC_Infile->fd != STDIN || !EiC_Interact) {
501 if(EiC_Infile->buf == NULL)
502 EiC_Infile->buf = malloc(BUFSIZE+1);
503 if(EiC_Infile->fd != STRINGID)
504 EiC_Infile->n = read(EiC_Infile->fd,
505 EiC_Infile->buf,BUFSIZE);
511 sprintf(prompt,"\nEiC %d> ",EiC_Infile->lineno+1);
517 EiC_Infile->buf=startstr;
522 EiC_Infile->buf = ppcgets(getsbuf);
523 if(EiC_Infile->buf && *EiC_Infile->buf) {
524 EiC_Infile->n = strlen(EiC_Infile->buf);
525 EiC_Infile->buf[EiC_Infile->n] = '\n';
532 if(EiC_Infile->buf) {
533 free(EiC_Infile->buf);
534 EiC_Infile->buf = NULL;
537 sprintf(prompt,"EiC %d> ",EiC_Infile->lineno+1);
538 EiC_Infile->buf = EiC_readline(prompt);
539 if(EiC_Infile->buf && *EiC_Infile->buf) {
540 EiC_add_history(EiC_Infile->buf);
541 EiC_Infile->n = strlen((char*)EiC_Infile->buf);
542 EiC_Infile->buf[EiC_Infile->n] = '\n';
548 EiC_Infile->bufp = EiC_Infile->buf;
550 c = ((EiC_Infile->n-- > 0) ? *EiC_Infile->bufp++ : EOF);
554 #endif /* _STANDALONE */
556 char *EiC_prolineString(char *str)
558 NewInfile(STRINGID,"STRING","::EiC::");
559 EiC_Infile->n = strlen(str);
560 EiC_Infile->buf=EiC_Infile->bufp=(unsigned char*)str;
564 static void rebuff(char **buf, int *len)
566 *buf = (char *) realloc(*buf, (*len + REBUFF_INCREMENT) * sizeof(char));
567 *len += REBUFF_INCREMENT;
570 static void in(char c)
573 if (lp >= line + linelen) {
576 rebuff(&line, &linelen);
577 lp = line + (size_t) d;
581 static char *out(char c)
584 if (olp >= oline + olinelen) {
587 rebuff(&oline, &olinelen);
588 olp = oline + (size_t) d;
594 static char *outChar(char *s, char c, int mod, int i)
598 s = (char *)xmalloc(sizeof(char)*(i+mod + 1));
600 s = (char *)xrealloc(s,sizeof(char)*(i+mod + 1));
607 #define EiC_saveComment() NULL
612 /* automatically strips out comments and
613 * performs line splicing.
620 switch ((c = Rgetc())) {
621 case '\\': /* look for line continuation */
622 switch ((c = Rgetc())) {
624 EiC_pre_error("Unexpected end of file");
626 ++EiC_Infile->lineno;
628 case '\r': /* ignore carriage returns */
629 if((c = Rgetc()) == '\n') {
630 ++EiC_Infile->lineno;
637 if(!isspace(c) || lp != line) /* skip leading white */
641 if(iflevel && file_cnt == 2)
642 EiC_pre_error("unterminated `#if' conditional");
643 ++EiC_Infile->lineno;
646 if (EiC_Infile->next) {
650 }else if(!EiC_Interact) {
657 if (cmode == 0) { /* check for comment*/
658 if((c = Rgetc()) == '*' || c == '/') {
660 void (*sC) (char *s);
661 char *comment = NULL;
663 if(c == '/') /* Allow for C++ style comments */
665 /* strip comment out */
667 sC = EiC_saveComment();
669 in(' '); /* replace comment with space */
672 comment = outChar(comment,c,5,i++);
679 ++EiC_Infile->lineno;
681 if(c == '*' && !lcom) {
682 if((c = Rgetc()) == '/')
684 } else if (c == '\\' && lcom) {
685 /* allow for line splicing */
686 c = Rgetc(); /* waste next char */
694 comment = outChar(comment,'\0',5,i++);
701 ++EiC_Infile->lineno;
711 else if (cmode == CMstr)
718 else if (cmode == CMchr)
722 case '\r': /* ignore carriage returns */
725 ++EiC_Infile->lineno;
726 if(lp == line && EiC_Infile->next ) {
729 if (cmode == CMstr) {
731 EiC_pre_error("unbalanced \""); /* " */
735 } else if (cmode == CMchr) {
737 EiC_pre_error("unbalanced \'");
750 static void expr_list(eicstack_t *parms, char **p,int more)
752 extern char *EiC_strsave(char *);
756 static unsigned sz =BUFSIZE;
757 static char *str = NULL;
761 str = (char*)malloc(BUFSIZE);
764 if(isspace(*s) && !cmode) {
765 while(*s && isspace(*s)) s++;
772 str = realloc(str,sz);
777 str[c++] = *++s; /*get next char */
783 if (cmode || b) continue;
787 if(b) {b--;continue;}
793 case 0: cmode = CMchr;
794 case CMstr: continue;
800 case 0: cmode = CMstr;
801 case CMchr: continue;
812 /*strip leading white space */
814 while(str[c] && isspace(str[c]))
816 v.p.p = EiC_strsave(&str[c]);
817 EiC_eicpush(parms, v);
819 if(!*s && more) { /*need more input*/
820 if(EiC_Infile->fd == STDIN) {
821 EiC_pre_error("Illegal line continuation during macro expansion");
825 if(c && !isspace(str[c-1]) && !isspace(*line))
826 str[c++] = ' '; /* need white space */
834 EiC_pre_error("Illegal macro definition");
841 if(sz > BUFSIZE << 2) {
843 str = realloc(str,sz);
848 static int findparm(eicstack_t *parms,char *name, size_t len)
852 for (v = parms->val, i = 1; i <= parms->n; i++, v++)
853 if (strncmp(v->p.p, name, len) == 0)
858 static void mergeTokens(macro_t *mac)
864 mac->protect = xcalloc(mac->nparms + 1,sizeof(char));
865 /*printf("%s id %ld\n",mac->id,tot_seen);*/
868 s = seq = mac->tok_seq;
870 if(!cmode && *s == '#' && *(s+1) == '#') {
871 int d = (int)(s - seq) - 1;
872 while(d >= 0 && seq[d] > 0 && isspace(seq[d]))
875 EiC_pre_error("macro definition begins with ##");
877 d = (int)(s - seq) + 2;
878 while(seq[d] > 0 && isspace(seq[d]))
881 EiC_pre_error("macro definition ends with ##");
887 mac->protect[-seq[left]] = 1;
889 mac->protect[-seq[right]] = 1;
891 while(seq[left] != 0)
892 seq[++left] = seq[right++];
893 } else if (*s == '"') {
896 else if (cmode == CMstr)
898 } else if (*s == '\'') {
901 else if (cmode == CMchr)
908 static void parameterise(eicstack_t *parms)
915 op = s = defmacro.tok_seq;
918 if (!cmode && (isalpha(*s) || *s == '_')) {
920 while (isalnum(*s) || *s == '_')
922 if ((i = findparm(parms, id, (size_t) (s - id))) != 0)
931 else if (cmode == CMstr)
933 } else if (*s == '\'') {
936 else if (cmode == CMchr)
938 } else if (isspace(*s) && !cmode) {
941 while(*s && isspace(*s));
950 EiC_pre_error("Missing end \" in macro token sequence");
952 EiC_pre_error("Missing end ' in macro token sequence");
954 mergeTokens(&defmacro);
958 static void markmacro(macro_t * mac, char mark)
961 xmark(mac->id, mark);
963 xmark(mac->protect,mark);
964 if(mac->tok_seq != empty_string)
965 xmark(mac->tok_seq, mark);
966 EiC_stab_Mark(&FileNames,mark);
969 void EiC_markmacros(char mark)
976 xmark(macros.val, mark);
978 for (i = 0; i < macros.n; ++i, ++v) {
980 markmacro(mac, mark);
984 for(i=0;i<NINCLUDES;++i)
985 xmark(Include_prefixes[i],mark);
989 static void Check4Res(macro_t * mac)
992 char * itoa(int,char *s, int);
995 if(mac->id[0] == '_' && mac->id[1] == '_') {
998 if(strcmp(mac->id,"__FILE__") == 0) {
999 c = 1; s = EiC_Infile->fname;
1000 if(strcmp(s,mac->tok_seq) == 0)
1005 if(strcmp(mac->id,"__LINE__")== 0) {
1006 sprintf(str,"%d",EiC_Infile->lineno);
1014 if(strcmp(mac->id,"__DATE__") == 0 ||
1015 strcmp(mac->id,"__TIME__") == 0) {
1016 time_t t = time(NULL);
1017 char * ct = ctime(&t);
1019 if(mac->id[2] == 'D') {
1020 strncpy(str, ct+4, 7);
1021 strncpy(&str[7], ct+20, 4);
1024 strncpy(str, ct+11, 8);
1030 if(strcmp(mac->id,"__STDC__")== 0) {
1031 str[0] = '1'; str[1] = 0;
1040 xfree(mac->tok_seq);
1041 p = mac->tok_seq = (char*)xmalloc(strlen(s) + 3);
1042 xmark(mac->tok_seq,eicstay);
1055 static void displayMacro(int k, char *id)
1057 macro_t *mac = macros.val[k].p.p;
1058 char *s = mac->tok_seq;
1060 printf("%s -> #define %s",id,id);
1063 for(p = 0;*s != 0;++s)
1071 if(k+1 < mac->nparms)
1077 for(k = 0;*s != 0;++s,++k)
1080 if(*(s-1) > EOF && isalnum(*(s-1)))
1084 if(*(s+1) && (*(s+1) < 0 || isalnum(*(s+1))))
1092 int EiC_showMacro(char * id)
1095 if((k = EiC_ismacroid(id)) >= 0) {
1103 void EiC_showFileMacros(char *fname)
1109 for (i = 0; i < macros.n; ++i, ++v) {
1111 if (strcmp(mac->fname, fname) == 0)
1112 displayMacro(i,mac->id);
1117 void EiC_ClearFileMacros(char *fname)
1119 /* clear all the macros from the macro lut
1120 * that were entered via file `fname'
1124 int i, *ind = NULL, cnt = 0;
1127 for (i = 0; i < macros.n; ++i, ++v) {
1129 if (strcmp(mac->fname, fname) == 0) {
1131 ind = xrealloc(ind,sizeof(int) * (cnt + 1));
1133 ind = xmalloc(sizeof(int));
1137 for(i = cnt; i>0;i--)
1138 remmacroid(ind[i-1]);
1143 int EiC_ismacroid(char *id)
1150 hc = get_hcode((unsigned char *)id);
1151 for (i = 0; i < macros.n; ++i, ++v) {
1153 if (hc == mac->hcode && strcmp(mac->id, id) == 0) {
1161 static void kill_Items(eicstack_t *parms)
1165 for (i = 0; i < parms->n; i++)
1166 xfree(parms->val[i].p.p);
1173 static void freemacro(macro_t * mac)
1180 if(mac->tok_seq != empty_string)
1181 xfree(mac->tok_seq);
1182 mac->tok_seq = NULL;
1185 xfree(mac->protect);
1188 static void remmacroid(int k)
1193 mac = macros.val[k].p.p;
1196 if(k < macros.n-1) {
1197 memmove(¯os.val[k],
1199 ((macros.n-1) - k) * sizeof(val_t));
1201 /* Throw away last item on stack*/
1202 EiC_eicpop(¯os,&v);
1208 static void newmacro(eicstack_t *parms)
1213 k = EiC_ismacroid(defmacro.id);
1216 old = macros.val[k].p.p;
1217 if ((old->nparms != parms->n) ||
1218 !((old->tok_seq == empty_string && !*defmacro.tok_seq) ||
1219 strcmp(old->tok_seq, defmacro.tok_seq) == 0)) {
1220 EiC_pre_error("Re-declaration of macro %s",defmacro.id);
1222 if(defmacro.protect)
1223 xfree(defmacro.protect);
1226 new = (macro_t *) xcalloc(1, sizeof(macro_t));
1227 defmacro.id = EiC_strsave(defmacro.id);
1228 defmacro.hcode = get_hcode((unsigned char *)defmacro.id);
1229 defmacro.fname = CurrentFileName();
1230 if(*defmacro.tok_seq)
1231 defmacro.tok_seq = EiC_strsave(defmacro.tok_seq);
1232 else /* allow for empty macro */
1233 defmacro.tok_seq = empty_string;
1234 defmacro.nparms = parms->n;
1237 EiC_eicpush(¯os, v);
1239 defmacro.protect = defmacro.id = defmacro.tok_seq = NULL;
1242 extern void dodefine(char *def)
1245 * for processing -Dname[=value] switch
1246 * def = name[=value]
1250 int i = strlen(def);
1251 char * str = xmalloc(i+3);
1252 memcpy(str,def,i+1);
1253 for(p = str;*p && *p != '=';++p)
1268 static void dodefmacro(char *s)
1270 eicstack_t parms = {0, NULL};
1273 while (*s && !isspace(*s) && *s != '(')
1277 expr_list(&parms,&s,0);
1282 defmacro.tok_seq = s;
1283 defmacro.nparms = parms.n;
1289 parameterise(&parms);
1294 int EiC_Include_file(char *e, /* name of file to Include for */
1295 int mode) /* if 1, look locally first */
1296 { /* returns 1 on success else it returns 0 */
1299 char fname[512] = {0};
1300 if(mode == 1) /* look in current directory first */
1301 fd = open(e,O_RDONLY);
1304 for(i=0;i<NINCLUDES && fd < 0;i++) {
1305 strcpy(fname,Include_prefixes[i]);
1309 printf("looking for %s:%d\n",fname,file_cnt);
1310 fd = open(fname, O_RDONLY);
1313 NewInfile(fd,e,fname);
1319 static int control_line(void)
1329 if(!*s) /* test for null directive */
1332 for(k=0;isalpha(*s);k++)
1336 k = EiC_iskeyword(pwords, key, sizeof(pwords)
1337 / sizeof(keyword_t));
1345 EiC_pre_error("empty '#define' directive");
1349 if(skip && skip == iflevel) {
1350 if(EiC_cpp_parse(s))
1352 } else if(!skip && iflevel)
1357 EiC_pre_error("Unmatched #else");
1358 else if (skip == iflevel)
1365 EiC_pre_error("Unmatched #endif");
1367 if (skip >= iflevel)
1376 if(!EiC_cpp_parse(s))
1379 EiC_pre_error("empty '#if' directive");
1386 if (isalpha(*s) || *s == '_') {
1390 if (EiC_ismacroid(e) > -1) {
1394 } else if (k == IFDEF)
1397 EiC_pre_error("Illegal macro identifier");
1404 EiC_pre_error("empty '#include' directive");
1407 if (*s == '\"') /* " */
1416 if (cmode == CMstr && *(s - 1) != '\"')
1417 EiC_pre_error("Missing \"");
1418 else if (cmode == CMang && *(s - 1) != '>')
1419 EiC_pre_error("Missing >");
1421 } else { /* token_sequence */
1430 if(!EiC_Include_file(e,(cmode != CMang)))
1431 EiC_pre_error("failed to open include file %s",e);
1439 k = EiC_ismacroid(e);
1446 char *S = EiC_process2(s,0,0);
1454 char *S = EiC_process2(s,0,0);
1463 extern int ScriptMode;
1465 EiC_pre_error("undefined or invalid # directive");
1476 static int forbid[TopMax];
1478 static char * stringise(char * seq)
1483 S = outChar(S,'\"',MoD,i++); /* " */
1485 if(*seq == '\"' || *seq == '\\') /* " */
1486 S = outChar(S,'\\',MoD,i++);
1487 S = outChar(S,*seq++,MoD,i++);
1489 S = outChar(S,'\"',MoD,i++); /* " */
1494 static char * EiC_expand(char *fld,char **end, int bot, int top)
1501 eicstack_t parms = {0, NULL};
1503 for(i=0;*fld && (isalnum(*fld) || *fld == '_');++i)
1509 if ((k = EiC_ismacroid(word)) < 0)
1511 for(i=bot;i<top;i++)
1516 mac = macros.val[k].p.p;
1517 if (mac->nparms > 0) {
1520 else { /* collect arguments */
1522 expr_list(&parms,&fld,1);
1527 if (parms.n != mac->nparms)
1528 EiC_pre_error("Macro syntax error");
1532 /* Now substitute in arguments and
1533 * expand as necessary
1538 if(mac->protect && mac->protect[-*p] == 1)
1540 else if((i && S[i-1] == '#') || (i >= 2 && S[i-2] == '#')) {
1541 p2 = stringise(Item(&parms,-*p - 1,p.p));
1547 p2 = EiC_process2(Item(&parms,-*p-1,p.p),top,top);
1551 S = outChar(S,*p2++,MoD,i++);
1554 p2 = Item(&parms,-*p - 1,p.p);
1556 S = outChar(S,*p2++,MoD,i++);
1560 S = outChar(S,*p++,MoD,i++);
1563 if(S) { /* Now rescan macro definition */
1568 /* catch possible new macro funcs */
1569 /* bit of hack, but seems to work */
1570 /* should really check also for */
1571 /* brackets in strings and char literals */
1572 while(*fld && isspace(*fld))
1574 while(*fld == '(') {
1577 S = outChar(S,*fld,MoD,i++);
1580 else if(*fld == ')')
1582 if(! *++fld && parens) {
1583 /* need more input */
1584 if(EiC_Infile->fd == STDIN) {
1585 EiC_pre_error("Illegal line continuation "
1586 "during macro expansion");
1592 } while(*fld && parens);
1594 EiC_pre_error("Missing `)'");
1597 } while(isspace(*fld));
1605 else if (cmode == CMstr)
1607 } else if (*s == '\'') {
1610 else if (cmode == CMchr)
1612 } else if(*s == '\\')
1613 S2 = outChar(S2,*s++,MoD,k++);
1614 else if((isalpha(*s) || *s == '_') && !cmode) {
1615 t = EiC_expand(s,&p,bot,top);
1619 S2 = outChar(S2,*t++,MoD,k++);
1624 S2 = outChar(S2,*s++,MoD,k++);
1627 S2 = outChar(S2,*s++,MoD,k++);
1639 char * EiC_process2(char * line,int bot,int top)
1642 char *p, *s, *S = NULL;
1646 if (!cmode && (isalpha(*lp) || *lp == '_')) {
1648 p = EiC_expand(lp, &lp,bot,top);
1652 S = outChar(S,*p++,MoD,k++);
1656 S = outChar(S,*s++,MoD,k++);
1661 else if (cmode == CMchr)
1664 if (*lp == '\"') { /* " */
1667 else if(cmode == CMstr)
1669 } else if (*lp == '\\' && (cmode == CMstr || cmode == CMchr) ) {
1670 S = outChar(S,*lp++,MoD,k++);
1671 if (!*lp) /* get second char */
1674 S = outChar(S,*lp++,MoD,k++);
1681 static void cp2out(char *S)
1689 static void process(void)
1692 *(olp = oline) = '\0';
1693 S = EiC_process2(line,0,0);
1701 int EiC_setinfile(char * fname)
1703 /* look in current directory */
1704 char name[100] = {0,};
1705 int fd = open(fname,O_RDONLY);
1708 sprintf(name,"%s/%s",getenv("HOME"),fname);
1709 fd = open(name,O_RDONLY);
1711 /* look in search path include directories */
1712 fd = EiC_Include_file(fname,0);
1717 NewInfile(fd,fname,name);
1721 extern char *EiC_nextproline(void)
1723 extern int EiC_SHOWLINE;
1727 if(line[0] != ':') {
1728 if (!control_line()) {
1731 } else if (EiC_Infile->fd == STDIN) {
1735 } else if(!skip) { /* else got an EiC command line */
1736 *(olp = oline) = '\0';
1741 if (EiC_Infile->fd == STDIN)
1743 if (EiC_SHOWLINE && !showON) {
1745 fputs(oline,stdout);
1751 int EiC_insertpath(char *path)
1753 /* Adds path to include path list */
1757 * don't append the same path more than once
1759 for(i=0;i<NINCLUDES;++i)
1760 if(strcmp(path,Include_prefixes[i]) == 0)
1762 Include_prefixes = realloc(Include_prefixes,
1763 sizeof(char*)*(NINCLUDES+1));
1764 Include_prefixes[NINCLUDES] = EiC_strsave(path);
1765 if(!Include_prefixes[NINCLUDES])
1772 int EiC_removepath(char *path)
1775 for(i=0;i<NINCLUDES;++i)
1776 if(Include_prefixes[i] &&
1777 strcmp(path,Include_prefixes[i])==0) {
1778 xfree(Include_prefixes[i]);
1779 for(k=i;k<NINCLUDES-1;k++)
1780 Include_prefixes[k] = Include_prefixes[k+1];
1787 void EiC_listpath(void)
1790 for(i=0;i<NINCLUDES;++i)
1791 printf("%s\n",Include_prefixes[i]);
1794 int EiC_initpp(void)
1796 static int ftime = 1;
1797 NewInfile(STDIN,"::EiC::","::EiC::");
1802 line = (char *) calloc(REBUFF_INCREMENT, sizeof(char));
1803 oline = (char *) calloc(REBUFF_INCREMENT, sizeof(char));
1804 linelen = olinelen = REBUFF_INCREMENT;
1805 if (!line || !oline)
1808 dodefine("__FILE__=emp");
1809 dodefine("__LINE__=emp");
1810 dodefine("__DATE__=emp");
1811 dodefine("__TIME__=emp");
1812 dodefine("__STDC__=1");
1820 /* TODO: eicmod.c global needs header */
1821 extern int EiC_showIncludes = 0;
1823 static int EiC_iskeyword(keyword_t *keywords,char*id,int n)
1827 if(strcmp(keywords[i].id,id) == 0)
1828 return keywords[i].token;
1832 static void EiC_eicpush(eicstack_t *s, val_t v)
1836 s->val = (val_t*)xcalloc(sizeof(val_t),2);
1838 s->val = (val_t*)xrealloc(s->val,(s->n+2)*sizeof(val_t));
1844 static int EiC_eicpop(eicstack_t *s, val_t *pop)
1849 *pop = s->val[s->n];
1854 s->val = (val_t*)xrealloc(s->val,s->n*sizeof(val_t));
1859 static extern char * EiC_strsave(char *s)
1862 if((p = (char*)xcalloc(strlen(s)+1,sizeof(char))) != NULL)
1867 /* TODO: eicmod.c global needs header */
1868 int EiC_SHOWLINE = 1;
1870 static int do_sw_commands(char *cp)
1873 case 'D': dodefine(cp); return 1;
1874 case 'I': EiC_insertpath(cp);return 1;
1877 case 'R': EiC_setinfile(cp); return 1;
1879 case 'S': EiC_verboseON = 0; return 1;
1885 void main(int argc, char ** argv)
1891 if(argv[1][0] == '-') {
1892 if(!do_sw_commands(&argv[1][1])) {
1893 fprintf(stderr,"Unknown switch command [%s]\n",argv[1]);
1897 fprintf(stderr,"Unknown switch command [%s]\n",argv[1]);
1902 if(EiC_Infile->fd == STDIN) {
1903 fputs("testpp> ",stdout);
1907 buf = EiC_nextproline();
1908 while(*buf && *buf != EOF)
1910 }while(*buf != EOF);