home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg
- *
- * Permission is granted to anyone to use this software for any purpose
- * on any computer system, and to redistribute it freely, with the
- * following restrictions:
- * 1) No charge may be made other than reasonable charges for reproduction.
- * 2) Modified versions must be clearly marked as such.
- * 3) The authors are not responsible for any harmful consequences
- * of using this software, even if they result from defects in it.
- *
- * pre.c
- *
- * preprocessor for the compiler
- *
- * Handles all preprocessor (#) commands and
- * looks up keywords
- *
- * Interface:
- * getnode() returns next "token node"
- */
-
- #include <stdio.h>
- #include "param.h"
- #include "tok.h"
- #include "nodes.h"
-
- #if CC68
- FILE *fopenb();
- #define fopen fopenb
- #endif
-
- extern struct tok curtok;
- extern char curstr[];
-
- #define TK_SEENL 1 /* want to see NL token */
- #define TK_SEEWS 2 /* want to see WS token */
- #define TK_ONLY1 4 /* only want 1st token on line */
- #define TK_LTSTR 8 /* '<' starts a string */
- #define TK_NOESC 16 /* dont do '\' escapes in string */
-
- extern int tk_flags, sawnl;
-
- #ifndef ACK_HOST
- NODE *deflist[NHASH];
- NODE *holdtok;
- int iflevel, iftruth, ifnest, in_if_x, skip_id;
- #else
- #if PART_1
- NODE *deflist[NHASH];
- NODE *holdtok;
- extern int iflevel, iftruth, ifnest, in_if_x, skip_id;
- #else
- extern NODE *deflist[NHASH];
- extern NODE *holdtok;
- int iflevel, iftruth, ifnest, in_if_x, skip_id;
- #endif
- #endif
-
- extern lineno;
- extern char *inname;
- extern FILE *input;
-
- NODE *hlook(), *llook();
- NODEP tok_to_node();
- NODE *copylist();
-
- #ifdef DEBUG
- extern int oflags[];
- #define debugd oflags['d'-'a']
- #define debugt oflags['t'-'a']
- #endif
-
- #ifndef ACK_HOST
- #define PART_1 1
- #define PART_2 1
- #endif
-
- #if PART_1
-
- NODEP
- hi_node()
- {
- register NODEP rv;
-
- /* node from hold queue ? */
- if (holdtok) {
- #ifdef DEBUG
- if (debugd > 2) {
- printf("Holdqueue");
- printnode(holdtok);
- }
- #endif
- rv = holdtok;
- holdtok = rv->n_next;
- rv->n_next = NULL;
- return rv;
- }
- /* node from input */
- again:
- while (iflevel && !iftruth)
- skiplines();
- if (nxttok()==0)
- return NULL;
- if (curtok.tnum == '#') {
- dopound(0);
- goto again;
- }
- rv = tok_to_node();
- return rv;
- }
-
- NODEP
- getnode()
- {
- register NODEP rv;
- NODEP dp;
-
- again:
- rv = hi_node();
- if (rv == NULL) {
- rv = allocnode();
- rv->e_token = EOFTOK;
- strcpy(rv->n_name, "*EOF*");
- } else
- if (rv->e_token == ID) {
- if (in_if_x && strcmp(rv->n_name, "defined") == 0) {
- skip_id = 1;
- goto out;
- }
- if (skip_id) {
- skip_id = 0;
- goto out;
- }
- if ((dp = hlook(deflist, rv)) != NULL) {
- expand(dp);
- freenode(rv);
- goto again;
- } else if (rv->n_name[0] == '_' && builtin(rv))
- return rv;
- else
- kw_tok(rv);
- }
- out:
- #ifdef DEBUG
- if (debugt) {
- putchar('[');
- put_nnm(rv);
- printf("] ");
- }
- #endif
- return rv;
- }
-
- builtin(np)
- register NODEP np;
- {
- int rv;
-
- if (strcmp(np->n_name, "__LINE__") == 0) {
- np->e_token = ICON;
- np->e_ival = lineno;
- return 1;
- }
- else if (strcmp(np->n_name, "__FILE__") == 0) {
- np->e_token = SCON;
- nscpy(np, inname);
- return 1;
- }
- return 0;
- }
-
- skiplines()
- {
- for (;;) {
- if (nxttok()== 0)
- return;
- if (curtok.tnum == '#') {
- dopound(1);
- return;
- }
- tk_flags |= TK_ONLY1;
- }
- }
-
- static defnargs;
-
- p_def()
- {
- NODE *args;
- NODE *val;
- NODE *def;
- NODE *def_rgs(), *def_val();
-
- defnargs = -1;
- args = NULL;
- val = NULL;
- nxttok();
- if (curtok.tnum != ID) {
- error("bad #define");
- goto flush;
- }
- def = tok_to_node();
-
- tk_flags |= TK_SEEWS;
- nxttok();
- switch (curtok.tnum) {
- case '(':
- defnargs = 0;
- args = def_rgs();
- case WS:
- goto getval;
- case NL:
- goto dodef;
- default:
- error("bad #define");
- goto flush;
- }
- getval:
- val = def_val();
- dodef:
- def->e_ival = defnargs;
- define(def, val, args);
- flush:
- ;
- }
-
- optdef(s,as)
- char *s, *as;
- {
- NODEP val;
- NODEP def;
- NODEP id_tok(), def_val();
-
- defnargs = -1;
- val = NULL;
-
- def = id_tok(s);
- chr_push(as);
-
- tk_flags |= TK_SEENL;
-
- val = def_val();
-
- tk_flags = 0;
-
- def->e_ival = defnargs;
- define(def, val, NULL);
- }
-
- /*
- optundef(s)
- char *s;
- {
- NODEP np, tp, id_tok();
-
- np = id_tok(s);
- tp = hlook(deflist, np);
- if (tp != NULL)
- tp->n_name[0] = '#';
- freenode(np);
- }
- */
-
- samedef(p1, p2)
- NODEP p1, p2;
- {
- if (p1->e_ival != p2->e_ival)
- return 0;
- return same_list(p1->n_right, p2->n_right);
- }
-
- same_list(p1, p2)
- NODEP p1, p2;
- {
- if (p1 == NULL)
- return p2 == NULL;
- if (p2 == NULL)
- return 0;
- if (l_cmp(p1, p2, sizeof(*p1)/sizeof(long)) != 0)
- return 0;
- return same_list(p1->n_left, p2->n_left);
- }
-
- l_cmp(p1, p2, n)
- NODE *p1, *p2;
- {
- if (xstrcmp(p1,p2) != 0)
- return 1;
- if (p1->e_token != p2->e_token ||
- p1->e_ival != p2->e_ival)
- return 1;
- return 0;
- }
-
- define(def, val, args)
- NODEP def, val, args;
- {
- NODEP oldp;
-
- if (args != NULL) {
- argsmod(val, args);
- freenode(args);
- }
- def->n_right = val;
- if ((oldp = hlook(deflist, def)) != NULL) {
- if (!samedef(oldp, def))
- warnn("redefined", def);
- }
- #ifdef DEBUG
- if (debugd) {
- printf("define (%d args)", (int)def->e_ival);
- printnode(def);
- }
- #endif
- puthlist(deflist, def);
- }
-
- argsmod(toks, args)
- NODEP toks, args;
- {
- register NODE *np, *vp;
-
- for (np=toks; np != NULL; np = np->n_next)
- if (np->e_token == ID) {
- vp = llook(args,np);
- if (vp != NULL) {
- np->e_token = DPARAM;
- np->e_ival = vp->e_ival;
- sprintf(np->n_name, "\\%d", (int)np->e_ival);
- }
- }
- }
-
- NODE *
- def_rgs()
- {
- NODE *rv;
- NODE *tail;
- NODE *np;
-
- rv = NULL;
- tail = NULL;
- nxttok();
- if (curtok.tnum == ')') {
- goto out;
- }
- more:
- if (curtok.tnum != ID) {
- error("expect ID");
- goto bad;
- }
- np = tok_to_node();
- np->e_ival = defnargs; /* hold sequence number */
- defnargs++;
- if (tail == NULL) { /* first one */
- rv = np;
- tail = np;
- } else { /* more */
- tail->n_next = np;
- tail = np;
- }
- nxttok();
- if (curtok.tnum == ',') {
- nxttok();
- goto more;
- }
- if (curtok.tnum == ')')
- goto out;
- error("define arg syntax");
- bad:
- freenode(rv);
- rv = NULL;
- defnargs = 0;
- out:
- return rv;
- }
-
- NODE *
- def_val()
- {
- NODE *rv;
- NODE *tail;
- NODE *np;
-
- rv = NULL;
- tail = NULL;
- more:
- nxttok();
- if (curtok.tnum == NL) {
- goto out;
- /*
- } else if (curtok.tnum == '\\') {
- nxttok();
- if (curtok.tnum != NL)
- goto bad;
- goto more;
- */
- }
- np = tok_to_node();
- if (tail == NULL) { /* first one */
- rv = np;
- tail = np;
- } else { /* more */
- tail->n_next = np;
- tail = np;
- }
- goto more;
-
- bad:
- freenode(rv);
- rv = NULL;
- out:
- return rv;
- }
-
- NODE *
- gath1(sep)
- int *sep;
- {
- NODE *np, *rv, *tail;
- int inparen;
-
- inparen = 0;
- rv = NULL;
- tail = NULL;
- more:
- np = hi_node();
- if (np == NULL) {
- goto bad;
- }
- switch (np->e_token) {
- case ')':
- case ',':
- if (inparen) { /* dont end, part of subexpr */
- if (np->e_token == ')')
- inparen--;
- break;
- }
- *sep = np->e_token;
- freenode(np);
- goto out;
- case '(':
- inparen++;
- break;
- }
- if (tail == NULL) { /* first one */
- rv = np;
- tail = np;
- } else { /* more */
- tail->n_next = np;
- tail = np;
- }
- goto more;
- bad:
- freenode(rv);
- rv = NULL;
- *sep = 0;
- out:
- return rv;
- }
-
- NODE *
- gath_args(n)
- {
- NODE *rv;
- NODE *tail;
- NODE *np;
- int sep;
- int getn;
-
- getn = 0;
- rv = NULL;
- tail = NULL;
- np = hi_node();
- if (np->e_token != '(') {
- error("expect (");
- goto bad;
- }
- freenode(np);
- if (n == 0) {
- np = hi_node();
- if (np->e_token != ')') {
- error("expect )");
- goto bad;
- }
- freenode(np);
- return NULL;
- }
- more:
- np = gath1(&sep);
- if (np == NULL) {
- error("expect arg");
- goto bad;
- }
- getn++;
- if (tail == NULL) { /* first one */
- rv = np;
- tail = np;
- } else { /* more */
- tail->n_right = np;
- tail = np;
- }
- if (sep) switch (sep) {
- case ',':
- goto more;
- case ')':
- if (getn != n) {
- error("arg num mismatch");
- goto bad;
- }
- goto out;
- }
- error("expand arg syntax");
- bad:
- freenode(rv);
- rv = NULL;
- out:
- return rv;
- }
-
- NODE *
- argfix(val, args, rt)
- NODE *val, *args;
- NODE **rt;
- {
- register NODE *scan, *sub;
- NODE *head;
- NODE *tail, *back;
- NODE *rthnode();
- NODE *copylist();
-
- head = val;
- back = NULL;
- for (scan = val; scan != NULL; back=scan, scan=scan->n_next)
- if (scan->e_token == DPARAM) {
- sub = rthnode(args, (int)scan->e_ival);
- sub = copylist(sub,&tail);
- if (back) {
- back->n_next = sub;
- tail->n_next = scan->n_next;
- } else {
- head = sub;
- tail->n_next = scan->n_next;
- }
- scan->n_next = NULL;
- freenode(scan);
- scan = tail;
- }
- *rt = back;
- return head;
- }
-
- expand(dp)
- NODEP dp;
- {
- int nargs;
- NODEP args;
- register NODEP val;
- NODEP tail;
-
- val = dp->n_right;
- if (val)
- val = copylist(val, &tail);
- nargs = dp->e_ival;
- if (nargs >= 0) {
- args = gath_args(nargs);
- if (args) {
- if (val)
- val = argfix(val,args,&tail);
- freenode(args);
- }
- }
- if (val == NULL)
- return;
- #ifdef DEBUG
- if (debugd > 1) {
- printf("Expand");
- printnode(val);
- }
- #endif
- tail->n_next = holdtok;
- holdtok = val;
- }
-
- p_undef()
- {
- NODEP np, tp;
-
- nxttok();
- if (curtok.tnum != ID) {
- error("bad #undef");
- goto out;
- }
- tp = tok_to_node();
- if ((np = hlook(deflist, tp)) != NULL)
- /* quick and dirty */
- np->n_name[0] = '#';
- freenode(tp);
- out:
- ;
- }
-
- #endif
- #if PART_2
-
- p_inc()
- {
- int chkhere;
- FILE *newf, *srch_open();
- char *scopy(), *newnm;
-
- tk_flags |= TK_NOESC|TK_LTSTR;
- nxttok();
- switch (curtok.tnum) {
- case SCON:
- chkhere = 1;
- break;
- case SCON2:
- chkhere = 0;
- break;
- case NL:
- case EOF:
- error("bad #include");
- return;
- }
- newf = srch_open(curstr, chkhere);
- if (newf == NULL) {
- fatals("Cant open ", curstr);
- return;
- }
- newnm = scopy(curstr);
- do
- nxttok();
- while (curtok.tnum != NL);
- newfile(newf,newnm);
- }
-
- int inclvl;
- struct svinc {
- int lineno;
- FILE *fd;
- char *filenm;
- } svincs[MAXINCL];
-
- #if NEEDBUF
- char p_buf[MAXINCL][BUFSIZ];
- #endif
-
- static char obuf[MAXSTR];
-
- newfile(fd,s)
- FILE *fd;
- char *s;
- {
- register struct svinc *p;
-
- inclvl++;
- if (inclvl > MAXINCL) {
- inclvl--;
- fclose(fd);
- error("too many includes");
- return;
- }
- p = &svincs[inclvl-1];
- p->lineno = lineno;
- p->fd = input;
- p->filenm = inname;
- input = fd;
- lineno = 1;
- inname = s;
- #if NEEDBUF
- setbuf(input, p_buf[inclvl-1]);
- #endif
- }
-
- endfile()
- {
- register struct svinc *p;
-
- if (inclvl == 0)
- return 0;
- fclose(input);
- inclvl--;
- p = &svincs[inclvl];
- sfree(inname);
- input = p->fd;
- lineno = p->lineno;
- inname = p->filenm;
- return 1;
- }
-
- #define MAXIDIR 10
-
- #ifndef FOR_AMIGA
- #ifndef MINIX
- char *srchlist[MAXIDIR] = {
- "",
- "\\include\\",
- "\\sozobon\\include\\",
- "",
- 0
- };
- static int idir_n = 4; /* number of entries in above table */
- #else
- char *srchlist[MAXIDIR] = {
- "",
- "/usr/include/",
- 0
- };
- static int idir_n = 2;
- #endif
- #else
- char *srchlist[MAXIDIR] = {
- "",
- "include:",
- 0
- };
- static int idir_n = 2; /* number of entries in above table */
- #endif
-
- static int idir_put = 1; /* where to put -I dirs */
-
- optincl(s)
- char *s;
- {
- register char **pp;
-
- if (idir_n >= MAXIDIR-1) {
- warn("too many -I dirs");
- return;
- }
- for (pp = &srchlist[idir_n]; pp > &srchlist[idir_put]; ) {
- pp--;
- pp[1] = pp[0];
- }
- *pp = s;
- idir_put++;
- idir_n++;
- }
-
- FILE *
- srch_open(s, chkhere)
- char *s;
- {
- char **dir;
- FILE *fd;
-
- dir = srchlist;
- if (chkhere == 0) dir++;
- while (*dir) {
- strcpy(obuf, *dir);
- strcat(obuf, s);
- fd = fopen(obuf, ROPEN);
- if (fd != NULL) {
- return fd;
- }
- dir++;
- }
- return NULL;
- }
-
- p_if(kind,skipping)
- {
- int truth;
- NODEP tp;
-
- if (skipping) {
- ifnest++;
- return;
- }
- switch (kind) {
- case 0:
- truth = if_expr();
- break;
- case 1:
- case 2:
- nxttok();
- if (curtok.tnum != ID) {
- error("bad #if(n)def");
- goto flush;
- }
- tp = tok_to_node();
- truth = (hlook(deflist, tp) != NULL);
- freenode(tp);
- if (kind == 2)
- truth = !truth;
- }
- iflevel++;
- iftruth = truth;
- flush:
- ;
- }
-
- if_expr()
- {
- NODE *tp, *questx();
- extern NODE *cur;
- int rv;
-
- in_if_x = 1;
- skip_id = 0;
- advnode();
- tp = questx();
- in_if_x = 0;
- skip_id = 0;
- if (tp) {
- pnames(tp);
- rv = conxval(tp);
- } else
- rv = 0;
- if (cur->e_token != NL) {
- error("bad #if");
- } else
- freenode(cur);
- return rv;
- }
-
- pnames(np)
- register NODEP np;
- {
- again:
- if (np->e_token == ID) {
- np->e_token = ICON;
- np->e_ival = 0;
- } else if (np->e_token == '(') {
- NODEP rp, lp;
- int truth;
-
- rp = np->n_right;
- lp = np->n_left;
- if (lp->e_token == ID && strcmp(lp->n_name, "defined") == 0
- && rp && rp->e_token == ID) {
- truth = (hlook(deflist, rp) != NULL);
- freenode(rp);
- freenode(lp);
- np->n_left = NULL;
- np->n_right = NULL;
- np->e_token = ICON;
- np->e_ival = truth;
- }
- }
- if (np->n_right)
- pnames(np->n_right);
- np = np->n_left;
- if (np)
- goto again;
- }
-
- p_swit(kind,skipping)
- {
- if (skipping && ifnest) {
- if (kind == 1)
- ifnest--;
- return;
- }
- if (iflevel == 0) {
- error("not in #if");
- goto out;
- }
- switch (kind) {
- case 0: /* else */
- iftruth = !iftruth;
- break;
- case 1: /* endif */
- iflevel--;
- iftruth = 1;
- break;
- }
- out:
- ;
- }
-
- p_line()
- {
- char *scopy();
-
- nxttok();
- if (curtok.tnum != ICON) {
- error("bad #line");
- goto flush;
- }
- tk_flags |= TK_NOESC;
- nxttok();
- if (curtok.tnum == SCON) {
- sfree(inname);
- inname = scopy(curtok.name);
- }
- lineno = curtok.ival;
- flush:
- ;
- }
-
- struct cmds {
- char *name;
- int (*fun)();
- int arg;
- int skip;
- } pcmds[] = {
- {"define", p_def, 0, 1},
- {"undef", p_undef, 0, 1},
- {"include", p_inc, 0, 1},
- {"if", p_if, 0, 0},
- {"ifdef", p_if, 1, 0},
- {"ifndef", p_if, 2, 0},
- {"else", p_swit, 0, 0},
- {"endif", p_swit, 1, 0},
- {"line", p_line, 0, 1},
- {0}
- };
-
- dopound(skipping)
- {
- register struct cmds *p;
- register char *cname;
-
- tk_flags |= TK_SEENL;
- sawnl = 0;
- nxttok();
- if (curtok.tnum != ID) {
- error("expect name");
- return;
- }
- cname = curtok.name;
- for (p=pcmds; p->name; p++)
- if (strcmp(p->name, cname) == 0) {
- if (!skipping || !p->skip)
- (*p->fun)(p->arg, skipping);
- tk_flags = 0;
- if (sawnl == 0)
- tk_flags |= TK_ONLY1;
- return;
- }
- error("bad # command");
- }
-
- NODEP
- tok_to_node()
- {
- register struct tok *tp;
- register NODEP np;
-
- tp = &curtok;
- np = allocnode();
- np->e_token = tp->tnum;
- np->e_flags = tp->flags;
- if (tp->prec) /* binary op */
- np->e_prec = tp->prec;
- else
- switch (np->e_token) {
- case ICON:
- np->e_ival = tp->ival;
- break;
- case FCON:
- np->e_fval = tp->fval;
- break;
- }
- nscpy(np, tp->name);
- return np;
- }
-
- NODEP
- id_tok(s)
- char *s;
- {
- NODEP np;
-
- np = allocnode();
- np->e_token = ID;
- nscpy(np, s);
- return np;
- }
-
- #endif
-