/* * Copyright (c) 1994-2000 FUJITSU LABORATORIES LIMITED * All rights reserved. * * FUJITSU LABORATORIES LIMITED ("FLL") hereby grants you a limited, * non-exclusive and royalty-free license to use, copy, modify and * redistribute, solely for non-commercial and non-profit purposes, the * computer program, "Risa/Asir" ("SOFTWARE"), subject to the terms and * conditions of this Agreement. For the avoidance of doubt, you acquire * only a limited right to use the SOFTWARE hereunder, and FLL or any * third party developer retains all rights, including but not limited to * copyrights, in and to the SOFTWARE. * * (1) FLL does not grant you a license in any way for commercial * purposes. You may use the SOFTWARE only for non-commercial and * non-profit purposes only, such as academic, research and internal * business use. * (2) The SOFTWARE is protected by the Copyright Law of Japan and * international copyright treaties. If you make copies of the SOFTWARE, * with or without modification, as permitted hereunder, you shall affix * to all such copies of the SOFTWARE the above copyright notice. * (3) An explicit reference to this SOFTWARE and its copyright owner * shall be made on your publication or presentation in any form of the * results obtained by use of the SOFTWARE. * (4) In the event that you modify the SOFTWARE, you shall notify FLL by * e-mail at risa-admin@sec.flab.fujitsu.co.jp of the detailed specification * for such modification or the source code of the modified part of the * SOFTWARE. * * THE SOFTWARE IS PROVIDED AS IS WITHOUT ANY WARRANTY OF ANY KIND. FLL * MAKES ABSOLUTELY NO WARRANTIES, EXPRESSED, IMPLIED OR STATUTORY, AND * EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT OF THIRD PARTIES' * RIGHTS. NO FLL DEALER, AGENT, EMPLOYEES IS AUTHORIZED TO MAKE ANY * MODIFICATIONS, EXTENSIONS, OR ADDITIONS TO THIS WARRANTY. * UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, TORT, CONTRACT, * OR OTHERWISE, SHALL FLL BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, PUNITIVE OR CONSEQUENTIAL * DAMAGES OF ANY CHARACTER, INCLUDING, WITHOUT LIMITATION, DAMAGES * ARISING OUT OF OR RELATING TO THE SOFTWARE OR THIS AGREEMENT, DAMAGES * FOR LOSS OF GOODWILL, WORK STOPPAGE, OR LOSS OF DATA, OR FOR ANY * DAMAGES, EVEN IF FLL SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF * SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. EVEN IF A PART * OF THE SOFTWARE HAS BEEN DEVELOPED BY A THIRD PARTY, THE THIRD PARTY * DEVELOPER SHALL HAVE NO LIABILITY IN CONNECTION WITH THE USE, * PERFORMANCE OR NON-PERFORMANCE OF THE SOFTWARE. * * $OpenXM: OpenXM_contrib2/asir2018/parse/cpp.c,v 1.1 2018/09/19 05:45:08 noro Exp $ */ #include #include #include jmp_buf cpp_env; #if 0 #include "accum.h" #include "expr.h" #include "if.h" #include "io.h" #include "is.h" #include "malloc.h" #include "stats.h" #include "symtbl.h" #include "unctrl.h" #endif #include "cpp.h" char *init_accum(void) { ACCUM *a; a = NEW(ACCUM); check_malloc(a); a->used = 0; a->have = 8; a->buf = malloc(8); check_malloc(a->buf); return((char *)a); } void accum_char(char *A, char c) #define a ((ACCUM *)A) { while (a->used >= a->have) { a->buf = realloc(a->buf,a->have+=8); check_malloc(a->buf); } a->buf[a->used++] = c; } #undef a char accum_regret(char *A) #define a ((ACCUM *)A) { if (a->used > 0) { return(a->buf[--a->used]); } else { return(0); } } #undef a char *accum_result(char *A) #define a ((ACCUM *)A) { char *cp; cp = realloc(a->buf,a->used+1); check_malloc(cp); cp[a->used] = '\0'; OLD(a); return(cp); } #undef a char *accum_sofar(char *A) #define a ((ACCUM *)A) { char *cp; cp = malloc(a->used+1); check_malloc(cp); Bcopy(a->buf,cp,a->used); cp[a->used] = '\0'; return(cp); } #undef a char *accum_buf(char *A) #define a ((ACCUM *)A) { return(a->buf); } #undef a int accum_howfar(char *A) #define a ((ACCUM *)A) { return(a->used); } #undef a void do_at(void) { char *w; w = read_ctrl(); if (strcmp(w,"include") == 0) { do_include(0); } else if (strcmp(w,"define") == 0) { do_define(0,0); } else if (strcmp(w,"undef") == 0) { do_undef(0); } else if (strcmp(w,"redefine") == 0) { do_define(0,1); } else if (strcmp(w,"ifdef") == 0) { do_ifdef(0); } else if (strcmp(w,"ifndef") == 0) { do_ifndef(0); } else if (strcmp(w,"if") == 0) { do_if(0); } else if (strcmp(w,"else") == 0) { do_else(0); } else if (strcmp(w,"elif") == 0) { do_elif(0); } else if (strcmp(w,"endif") == 0) { do_endif(0); } else if (strcmp(w,"set") == 0) { do_set(); } else if (strcmp(w,"while") == 0) { do_while(); } else if (strcmp(w,"endwhile") == 0) { do_endwhile(); } else if (strcmp(w,"dump") == 0) { do_dump(); } else if (strcmp(w,"debug") == 0) { do_debug(); } else if (strcmp(w,"eval") == 0) { do_eval(); } else { if (! in_false_if()) { err_head(); fprintf(stderr,"unknown control `%s'\n",w); } } free(w); } static char *temp; void autodef_file(char *f) { int i; i = strlen(f); temp = malloc(i+2+1); check_malloc(temp); sprintf(temp,"\"%s\"",f); undef("__FILE__"); define("__FILE__",-1,(unsigned char *)temp,0); } void autodef_line(int l) { defd("__LINE__",l); } char *copyofstr(char *str) { char *cp; if (str == 0) { return(0); } cp = malloc(strlen(str)+1); if (cp == 0) { return(0); } strcpy(cp,str); return(cp); } char *copyofblk(char *blk, int len) { char *cp; if (blk == 0) { return(0); } cp = malloc(len); if (cp == 0) { return(0); } Bcopy(blk,cp,len); return(cp); } /* these really don't beint here; they should be in their own file */ #if 0 char *malloc(nb) #undef malloc int nb; { extern char *malloc(); return(malloc(nb?nb:1)); } char *realloc(old,nb) #undef realloc char *old; int nb; { extern char *realloc(); return(realloc(old,(nb?nb:1))); } #endif static char buf[BUFSIZ]; int debugging = 0; void do_debug(void) { char c; fflush(outfile); c = getnonspace(); switch (c) { case '1': case 'y': case 'Y': debugging = 1; break; default: debugging = 0; break; } setbuf(outfile,debugging?NULL:buf); } static int nargs; static int nfound; static char **argnames; void read_formals(void) { char *arg; char c; nargs = 0; argnames = (char **) malloc(1); check_malloc(argnames); while (1) { arg = read_ident(); if (arg) { argnames = (char **) realloc((char *)argnames,(nargs+1)*sizeof(char *)); check_malloc(argnames); argnames[nargs] = arg; nargs ++; c = getnonspace(); if (c == ')') { return; } else if (c != ',') { err_head(); fprintf(stderr,"invalid macro parameter delimiter\n"); } } else { c = Get(); if ((c == ')') && (nargs == 0)) { return; } else { Push(c); } err_head(); fprintf(stderr,"missing/illegal macro parameter\n"); while (1) { c = Get(); if (c == ')') { return; } if (isbsymchar(c)) { Push(c); break; } } } } } void do_define(int sharp, int redef) { char *mac; char c; char *acc; unsigned char *repl; int quoted; int incomment; unsigned char *f; unsigned char *t; unsigned char *g; int i; if (in_false_if()) { char e = '\0'; if (sharp) { while (1) { c = e; e = Get(); if (e == '\n') { if (c == '\\') { maybe_print('\n'); } else { break; } } } } else { do { c = e; e = Get(); } while ((c != '@') || (e == '@')); Push(e); } return; } mac = read_ident(); if (! mac) { err_head(); fprintf(stderr,"missing/illegal macro name\n"); flush_sharp_line(); return; } c = Get(); if (c == '(') { read_formals(); nfound = nargs; if (nargs > 128) { err_head(); fprintf(stderr,"too many macro formals, more than 128 ignored\n"); nargs = 128; } } else { argnames = 0; nargs = -1; nfound = -1; if ((c != ' ') && (c != '\t')) { Push(c); } } quoted = 0; incomment = 0; acc = init_accum(); if (sharp) { while (1) { c = Get(); if (quoted && (c == '\n')) { quoted = 0; maybe_print('\n'); } else if (quoted) { accum_char(acc,'\\'); accum_char(acc,c); quoted = 0; } else if (c == '/') { char d = Get(); accum_char(acc,'/'); if (d == '*') { accum_char(acc,'*'); incomment = 1; } else { Push(d); } } else if (incomment) { accum_char(acc,c); if (c == '*') { char d = Get(); if (d == '/') { accum_char(acc,'/'); incomment = 0; } else { Push(d); } } else if (c == '\n') { maybe_print('\n'); } } else if (c == '\\') { quoted = 1; } else if (c == '\n') { break; } else { accum_char(acc,c); } } } else { while (1) { c = Get(); if (quoted && (c == '@')) { accum_char(acc,'@'); quoted = 0; } else if (quoted) { Push(c); break; } else if (c == '/') { char d = Get(); accum_char(acc,'/'); if (d == '*') { accum_char(acc,'*'); incomment = 1; } else { Push(d); } } else if (incomment) { accum_char(acc,c); if (c == '*') { char d = Get(); if (d == '/') { accum_char(acc,'/'); incomment = 0; } else { Push(d); } } else if (c == '\n') { maybe_print('\n'); } } else if (c == '@') { quoted = 1; } else { if (c == '\n') { maybe_print('\n'); } accum_char(acc,c); } } } repl = (unsigned char *) accum_result(acc); f = repl; t = repl; while (*f) { if (isbsymchar(*f) && !incomment) { for (g=f;issymchar(*g);g++) ; c = *g; *g = '\0'; for (i=0;ilink) { dump_single(d); putc('\n',stderr); } } fprintf(stderr,"\n\tInclude directory stack:\n\n"); for (i=0;iname); if (d->nargs == 0) { fprintf(stderr,"()"); } else if (d->nargs > 0) { int i; for (i=0;inargs;i++) { fprintf(stderr,"%c#%d",i?',':'(',i); } putc(')',stderr); } putc(' ',stderr); for (cp=d->repl;*cp;cp++) { if (*cp & 0x80) { fprintf(stderr,"#%d",(*cp)&~0x80); } else { putc(*cp,stderr); } } } void err_head(void) { fprintf(stderr,"\"%s\", line %d: ",curfile(),curline()); } void Check_malloc(char *ptr) { if (ptr == 0) { fprintf(stderr,"out of memory!\n"); abort(); } } void do_eval(void) { char c; char temp[64]; int i; if (! in_false_if()) { c = getnonspace(); if (c != '(') { err_head(); fprintf(stderr,"@eval must have ()s\n"); Push(c); return; } sprintf(temp,"%d",eval_expr(0,1)); for (i=strlen(temp)-1;i>=0;i--) { Push(temp[i]); } } } #define DEBUG_EXPAND/**/ #ifdef DEBUG_EXPAND extern int debugging; #endif extern int keep_comments; static char **actuals; static int *actlens; void read_actuals(DEF *d) { int n; int i; int pc; char c; char last; char quote; int backslash; int comment; char *acc; n = d->nargs; actuals = (char **) malloc(n*sizeof(char *)); check_malloc(actuals); actlens = (int *) malloc(n*sizeof(int)); check_malloc(actlens); c = getnonspace(); if (c != '(') { err_head(); if (n == 0) { fprintf(stderr,"missing () on %s\n",d->name); } else { fprintf(stderr,"missing argument%s to %s\n",(n==1)?"":"s",d->name); } for (i=0;iname); Push(c); } return; } i = 0; while (1) { pc = 0; quote = 0; backslash = 0; comment = 0; c = 0; acc = init_accum(); while (1) { last = c; c = Get(); accum_char(acc,c); if (comment) { if ((last == '*') && (c == '/')) { comment = 0; } } else { if (backslash) { backslash = 0; } else if (quote && (c == quote)) { quote = 0; } else if (c == '\\') { backslash = 1; } else if (quote) { } else if ((last == '/') && (c == '*')) { comment = 1; } else if ((c == '\'') || (c == '"')) { quote = c; } else if (c == '(') { pc ++; } else if (c == ')') { if (pc > 0) { pc --; } else { accum_regret(acc); break; } } else if ((c == ',') && (pc == 0)) { accum_regret(acc); break; } } } if (i < n) { actuals[i] = accum_result(acc); actlens[i] = strlen(actuals[i]); i ++; } else if (i == n) { err_head(); fprintf(stderr,"too many arguments to %s\n",d->name); i ++; } if (c == ')') { break; } } if (i < n) { err_head(); fprintf(stderr,"too few arguments to %s\n",d->name); for (;inargs >= 0) { read_actuals(d); } #ifdef DEBUG_EXPAND if (debugging) { char *cp; outputs("~EXPAND:"); outputs(d->name); if (d->nargs == 0) { outputs("()"); } else if (d->nargs > 0) { int i; for (i=0;inargs;i++) { outputc((char)(i?',':'(')); outputs(actuals[i]); } outputc(')'); } outputs("-->"); for (cp=(char *)d->repl;*cp;cp++) { outputs(unctrl(*cp)); } outputc('~'); } #endif result = init_accum(); for (cp=d->repl;*cp;cp++) { if (*cp & 0x80) { char *dp; int i; i = *cp & ~0x80; for (dp=actuals[i];*dp;dp++) { accum_char(result,*dp); } } else { accum_char(result,*cp); } } dp = accum_result(result); #ifdef DEBUG_EXPAND if (debugging) { outputs("first:"); for (ep=dp;*ep;ep++) { outputs(unctrl(*ep)); } outputc('~'); } #endif result = init_accum(); last = '\0'; ok = 1; incomm = 0; for (ep=dp;*ep;ep++) { if (!incomm && (last == '/') && (*ep == '*')) { incomm = 1; if (!keep_comments || (strncmp(ep,"**/",3) == 0)) { accum_regret(result); ok = 0; } } if (ok) { accum_char(result,*ep); } if ((last == '*') && (*ep == '/')) { incomm = 0; ok = 1; } last = *ep; } free(dp); result = accum_result(result); #ifdef DEBUG_EXPAND if (debugging) { outputs("/**/strip:"); outputs(result); outputc('~'); } #endif for (dp=result+strlen(result)-1;dp>=result;dp--) { Push(*dp); } free(result); if (d->nargs >= 0) { int i; for (i=0;inargs;i++) { free(actuals[i]); } free((char *)actuals); } } #define DEBUG_EXPR/**/ #define TWOCHAR(c1,c2) (((c1)<<8)|(c2)) #define LSH TWOCHAR('<','<') #define RSH TWOCHAR('>','>') #define LEQ TWOCHAR('<','=') #define GEQ TWOCHAR('>','=') #define EQL TWOCHAR('=','=') #define NEQ TWOCHAR('!','=') #define AND TWOCHAR('&','&') #define OR TWOCHAR('|','|') #define ALLBINS \ BIN('*',*) \ BIN('/',/) \ BIN('%',%) \ BIN('+',+) \ BIN(LSH,<<) \ BIN(RSH,>>) \ BIN('<',<) \ BIN('>',>) \ BIN(LEQ,<=) \ BIN(GEQ,>=) \ BIN(EQL,==) \ BIN(NEQ,!=) \ BIN('&',&) \ BIN('^',^) \ BIN('|',|) \ BIN(AND,&&) \ BIN(OR ,||) char *Index(char *s, int c); static NODE *expr; int expr_sharp; #define sharp expr_sharp static int complain; #ifdef DEBUG_EXPR extern int debugging; #endif void free_expr(NODE *n) { switch (n->op) { case 0: break; case '-': if (n->left) { free_expr(n->left); } free_expr(n->right); break; case '!': case '~': free_expr(n->right); break; case 'd': free(n->name); break; default: free_expr(n->left); free_expr(n->right); break; } OLD(n); } int exec_free(NODE *n) { int rv; int l; int r; switch (n->op) { case 0: rv = n->leaf; break; case '-': if (n->left) { rv = exec_free(n->left); } else { rv = 0; } rv -= exec_free(n->right); break; case '!': rv = ! exec_free(n->right); break; case '~': rv = ~ exec_free(n->right); break; case 'd': rv = !! find_def(n->name); free(n->name); break; #define BIN(key,op) case key:l=exec_free(n->left);r=exec_free(n->right);rv=l op r;break; ALLBINS #undef BIN } OLD(n); return(rv); } int exec_nofree(NODE *n) { int rv; switch (n->op) { case 0: rv = n->leaf; break; case '-': if (n->left) { rv = exec_nofree(n->left); } else { rv = 0; } rv -= exec_nofree(n->right); break; case '!': rv = ! exec_nofree(n->right); break; case '~': rv = ~ exec_nofree(n->right); break; case 'd': rv = !! find_def(n->name); free(n->name); break; #define BIN(key,op) case key:rv=(exec_nofree(n->left)op exec_nofree(n->right));break; ALLBINS #undef BIN } return(rv); } NODE *newnode(NODE *l, int c, NODE *r) { NODE *n; n = NEW(NODE); check_malloc(n); n->left = l; n->right = r; n->op = c; return(n); } NODE *newleaf(int v) { NODE *n; n = NEW(NODE); check_malloc(n); n->op = 0; n->left = 0; n->right = 0; n->leaf = v; return(n); } NODE *newname(char *name) { NODE *n; n = NEW(NODE); check_malloc(n); n->op = 'd'; n->name = copyofstr(name); check_malloc(n->name); return(n); } int get_quote_char(void) { char c; char d; c = Get(); if (c == '\'') { return(-1); } if (c == '\n') { err_head(); fprintf(stderr,"newline in character constant\n"); return(-1); } if (c != '\\') { return(0xff&(int)c); } c = Get(); if ((c >= '0') && (c <= '7')) { d = c - '0'; c = Get(); if ((c >= '0') && (c <= '7')) { d = (d << 3) + c - '0'; c = Get(); if ((c >= '0') && (c <= '7')) { d = (d << 3) + c - '0'; } else { Push(c); } } else { Push(c); } return(0xff&(int)d); } switch (c) { case 'n': return('\n'); break; case 'r': return('\r'); break; case 'e': return('\033'); break; case 'f': return('\f'); break; case 't': return('\t'); break; case 'b': return('\b'); break; case 'v': return('\v'); break; default: return(0xff&(int)c); break; } } NODE *read_expr_11(void) { char c; #ifdef DEBUG_EXPR if (debugging) { outputs("~E11:"); } #endif while (1) { c = getnhsexpand(); if (c == '(') { NODE *n; NODE *read_expr_(void); #ifdef DEBUG_EXPR if (debugging) { outputs("()"); } #endif n = read_expr_(); c = getnhsexpand(); if (c != ')') { err_head(); fprintf(stderr,"expression syntax error -- missing ) supplied\n"); Push(c); } #ifdef DEBUG_EXPR if (debugging) { outputs("~"); } #endif return(n); } else if (isdigit(c)) { int base; static char digits[] = "0123456789abcdefABCDEF"; static char values[] = "\0\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17\12\13\14\15\16\17"; char *d; int v; #ifdef DEBUG_EXPR if (debugging) { outputs("N"); } #endif base = 10; if (c == '0') { base = 8; c = Get(); if ((c == 'x') || (c == 'X')) { base = 16; c = Get(); } } v = 0; while (1) { d = Index(digits,c); if (d == 0) { Push(c); #ifdef DEBUG_EXPR if (debugging) { outputd(v); outputs("~"); } #endif return(newleaf(v)); } else if (values[d-digits] >= base) { err_head(); fprintf(stderr,"warning: illegal %sdigit `%c'\n", (base==16)?"hex ":(base==8)?"octal ":"",c); } v = (v * base) + values[d-digits]; c = Get(); } } else if (c == '\'') { int i; int j; int n; i = 0; n = 0; while (1) { j = get_quote_char(); if (j < 0) { break; } i = (i << 8) | j; n ++; } if (n > 4) { err_head(); fprintf(stderr,"warning: too many characters in character constant\n"); } return(newleaf(i)); } else if ((c == '\n') && !sharp) { } else { char *id; if (complain) { err_head(); fprintf(stderr,"expression syntax error -- number expected\n"); } if (isbsymchar(c)) { Push(c); id = read_ident(); } else { id = 0; } #ifdef DEBUG_EXPR if (debugging) { outputs("0("); outputc(c); outputs(":"); outputs(id?id:"(none)"); outputs(")~"); } #endif if (id) { free(id); } return(newleaf(0)); } } } NODE *read_expr_10(void) { char c; char *w; NODE *n; #ifdef DEBUG_EXPR if (debugging) { outputs("~E10:"); } #endif while (1) { c = getnhsexpand(); switch (c) { case '-': case '~': case '!': #ifdef DEBUG_EXPR if (debugging) { outputc(c); } #endif n = read_expr_10(); #ifdef DEBUG_EXPR if (debugging) { outputs("~"); } #endif return(newnode(0,c,n)); break; case 'd': Push(c); input_mark(); w = read_ident(); if (strcmp(w,"defined") == 0) { c = getnonspace(); if (c == '(') { char *id; id = read_ident(); if (id) { c = getnonspace(); if (c == ')') { input_unmark(); #ifdef DEBUG_EXPR if (debugging) { outputs("ifdef"); } #endif return(newname(id)); } } } else if (isbsymchar(c)) { char *id; Push(c); id = read_ident(); if (id) { input_unmark(); #ifdef DEBUG_EXPR if (debugging) { outputs("ifdef"); } #endif return(newname(id)); } } } input_recover(); n = read_expr_11(); #ifdef DEBUG_EXPR if (debugging) { outputs("~"); } #endif return(n); break; default: Push(c); n = read_expr_11(); #ifdef DEBUG_EXPR if (debugging) { outputs("~"); } #endif return(n); break; } } } NODE *read_expr_9(void) { NODE *l; NODE *r; char c; #ifdef DEBUG_EXPR if (debugging) { outputs("~E9:"); } #endif l = read_expr_10(); while (1) { c = getnhsexpand(); switch (c) { case '*': case '/': case '%': #ifdef DEBUG_EXPR if (debugging) { outputc(c); } #endif r = read_expr_10(); l = newnode(l,c,r); break; default: #ifdef DEBUG_EXPR if (debugging) { outputs("~"); } #endif Push(c); return(l); break; } } } NODE *read_expr_8(void) { NODE *l; NODE *r; char c; #ifdef DEBUG_EXPR if (debugging) { outputs("~E8:"); } #endif l = read_expr_9(); while (1) { c = getnhsexpand(); switch (c) { case '+': case '-': #ifdef DEBUG_EXPR if (debugging) { outputc(c); } #endif r = read_expr_9(); l = newnode(l,c,r); break; default: #ifdef DEBUG_EXPR if (debugging) { outputs("~"); } #endif Push(c); return(l); break; } } } NODE *read_expr_7(void) { NODE *l; NODE *r; char c; char d; #ifdef DEBUG_EXPR if (debugging) { outputs("~E7:"); } #endif l = read_expr_8(); while (1) { c = getnhsexpand(); switch (c) { case '<': case '>': d = Get(); if (d == c) { #ifdef DEBUG_EXPR if (debugging) { outputc(c); outputc(d); } #endif r = read_expr_8(); l = newnode(l,(c=='<')?LSH:RSH,r); break; } Push(d); /* fall through ... */ default: #ifdef DEBUG_EXPR if (debugging) { outputs("~"); } #endif Push(c); return(l); break; } } } NODE *read_expr_6(void) { NODE *l; NODE *r; char c; char d; #ifdef DEBUG_EXPR if (debugging) { outputs("~E6:"); } #endif l = read_expr_7(); while (1) { c = getnhsexpand(); switch (c) { case '<': case '>': d = Get(); if (d == '=') { #ifdef DEBUG_EXPR if (debugging) { outputc(c); outputc(d); } #endif r = read_expr_7(); l = newnode(l,(c=='<')?LEQ:GEQ,r); } else { #ifdef DEBUG_EXPR if (debugging) { outputc(c); } #endif Push(d); r = read_expr_7(); l = newnode(l,c,r); } break; default: #ifdef DEBUG_EXPR if (debugging) { outputs("~"); } #endif Push(c); return(l); break; } } } NODE *read_expr_5(void) { NODE *l; NODE *r; char c; char d; #ifdef DEBUG_EXPR if (debugging) { outputs("~E5:"); } #endif l = read_expr_6(); while (1) { c = getnhsexpand(); switch (c) { case '=': case '!': d = Get(); if (d == '=') { #ifdef DEBUG_EXPR if (debugging) { outputc(c); outputc(d); } #endif r = read_expr_6(); l = newnode(l,(c=='=')?EQL:NEQ,r); break; } Push(d); /* fall through ... */ default: #ifdef DEBUG_EXPR if (debugging) { outputs("~"); } #endif Push(c); return(l); break; } } } NODE *read_expr_4(void) { NODE *l; NODE *r; char c; char d; #ifdef DEBUG_EXPR if (debugging) { outputs("~E4:"); } #endif l = read_expr_5(); while (1) { c = getnhsexpand(); switch (c) { case '&': d = Get(); if (d != '&') { #ifdef DEBUG_EXPR if (debugging) { outputc(c); outputc(d); } #endif r = read_expr_5(); l = newnode(l,c,r); break; } Push(d); /* fall through ... */ default: #ifdef DEBUG_EXPR if (debugging) { outputs("~"); } #endif Push(c); return(l); break; } } } NODE *read_expr_3(void) { NODE *l; NODE *r; char c; #ifdef DEBUG_EXPR if (debugging) { outputs("~E3:"); } #endif l = read_expr_4(); while (1) { c = getnhsexpand(); switch (c) { case '^': #ifdef DEBUG_EXPR if (debugging) { outputc(c); } #endif r = read_expr_4(); l = newnode(l,c,r); break; default: #ifdef DEBUG_EXPR if (debugging) { outputs("~"); } #endif Push(c); return(l); break; } } } NODE *read_expr_2(void) { NODE *l; NODE *r; char c; char d; #ifdef DEBUG_EXPR if (debugging) { outputs("~E2:"); } #endif l = read_expr_3(); while (1) { c = getnhsexpand(); switch (c) { case '|': d = Get(); if (d != '|') { Push(d); #ifdef DEBUG_EXPR if (debugging) { outputc(c); } #endif r = read_expr_3(); l = newnode(l,c,r); break; } Push(d); /* fall through ... */ default: #ifdef DEBUG_EXPR if (debugging) { outputs("~"); } #endif Push(c); return(l); break; } } } NODE *read_expr_1(void) { NODE *l; NODE *r; char c; char d; #ifdef DEBUG_EXPR if (debugging) { outputs("~E1:"); } #endif l = read_expr_2(); while (1) { c = getnhsexpand(); switch (c) { case '&': d = Get(); if (d == c) { #ifdef DEBUG_EXPR if (debugging) { outputc(c); outputc(d); } #endif r = read_expr_2(); l = newnode(l,AND,r); break; } Push(d); /* fall through ... */ default: #ifdef DEBUG_EXPR if (debugging) { outputs("~"); } #endif Push(c); return(l); break; } } } NODE *read_expr_0(void) { NODE *l; NODE *r; char c; char d; #ifdef DEBUG_EXPR if (debugging) { outputs("~E0:"); } #endif l = read_expr_1(); while (1) { c = getnhsexpand(); switch (c) { case '|': d = Get(); if (d == c) { #ifdef DEBUG_EXPR if (debugging) { outputc(c); outputc(d); } #endif r = read_expr_1(); l = newnode(l,OR,r); break; } Push(d); /* fall through ... */ default: #ifdef DEBUG_EXPR if (debugging) { outputs("~"); } #endif Push(c); return(l); break; } } } NODE *read_expr_(void) { NODE *l; NODE *r; char c; #ifdef DEBUG_EXPR if (debugging) { outputs("~E"); } #endif l = read_expr_0(); while (1) { c = getnhsexpand(); switch (c) { case '\n': case ')': Push(c); return(l); break; case ',': r = read_expr_0(); l = newnode(l,c,r); break; default: err_head(); fprintf(stderr,"expression syntax error -- bad operator `%c'\n",c); return(l); break; } } } NODE *read_expr_p(void) { char c; NODE *rv; sharp = 0; complain = 1; c = getnonspace(); if (c != '(') { Push(c); return(0); } rv = read_expr_(); c = getnonspace(); if (c != ')') { err_head(); fprintf(stderr,"junk after expression\n"); } return(rv); } int eval_expr(int Sharp, int Complain) { char c; char d; int rv; sharp = Sharp; complain = Complain; expr = read_expr_(); if (sharp) { c = getnonhspace(); d = '\n'; } else { c = getnonspace(); d = ')'; } if (c != d) { if (complain) { err_head(); fprintf(stderr,"expression syntax error -- junk after expression\n"); } while (Get() != d) ; } #ifdef DEBUG_EXPR if (debugging) { outputc('<'); dump_expr(expr); outputc('='); rv = exec_free(expr); outputd(rv); outputc('>'); } else { rv = exec_free(expr); } return(rv); #else return(exec_free(expr)); #endif } #ifdef DEBUG_EXPR void dump_expr(NODE *n) { switch (n->op) { case 0: outputd(n->leaf); break; case '-': if (n->left) { dump_expr(n->left); } outputc('-'); dump_expr(n->right); break; case '!': outputc('!'); dump_expr(n->right); break; case '~': outputc('~'); dump_expr(n->right); break; case 'd': outputs("defined("); outputs(n->name); outputc(')'); break; #define BIN(key,op) case key:dump_expr(n->left);\ putx(key);\ dump_expr(n->right);\ break; ALLBINS #undef BIN } } void putx(int i) { if (i > 0xff) outputc((char)(i>>8)); outputc((char)(i&0xff)); } #endif /*#define DEBUG_IF/**/ #ifdef DEBUG_IF extern int debugging; #endif void do_if(int expr_sharp) { char c; char d; #ifdef DEBUG_IF if (debugging) { outputc('<'); outputc(sharp?'#':'@'); outputs("if: "); fflush(outfile); } #endif if (in_false_if()) { n_skipped_ifs ++; #ifdef DEBUG_IF if (debugging) { outputs("in-false, skipped>"); fflush(outfile); } #endif if (sharp) { d = '\0'; do { c = d; d = Get(); } while ((c == '\\') || (d != '\n')); } return; } if (! sharp) { c = getnonspace(); if (c != '(') { err_head(); fprintf(stderr,"@if must have ()s\n"); Push(c); iffalse(); #ifdef DEBUG_IF if (debugging) { outputc('>'); fflush(outfile); } #endif return; } } if (eval_expr(sharp,0)) { iftrue(); } else { iffalse(); } #ifdef DEBUG_IF if (debugging) { outputc('>'); fflush(outfile); } #endif } void do_ifdef(int expr_sharp) { char *w; #ifdef DEBUG_IF if (debugging) { outputc('<'); outputc(sharp?'#':'@'); outputs("ifdef: "); fflush(outfile); } #endif if (in_false_if()) { n_skipped_ifs ++; #ifdef DEBUG_IF if (debugging) { outputs("in-false, skipped>"); fflush(outfile); } #endif } else { w = read_ident(); if (! w) { #ifdef DEBUG_IF if (debugging) { outputs("no ident "); fflush(outfile); } #endif iffalse(); } else { #ifdef DEBUG_IF if (debugging) { outputs(w); outputc(' '); fflush(outfile); } #endif if (find_def(w)) { iftrue(); } else { iffalse(); } free(w); } #ifdef DEBUG_IF if (debugging) { outputc('>'); fflush(outfile); } #endif } if (sharp) { flush_sharp_line(); } } void do_ifndef(int expr_sharp) { char *w; #ifdef DEBUG_IF if (debugging) { outputc('<'); outputc(sharp?'#':'@'); outputs("ifndef: "); fflush(outfile); } #endif if (in_false_if()) { n_skipped_ifs ++; #ifdef DEBUG_IF if (debugging) { outputs("in-false, skipped>"); fflush(outfile); } #endif } else { w = read_ident(); if (! w) { #ifdef DEBUG_IF if (debugging) { outputs("no ident "); fflush(outfile); } #endif iftrue(); } else { #ifdef DEBUG_IF if (debugging) { outputs(w); outputc(' '); fflush(outfile); } #endif if (find_def(w)) { iffalse(); } else { iftrue(); } free(w); } #ifdef DEBUG_IF if (debugging) { outputc('>'); fflush(outfile); } #endif } if (sharp) { flush_sharp_line(); } } void do_else(int expr_sharp) { #ifdef DEBUG_IF if (debugging) { outputc('<'); outputc(sharp?'#':'@'); outputs("else: "); fflush(outfile); } #endif if (n_skipped_ifs == 0) { if (ifstack) { #ifdef DEBUG_IF if (debugging) { outputs("top "); output_ifstate(ifstack->condstate); fflush(outfile); } #endif switch (ifstack->condstate) { case IFSTATE_TRUE: ifstack->condstate = IFSTATE_STAYFALSE; break; case IFSTATE_FALSE: ifstack->condstate = IFSTATE_TRUE; break; } #ifdef DEBUG_IF if (debugging) { outputs(" now "); output_ifstate(ifstack->condstate); outputc('>'); fflush(outfile); } #endif } else { #ifdef DEBUG_IF if (debugging) { outputs(" no if>"); fflush(outfile); } #endif err_head(); fprintf(stderr,"if-less else\n"); } } else { #ifdef DEBUG_IF if (debugging) { outputs("in-false, forgetting>"); fflush(outfile); } #endif } if (sharp) { flush_sharp_line(); } } #ifdef DEBUG_IF void output_ifstate(state) int state; { switch (state) { case IFSTATE_TRUE: outputs("TRUE"); break; case IFSTATE_FALSE: outputs("FALSE"); break; case IFSTATE_STAYFALSE: outputs("STAYFALSE"); break; default: outputs("BAD"); outputd(state); break; } } #endif void do_elif(int expr_sharp) { char c; char d; int e; #ifdef DEBUG_IF if (debugging) { outputc('<'); outputc(sharp?'#':'@'); outputs("elif: "); fflush(outfile); } #endif if (ifstack == 0) { err_head(); fprintf(stderr,"if-less elif converted to normal if\n"); iffalse(); } if (n_skipped_ifs > 0) { #ifdef DEBUG_IF if (debugging) { outputs("being skipped, ignoring>"); fflush(outfile); } #endif if (sharp) { d = '\0'; do { c = d; d = Get(); } while ((c == '\\') || (d != '\n')); } return; } if (! sharp) { c = getnonspace(); if (c != '(') { err_head(); fprintf(stderr,"@elif must have ()s\n"); Push(c); ifstack->condstate = IFSTATE_STAYFALSE; #ifdef DEBUG_IF if (debugging) { outputs("forcing STAYFALSE>"); fflush(outfile); } #endif return; } } e = eval_expr(sharp,0); #ifdef DEBUG_IF if (debugging) { outputs("expr "); outputd(e); outputc(' '); fflush(outfile); } #endif #ifdef DEBUG_IF if (debugging) { outputs(" top "); output_ifstate(ifstack->condstate); fflush(outfile); } #endif switch (ifstack->condstate) { case IFSTATE_TRUE: ifstack->condstate = IFSTATE_STAYFALSE; break; case IFSTATE_FALSE: if (e) { ifstack->condstate = IFSTATE_TRUE; } break; } #ifdef DEBUG_IF if (debugging) { outputs(" now "); output_ifstate(ifstack->condstate); outputc('>'); fflush(outfile); } #endif } void do_endif(int expr_sharp) { IF *i; #ifdef DEBUG_IF if (debugging) { outputc('<'); outputc(sharp?'#':'@'); outputs("endif: "); fflush(outfile); } #endif if (n_skipped_ifs > 0) { n_skipped_ifs --; #ifdef DEBUG_IF if (debugging) { outputs("n_skipped -->"); fflush(outfile); } #endif } else if (ifstack) { i = ifstack->next; OLD(ifstack); ifstack = i; #ifdef DEBUG_IF if (debugging) { outputs("popping stack>"); fflush(outfile); } #endif } else { err_head(); fprintf(stderr,"if-less endif\n"); #ifdef DEBUG_IF if (debugging) { outputc('>'); fflush(outfile); } #endif } if (sharp) { flush_sharp_line(); } } void iftrue(void) { IF *i; i = NEW(IF); check_malloc(i); i->next = ifstack; ifstack = i; i->condstate = IFSTATE_TRUE; #ifdef DEBUG_IF if (debugging) { outputs("IFTRUE"); fflush(outfile); } #endif } void iffalse(void) { IF *i; i = NEW(IF); check_malloc(i); i->next = ifstack; ifstack = i; i->condstate = IFSTATE_FALSE; #ifdef DEBUG_IF if (debugging) { outputs("IFFALSE"); fflush(outfile); } #endif } int in_false_if(void) { return(ifstack && (ifstack->condstate != IFSTATE_TRUE)); } void maybe_print(char c) { extern int incldep; if (incldep) { return; } if ((c == '\n') || !in_false_if()) { outputc(c); } } char *Rindex(char *s, int c); int nIfiles; char **Ifiles; void init_include(void) { nIfiles = 0; Ifiles = (char **) malloc(1); check_malloc(Ifiles); } void Ifile(char *f) { Ifiles = (char **) realloc((char *)Ifiles,(nIfiles+1)*sizeof(char *)); check_malloc(Ifiles); Ifiles[nIfiles] = copyofstr(f); check_malloc(Ifiles[nIfiles]); nIfiles ++; } void do_include(int expr_sharp) { char c; char *acc; if (in_false_if()) { if (sharp) { flush_sharp_line(); } return; } while (1) { c = getnonspace(); if (isbsymchar(c)) { char *cp; DEF *d; cp = init_accum(); while (issymchar(c)) { accum_char(cp,c); c = Get(); } Push(c); cp = accum_result(cp); d = find_def(cp); if (d) { expand_def(d); n_hits ++; } else { char *dp; for (dp=cp+strlen(cp);dp>cp;dp--) Push(*dp); n_misses ++; } } else { break; } } acc = init_accum(); if (c == '"') { while (1) { c = Get(); if (c == '\n') { Push('\n'); c = '"'; err_head(); fprintf(stderr,"warning: unterminated %cinclude filename\n", sharp?'#':'@'); } if (c == '"') { break; } accum_char(acc,c); } if (sharp) { flush_sharp_line(); } read_include_file(accum_result(acc),1,sharp); } else if (c == '<') { while (1) { c = Get(); if (c == '\n') { Push('\n'); c = '>'; err_head(); fprintf(stderr,"warning: unterminated %cinclude filename\n", sharp?'#':'@'); } if (c == '>') { break; } accum_char(acc,c); } if (sharp) { flush_sharp_line(); } read_include_file(accum_result(acc),0,sharp); } else { free(accum_result(acc)); err_head(); fprintf(stderr,"illegal %cinclude filename delimiter\n",sharp?'#':'@'); } } #if defined(SYSV) #else #if defined(DELIM) #undef DELIM #endif #define DELIM '/' #endif #if defined(VISUAL) || defined(__MINGW32__) #if defined(DELIM) #undef DELIM #endif #define DELIM '\\' #endif void read_include_file(char *name, int dohere, int expr_sharp) { FILE *f; char *n; char temp[1024]; char *cp; extern int incldep; extern char *incldep_o; f = NULL; if (dohere) { if ((strcmp(curdir(),".") != 0) && (name[0] != DELIM)) { sprintf(temp,"%s%c%s",curdir(),DELIM,name); n = temp; } else { n = name; } f = fopen(n,"r"); } if (f == NULL) { if (name[0] == DELIM) { f = fopen(name,"r"); n = name; } else { int i; n = temp; for (i=0;i 0) { do { c = GET(); } while (c == NOEXPAND); if (c == MARKLINE) { mark_get_line(); continue; } mark_got_from_pushback(c); #ifdef DEBUG_IO if (debugging) { outputc('('); outputs(unctrl(c)); outputc(')'); fflush(outfile); } #endif break; } else { c = getc(cur_fstack); if (feof(cur_fstack)) { if (fstackdepth > 0) { #ifdef DEBUG_INCL if (debugging) { outputs("--eof:"); outputs(cur_fn); outputs("--"); } #endif fclose(cur_fstack); free(cur_fn); free(cur_incldir); change_fstackdepth(-1); mark_file_ending(); out_at(cur_lineno,cur_fn); autodef_file(curfile()); autodef_line(curline()); continue; } else { flush_final_nl(); save_stats(); #if 0 exit(0); #endif longjmp(cpp_env,1); } } mark_got_from_file(c); #ifdef DEBUG_IO if (debugging) { outputc('<'); outputs(unctrl(c)); outputc('>'); fflush(outfile); } #endif break; } } if (c == '\n') { cur_lineno ++; autodef_line(curline()); willbefirst = 1; } return(c); } void push_new_file(char *name, FILE *f) { change_fstackdepth(1); cur_fn = copyofstr(name); check_malloc(cur_fn); cur_lineno = 1; cur_fstack = f; cur_npushed = 0; #ifdef DEBUG_INCL if (debugging) { outputs("--newfile:"); outputs(name); outputs("--"); } #endif mark_file_beginning(); } void Push(char c) { if (cur_npushed > MAX_PUSHBACK) { fprintf(stderr,"too much pushback\n"); cur_npushed = 0; } PUSH() = c; mark_charpushed(); willbefirst = 0; if (c == '\n') { cur_lineno --; autodef_line(curline()); } #ifdef DEBUG_IO if (debugging) { outputc('['); outputs(unctrl(c)); outputc(']'); fflush(outfile); } #endif } char *curfile(void) { return(cur_fn); } char **Curfile(void) { return(&cur_fn); } int curline(void) { return(cur_lineno); } int *Curline(void) { return(&cur_lineno); } char *curdir(void) { return(cur_incldir); } char **Curdir(void) { return(&cur_incldir); } char getnonspace(void) { char c; while (isspace(c=Get())) ; return(c); } char getnonhspace(void) { char c; while (ishspace(c=Get())) ; return(c); } char getnhsexpand(void) { char c; while (1) { c = getexpand(); if (ishspace(c)) { continue; } if (expr_sharp && (c == '\\')) { c = Get(); if (c == '\n') { continue; } else { Push(c); c = '\\'; } } break; } return(c); } char getexpand(void) { char c; char *str; DEF *d; while (1) { c = Get(); if (c == '/') { char d; d = Get(); if (d == '*') { d = '\0'; do { c = d; d = Get(); } while ((c != '*') || (d != '/')); continue; } else { Push(d); return('/'); } } else if (c == NOEXPAND) { c = Get(); if (issymchar(c)) { Push(NOEXPAND); } return(c); } else if (! isbsymchar(c)) { return(c); } str = init_accum(); do { accum_char(str,c); } while (issymchar(c=Get())); Push(c); str = accum_result(str); if (d = find_def(str)) { expand_def(d); free(str); } else { int i; for (i=strlen(str)-1;i>0;i--) { Push(str[i]); } Push(NOEXPAND); c = str[0]; free(str); return(c); } } } char *read_ctrl(void) { char c; char *acc; acc = init_accum(); while (ishspace(c=Get())) ; Push(c); while (1) { c = Get(); if (islower(c)) { accum_char(acc,c); } else { Push(c); return(accum_result(acc)); } } } char *read_ident(void) { char *acc; char c; c = getnonspace(); if (! isbsymchar(c)) { Push(c); return(0); } acc = init_accum(); do { accum_char(acc,c); } while (issymchar(c=Get())); Push(c); return(accum_result(acc)); } void out_at(int line, char *file) { if ((line-nnls != atline) || strcmp(file,atfile)) { free(atfile); atline = line - nnls; atfile = copyofstr(file); check_malloc(atfile); done_line = 0; } } void outputc(char c) { extern int incldep; static char *white = 0; if (incldep) { return; } if (c == '\n') { nnls ++; if (white) { free(accum_result(white)); white = 0; } } else if ((nnls > 0) && ((c == ' ') || (c == '\t'))) { if (! white) { white = init_accum(); } accum_char(white,c); } else { if ((nnls > 2) || !done_line) { atline += nnls; nnls = 0; if (no_line_lines) { fprintf(outfile,"\n"); } else { fprintf(outfile,"\n# %d \"%s\"\n",atline,atfile); } done_line = 1; } for (;nnls;nnls--) { atline ++; putc('\n',outfile); } if (white) { white = accum_result(white); fputs(white,outfile); free(white); white = 0; } putc(c,outfile); } } void flush_final_nl(void) { if (nnls > 0) { putc('\n',outfile); } } void outputs(char *s) { for (;*s;s++) { outputc(*s); } } void outputd(int n) { char temp[64]; sprintf(temp,"%d",n); outputs(temp); } void mark_push_here(MARK *,int,char *); void input_mark(void) { MARK *m; m = NEW(MARK); check_malloc(m); m->link = marks; marks = m; m->startdepth = fstackdepth; m->acc = init_accum(); m->nignore = 0; m->nincs = 0; mark_push_here(m,curline(),curfile()); #ifdef DEBUG_IO if (debugging) { outputs("~MARK~"); } #endif } void input_unmark(void) { MARK *m; if (marks) { m = marks; marks = m->link; free(accum_result(m->acc)); OLD(m); #ifdef DEBUG_IO if (debugging) { outputs("~UNMARK~"); } #endif } } void input_recover(void) { register MARK *m; register char *txt; register int i; register int l; char c; if (marks) { m = marks; marks = m->link; #ifdef DEBUG_IO if (debugging) { outputs("~RECOVER~"); } #endif for (;m->nignore>0;m->nignore--) { accum_regret(m->acc); } txt = accum_result(m->acc); i = strlen(txt) - 1; while (m->nincs > 0) { l = m->incs[--m->nincs]; for (;i>=l;i--) { Push(txt[i]); } Push(MARKLEND); c = txt[i]; for (i--;txt[i]!=c;i--) { Push(txt[i]); } Push('A'); Push('@'); Push('@'); Push('@'); Push('@'); Push('@'); Push('@'); Push('@'); for (;(txt[i]!='#')&&(txt[i]!='@');i--) ; Push(MARKLINE); i --; } for (;i>=0;i--) { Push(txt[i]); } free(txt); OLD(m); } } void mark_file_beginning(void) { register MARK *m; for (m=marks;m;m=m->link) { m->incs[m->nincs++] = accum_howfar(m->acc); } } void mark_file_ending(void) { register MARK *m; register int i; register int to; register char *acc; for (m=marks;m;m=m->link) { if (m->startdepth > fstackdepth) { m->startdepth = fstackdepth; mark_push_here(m,curline(),curfile()); } else if (m->nincs <= 0) { fprintf(stderr,"INTERNAL BUG: nincs<0 in mark_file_ending\n"); abort(); } else { to = m->incs[--m->nincs]; acc = m->acc; for (i=accum_howfar(acc);i>to;i--) { accum_regret(acc); } } } } void mark_charpushed(void) { register MARK *m; for (m=marks;m;m=m->link) { m->nignore ++; } } void mark_got_from_pushback(char c) { mark_got(c); } void mark_got_from_file(char c) { mark_got(c); } void mark_got(char c) { register MARK *m; for (m=marks;m;m=m->link) { if (m->nignore > 0) { m->nignore --; } else { accum_char(m->acc,c); } } } void mark_push_here(MARK *m, int l, char *f) { int i; char c; switch (c=accum_regret(m->acc)) { case 0: break; case MARKLEND: while (accum_regret(m->acc) != MARKLINE) ; break; default: accum_char(m->acc,c); break; } accum_char(m->acc,MARKLINE); for (i=28;i>=0;i-=4) { accum_char(m->acc,(char)('@'+((l>>i)&0xf))); } for (;*f;f++) { accum_char(m->acc,*f); } accum_char(m->acc,MARKLEND); } void mark_get_line(void) { int l; char *f; int i; char c; MARK *m; l = 0; for (i=0;i<8;i++) { l = (l << 4) + (GET() & 0xf); } f = init_accum(); while ((c=GET()) != MARKLEND) { accum_char(f,c); } f = accum_result(f); out_at(l,f); for (m=marks;m;m=m->link) { mark_push_here(m,l,f); } free(f); } int ishspace(char c) { return((c == ' ') || (c == '\t')); } int isbsymchar(char c) { return(isalpha(c) || (c == '_')); } int issymchar(char c) { return(isalnum(c) || (c == '_') || (c == '$')); } void do_line(void) { char c; outputc('#'); while ((c=Get()) != '\n') { outputc(c); } } #define DEBUG_MAIN/**/ extern char **argvec; char *Index(char *s, int c); char *Rindex(char *s, int c); #ifdef DEBUG_MAIN extern int debugging; #endif static char quote; IF *ifstack; int n_skipped_ifs; int keep_comments; int no_line_lines; int incldep; char *incldep_o; int do_at_ctrls; extern char *predefs[]; #if defined(SYSV) void main(ac,av) #else void cpp_main(int ac, char **av) #endif { int argno; int rest; char *cp; static FILE *inf; static FILE *outf; char *inname; int backslash; int i; if ( setjmp(cpp_env) ) { if ( inf != stdin ) fclose(inf); if ( outf == stdout ) fflush(outf); else fclose(outf); return; } init_symtbl(); #define predef(str) ( (cp=copyofstr("1")), \ check_malloc(cp), \ define((str),-1,(unsigned char *)cp,DEF_PREDEF) ) for (i=0;predefs[i];i++) { predef(predefs[i]); } init_include(); inf = stdin; outf = stdout; inname = ""; keep_comments = 0; no_line_lines = 0; do_at_ctrls = 0; incldep = 0; argno = 0; for (ac--,av++;ac;ac--,av++) { if (**av == '-') { rest = 0; if (!strcmp(*av,"-undef")) { undef_predefs(); } else { for (++*av;(**av)&&!rest;++*av) { switch (**av) { case 'C': keep_comments = 1; break; case 'D': rest = 1; ++*av; if (strcmp(*av,"@") == 0) { do_at_ctrls = 1; } else { cp = Index(*av,'='); if (cp) { if (cp != *av) { char *dp; *cp++ = '\0'; dp = copyofstr(cp); check_malloc(dp); define(*av,-1,(unsigned char *)dp,DEF_CMDLINE); } else { fprintf(stderr,"Must give a name for -D\n"); } } else { char *dp; dp = copyofstr("1"); check_malloc(dp); define(*av,-1,(unsigned char *)dp,DEF_CMDLINE); } } break; case 'E': break; case 'I': rest = 1; ++*av; if (**av) { Ifile(*av); } else { fprintf(stderr,"Must give a directory name for -I\n"); } break; case 'M': incldep = 1; break; case 'P': no_line_lines = 1; break; case 'R': break; case 'U': rest = 1; ++*av; if (**av) { undef(*av); } else { fprintf(stderr,"Must give a name for -U\n"); } break; default: fprintf(stderr,"Unknown flag -%c\n",**av); break; } } } } else { switch (argno++) { case 0: if (strcmp(*av,"-") != 0) { FILE *f; f = fopen(*av,"r"); if (f == NULL) { fprintf(stderr,"Cannot open source file %s\n",*av); } else { inf = f; inname = *av; } } break; case 1: if (strcmp(*av,"-") != 0) { FILE *f; f = fopen(*av,"w"); if (f == NULL) { fprintf(stderr,"Can't create %s\n",*av); } else { outf = f; } } break; default: fprintf(stderr,"Extra name %s ignored\n",*av); break; } } } if (incldep && !inname[0]) { fprintf(stderr,"No input file for -M flag\n"); #if 0 exit(1); #endif longjmp(cpp_env,1); } if (do_at_ctrls) { predef("at_sign_ctrls"); } Ifile("/local/include"); Ifile("/usr/include"); willbefirst = 1; quote = 0; backslash = 0; init_io(inf,inname); outfile = outf; ifstack = 0; n_skipped_ifs = 0; cp = Rindex(inname,'/'); if (cp) { *cp = '\0'; init_incldir(inname); *cp = '/'; } else { init_incldir("."); } autodef_file(inname); autodef_line(1); out_at(1,inname); if (incldep) { char *dp; cp = Rindex(inname,'/'); if (cp) { cp ++; } else { cp = inname; } dp = cp + strlen(cp) - 2; if ((dp < cp) || strcmp(dp,".c")) { fprintf(stderr,"Missing .c in %s\n",inname); #if 0 exit(1); #endif longjmp(cpp_env,1); } incldep_o = copyofstr(cp); incldep_o[dp+1-cp] = 'o'; fprintf(outfile,"%s: ",incldep_o); fprintf(outfile,"%s\n",inname); } init_stats(); while (1) { char c; int haddigit; c = Get(); if (backslash) { maybe_print(c); backslash = 0; continue; } if (!incldep && (isdigit(c) || (c == '.'))) { haddigit = 0; while (isdigit(c) || (c == '.')) { haddigit |= isdigit(c); maybe_print(c); c = Get(); } if (haddigit && ((c == 'e') || (c == 'E'))) { maybe_print(c); c = Get(); while (isdigit(c)) { maybe_print(c); c = Get(); } } Push(c); continue; } if (quote) { if (c == '\\') { maybe_print(c); backslash = 1; continue; } else if ((c == quote) || (c == '\n')) { maybe_print(c); quote = 0; continue; } else { maybe_print(c); continue; } } if (c == '\\') /* this weirdness is Reiser semantics.... */ { backslash = 1; maybe_print(c); continue; } if ((c == '\'') || (c == '"')) { quote = c; maybe_print(c); } else if (linefirst && (c == '#')) { do_sharp(); } else if (do_at_ctrls && (c == '@')) { do_at(); } else if (! incldep) { if (isbsymchar(c) && !in_false_if()) { char *cp; DEF *d; cp = init_accum(); while (issymchar(c)) { accum_char(cp,c); c = Get(); } Push(c); cp = accum_result(cp); #ifdef DEBUG_MAIN if (debugging) { outputs(""); } #endif d = find_def(cp); if (d) { expand_def(d); n_hits ++; } else { for (;*cp;cp++) { maybe_print(*cp); } n_misses ++; } } else if (c == '/') { char d; d = Get(); if (d == '*') { d = '\0'; if (keep_comments) { maybe_print('/'); maybe_print('*'); } do { c = d; d = Get(); if ((d == '\n') || keep_comments) { maybe_print(d); } } while ((c != '*') || (d != '/')); } else { Push(d); maybe_print(c); } } else { maybe_print(c); } } } } void do_pragma(void) { char c; if (in_false_if()) { while ((c=Get()) != '\n') ; } else { outputc('#'); outputc('p'); outputc('r'); outputc('a'); outputc('g'); outputc('m'); outputc('a'); outputc(' '); while ((c=Get()) != '\n') { outputc(c); } } } char *predefs[] = { "mc68000", "unix", "NeXT", "__MACH__", 0 }; void do_set(void) { char *mac; char c; char temp[64]; mac = read_ident(); if (! mac) { err_head(); fprintf(stderr,"@set: missing/illegal macro name\n"); return; } if (! in_false_if()) { char *cp; c = getnonspace(); if (c != '(') { err_head(); fprintf(stderr,"@set must have ()s\n"); Push(c); return; } sprintf(temp,"%d",eval_expr(0,1)); undef(mac); cp = copyofstr(temp); check_malloc(cp); define(mac,-1,(unsigned char *)cp,DEF_DEFINE); } free(mac); } void do_sharp(void) { char *w; char c; w = read_ctrl(); if (strcmp(w,"ifdef") == 0) { do_ifdef(1); } else if (strcmp(w,"ifndef") == 0) { do_ifndef(1); } else if (strcmp(w,"if") == 0) { do_if(1); } else if (strcmp(w,"else") == 0) { do_else(1); } else if (strcmp(w,"elif") == 0) { do_elif(1); } else if (strcmp(w,"endif") == 0) { do_endif(1); } else if (strcmp(w,"include") == 0) { do_include(1); } else if (strcmp(w,"define") == 0) { do_define(1,0); } else if (strcmp(w,"undef") == 0) { do_undef(1); } else if (strcmp(w,"line") == 0) { do_line(); } else if (strcmp(w,"pragma") == 0) { do_pragma(); } else if (strcmp(w,"") == 0) { } else { int isnull; isnull = 0; if (strcmp(w,"") == 0) { c = Get(); if (c != '\n') { Push(c); } else { isnull = 1; } } if (!isnull && !in_false_if()) { err_head(); fprintf(stderr,"unknown control `%s'\n",w); flush_sharp_line(); } } maybe_print('\n'); free(w); } void flush_sharp_line(void) { int quote; int backslash; int comment; int lastc; int c; quote = 0; backslash = 0; comment = 0; c = 'x'; while (1) { lastc = c; c = Get(); if (backslash) { backslash = 0; continue; } if (comment) { if (c == '\\') { backslash = 1; } else if ((c == '/') && (lastc == '*')) { comment = 0; } continue; } if (quote) { if (c == '\\') { backslash = 1; } else if (c == quote) { quote = 0; } } switch (c) { case '\\': backslash = 1; continue; break; case '"': case '\'': quote = c; continue; break; case '*': comment = (lastc == '/'); continue; break; default: continue; break; case '\n': break; } break; } } int n_defines; int n_undefines; int n_hits; int n_misses; void init_stats(void) { n_defines = 0; n_undefines = 0; n_hits = 0; n_misses = 0; } void save_stats(void) { FILE *f; f = fopen("/@larry/u1/mouse/Mouse-C/cpp.stats","a"); if (f) { fprintf(f,"%d def, %d undef, %d hits, %d misses\n", n_defines,n_undefines,n_hits,n_misses); fclose(f); } } DEF **symtbl; int symtbl_size; int n_in_table; static int size_index; static int sizes[] = { 7, 37, 179, 719, 2003, 8009, 30011, 120011, 0 }; static int hash(unsigned char *s) { register unsigned int i; for (i=0;*s;s++) { i = (i >> 8) + (i << 3) + *s; } i &= ~0x80000000; return(i%symtbl_size); } void init_symtbl(void) { int i; symtbl_size = sizes[size_index=0]; symtbl = (DEF **) malloc(symtbl_size*sizeof(DEF *)); check_malloc(symtbl); for (i=0;ilink; h = hash((unsigned char *)d->name); d->link = symtbl[h]; symtbl[h] = d; } } free((char *)otbl); } void define(char *name, int nargs, unsigned char *repl, int how) { int h; DEF *d; char *n; n = copyofstr(name); h = hash((unsigned char *)n); for (d=symtbl[h];d;d=d->link) { if (strcmp(d->name,n) == 0) { break; } } if (d) { if ( (nargs != d->nargs) || strcmp((char *)repl,(char *)d->repl) ) { err_head(); fprintf(stderr,"%s redefined\n",n); } free((char *)d->repl); free(d->name); d->name = n; d->nargs = nargs; d->repl = repl; d->how = how; } else { d = NEW(DEF); check_malloc(d); d->name = n; d->nargs = nargs; d->repl = repl; d->how = how; d->link = symtbl[h]; symtbl[h] = d; n_in_table ++; if (n_in_table > 2*symtbl_size) { rehash_up(); } } if (strcmp(n,"at_sign_ctrls") == 0) { extern int do_at_ctrls; do_at_ctrls = 1; } } int undef(char *name) { int h; DEF **D; DEF *d; int rv; h = hash((unsigned char *)name); for (D=symtbl+h;*D;D= &(*D)->link) { if (strcmp((*D)->name,name) == 0) { break; } } rv = 0; if (d = *D) { *D = d->link; free(d->name); free((char *)d->repl); OLD(d); n_in_table --; rv = 1; } if (strcmp(name,"at_sign_ctrls") == 0) { extern int do_at_ctrls; do_at_ctrls = 0; } return rv; } DEF *find_def(char *name) { int h; DEF *d; h = hash((unsigned char *)name); for (d=symtbl[h];d;d=d->link) { if (strcmp(d->name,name) == 0) { break; } } return(d); } void defd(char *name, int value) { char temp[64]; char *cp; sprintf(temp,"%d",value); undef(name); cp = copyofstr(temp); check_malloc(cp); define(name,-1,(unsigned char *)cp,DEF_DEFINE); } void undef_predefs(void) { int h; DEF **D; DEF *d; for (h=symtbl_size-1;h>=0;h--) { D = symtbl + h; while (*D) { d = *D; if (d->how == DEF_PREDEF) { free(d->name); free((char *)d->repl); *D = d->link; OLD(d); n_in_table --; } else { D = &d->link; } } } } char *_unctrl[0400] = { "^@", "^A", "^B", "^C", "^D", "^E", "^F", "^G", "^H", "^I", "^J", "^K", "^L", "^M", "^N", "^O", "^P", "^Q", "^R", "^S", "^T", "^U", "^V", "^W", "^X", "^Y", "^Z", "^[", "^\\", "^]", "^^", "^_", " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "\\", "]", "^", "_", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{"/*}*/, "|", /*{*/"}", "~", "^?", "|^@", "|^A", "|^B", "|^C", "|^D", "|^E", "|^F", "|^G", "|^H", "|^I", "|^J", "|^K", "|^L", "|^M", "|^N", "|^O", "|^P", "|^Q", "|^R", "|^S", "|^T", "|^U", "|^V", "|^W", "|^X", "|^Y", "|^Z", "|^[", "|^\\", "|^]", "|^^", "|^_", "| ", "|!", "|\"", "|#", "|$", "|%", "|&", "|'", "|(", "|)", "|*", "|+", "|,", "|-", "|.", "|/", "|0", "|1", "|2", "|3", "|4", "|5", "|6", "|7", "|8", "|9", "|:", "|;", "|<", "|=", "|>", "|?", "|@", "|A", "|B", "|C", "|D", "|E", "|F", "|G", "|H", "|I", "|J", "|K", "|L", "|M", "|N", "|O", "|P", "|Q", "|R", "|S", "|T", "|U", "|V", "|W", "|X", "|Y", "|Z", "|[", "|\\", "|]", "|^", "|_", "|`", "|a", "|b", "|c", "|d", "|e", "|f", "|g", "|h", "|i", "|j", "|k", "|l", "|m", "|n", "|o", "|p", "|q", "|r", "|s", "|t", "|u", "|v", "|w", "|x", "|y", "|z", "|{"/*}*/, "||", /*{*/"|}", "|~", "|^?" }; char *_Unctrl[0400] = { "^@", "^A", "^B", "^C", "^D", "^E", "^F", "^G", "^H", "^I", "^J", "^K", "^L", "^M", "^N", "^O", "^P", "^Q", "^R", "^S", "^T", "^U", "^V", "^W", "^X", "^Y", "^Z", "^[", "^\\", "^]", "^^", "^_", "sp", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "\\", "]", "^", "_", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{"/*}*/, "|", /*{*/"}", "~", "^?", "|^@", "|^A", "|^B", "|^C", "|^D", "|^E", "|^F", "|^G", "|^H", "|^I", "|^J", "|^K", "|^L", "|^M", "|^N", "|^O", "|^P", "|^Q", "|^R", "|^S", "|^T", "|^U", "|^V", "|^W", "|^X", "|^Y", "|^Z", "|^[", "|^\\", "|^]", "|^^", "|^_", "|sp", "|!", "|\"", "|#", "|$", "|%", "|&", "|'", "|(", "|)", "|*", "|+", "|,", "|-", "|.", "|/", "|0", "|1", "|2", "|3", "|4", "|5", "|6", "|7", "|8", "|9", "|:", "|;", "|<", "|=", "|>", "|?", "|@", "|A", "|B", "|C", "|D", "|E", "|F", "|G", "|H", "|I", "|J", "|K", "|L", "|M", "|N", "|O", "|P", "|Q", "|R", "|S", "|T", "|U", "|V", "|W", "|X", "|Y", "|Z", "|[", "|\\", "|]", "|^", "|_", "|`", "|a", "|b", "|c", "|d", "|e", "|f", "|g", "|h", "|i", "|j", "|k", "|l", "|m", "|n", "|o", "|p", "|q", "|r", "|s", "|t", "|u", "|v", "|w", "|x", "|y", "|z", "|{"/*}*/, "||", /*{*/"|}", "|~", "|^?" }; void do_undef(int expr_sharp) { char *mac; if (! in_false_if()) { mac = read_ident(); if (! mac) { err_head(); fprintf(stderr,"missing/illegal macro name\n"); } else { if (undef(mac)) { n_undefines ++; } } } if (sharp) { flush_sharp_line(); } } /*#define DEBUG_WHILE/**/ #ifdef DEBUG_WHILE extern int debugging; #endif void do_while(void) { input_mark(); do_if(0); } void do_endwhile(void) { if (in_false_if()) { do_endif(0); input_unmark(); #ifdef DEBUG_WHILE if (debugging) { outputs("//endwhile:"); outputd(curline()); outputs(","); outputs(curfile()); outputs("\\\\"); } #endif out_at(curline(),curfile()); } else { do_endif(0); input_recover(); input_mark(); do_if(0); } } char *Index(char *s, int c) { return strchr(s,c); } char *Rindex(char *s, int c) { return strrchr(s,c); } void Bcopy(char *from, char *to, int len) { #if defined(GO32) bcopy(from,to,len); #else memmove((void *)from,(void *)to,(int)len); #endif }