home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d193 / zc.lha / Zc / pre.c < prev    next >
C/C++ Source or Header  |  1989-03-13  |  13KB  |  875 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  *
  11.  *    pre.c
  12.  *
  13.  *    preprocessor for the compiler
  14.  *
  15.  *    Handles all preprocessor (#) commands and
  16.  *      looks up keywords
  17.  *
  18.  *    Interface:
  19.  *        getnode()       returns next "token node"
  20.  */
  21.  
  22. #include <stdio.h>
  23. #include "param.h"
  24. #include "tok.h"
  25. #include "nodes.h"
  26.  
  27. #if CC68
  28. FILE *fopenb();
  29. #define fopen fopenb
  30. #endif
  31.  
  32. NODE *deflist[NHASH];
  33.  
  34. extern struct tok curtok;
  35. extern char curstr[];
  36.  
  37. #define TK_SEENL    1    /* want to see NL token */
  38. #define TK_SEEWS    2    /* want to see WS token */
  39. #define TK_ONLY1    4    /* only want 1st token on line */
  40. #define TK_LTSTR    8    /* '<' starts a string */
  41. #define TK_NOESC    16    /* dont do '\' escapes in string */
  42.  
  43. extern int tk_flags, sawnl;
  44.  
  45. NODE *holdtok;
  46.  
  47. extern lineno;
  48. extern char *inname;
  49. extern FILE *input;
  50.  
  51. int iflevel, iftruth, ifnest;
  52.  
  53. NODE *hlook(), *llook();
  54. NODEP tok_to_node();
  55. NODE *copylist();
  56.  
  57. #ifdef DEBUG
  58. extern int oflags[];
  59. #define debugd    oflags['d'-'a']
  60. #define debugt    oflags['t'-'a']
  61. #endif
  62.  
  63. NODEP
  64. hi_node()
  65. {
  66.     register NODEP rv;
  67.  
  68.     /* node from hold queue ? */
  69.     if (holdtok) {
  70. #ifdef DEBUG
  71.         if (debugd > 2) {
  72.             printf("Holdqueue");
  73.             printnode(holdtok);
  74.         }
  75. #endif
  76.         rv = holdtok;
  77.         holdtok = rv->n_next;
  78.         rv->n_next = NULL;
  79.         return rv;
  80.     }
  81.     /* node from input */
  82. again:
  83.     while (iflevel && !iftruth)
  84.         skiplines();
  85.     if (nxttok()==0)
  86.         return NULL;
  87.     if (curtok.tnum == '#') {
  88.         dopound(0);
  89.         goto again;
  90.     }
  91.     rv = tok_to_node();
  92.     return rv;
  93. }
  94.  
  95. NODEP
  96. getnode()
  97. {
  98.     register NODEP rv;
  99.     NODEP dp;
  100.  
  101. again:
  102.     rv = hi_node();
  103.     if (rv == NULL) {
  104.         rv = allocnode();
  105.         rv->e_token = EOFTOK;
  106.         strcpy(rv->n_name, "*EOF*");
  107.     } else
  108.     if (rv->e_token == ID) {
  109.         if ((dp = hlook(deflist, rv)) != NULL) {
  110.             expand(dp);
  111.             freenode(rv);
  112.             goto again;
  113.         } else
  114.             kw_tok(rv);
  115.     }
  116. #ifdef DEBUG
  117.     if (debugt) {
  118.         putchar('[');
  119.         put_nnm(rv);
  120.         printf("] ");
  121.     }
  122. #endif
  123.     return rv;
  124. }
  125.  
  126. skiplines()
  127. {
  128.     for (;;) {
  129.         if (nxttok()== 0)
  130.             return;
  131.         if (curtok.tnum == '#') {
  132.             dopound(1);
  133.             return;
  134.         }
  135.         tk_flags |= TK_ONLY1;
  136.     }
  137. }
  138.  
  139. static defnargs;
  140.  
  141. p_def()
  142. {
  143.     NODE *args;
  144.     NODE *val;
  145.     NODE *def;
  146.     NODE *def_rgs(), *def_val();
  147.  
  148.     defnargs = -1;
  149.     args = NULL;
  150.     val = NULL;
  151.     nxttok();
  152.     if (curtok.tnum != ID) {
  153.         error("bad #define");
  154.         goto flush;
  155.     }
  156.     def = tok_to_node();
  157.  
  158.     tk_flags |= TK_SEEWS;
  159.     nxttok();
  160.     switch (curtok.tnum) {
  161.     case '(':
  162.         defnargs = 0;
  163.         args = def_rgs();
  164.     case WS:
  165.         goto getval;
  166.     case NL:
  167.         goto dodef;
  168.     default:
  169.         error("bad #define");
  170.         goto flush;
  171.     }
  172. getval:
  173.     val = def_val();
  174. dodef:
  175.     def->e_ival = defnargs;
  176.     define(def, val, args);
  177. flush:
  178.     ;
  179. }
  180.  
  181. optdef(s)
  182. char *s;
  183. {
  184.     NODEP val;
  185.     NODEP def;
  186.     NODEP id_tok(), def_val();
  187.     char *as, *strchr();
  188.  
  189.     as = strchr(s, '=');
  190.     if (as)
  191.         *as++ = 0;
  192.     else
  193.         as = "1";
  194.  
  195.     defnargs = -1;
  196.     val = NULL;
  197.  
  198.     def = id_tok(s);
  199.     chr_push(as);
  200.  
  201.     tk_flags |= TK_SEENL;
  202.  
  203.     val = def_val();
  204.  
  205.     tk_flags = 0;
  206.  
  207.     def->e_ival = defnargs;
  208.     define(def, val, NULL);
  209. }
  210.  
  211. optundef(s)
  212. char *s;
  213. {
  214.     NODEP np, tp, id_tok();
  215.  
  216.     np = id_tok(s);
  217.     tp = hlook(deflist, np);
  218.     if (tp != NULL)
  219.         tp->n_name[0] = '#';
  220.     freenode(np);
  221. }
  222.  
  223. samedef(p1, p2)
  224. NODEP p1, p2;
  225. {
  226.     if (p1->e_ival != p2->e_ival)
  227.         return 0;
  228.     return same_list(p1->n_right, p2->n_right);
  229. }
  230.  
  231. same_list(p1, p2)
  232. NODEP p1, p2;
  233. {
  234.     if (p1 == NULL)
  235.         return p2 == NULL;
  236.     if (p2 == NULL)
  237.         return 0;
  238.     if (l_cmp(p1, p2, sizeof(*p1)/sizeof(long)) != 0)
  239.         return 0;
  240.     return same_list(p1->n_left, p2->n_left);
  241. }
  242.  
  243. l_cmp(p1, p2, n)
  244. NODE *p1, *p2;
  245. {
  246.     if (xstrcmp(p1,p2) != 0)
  247.         return 1;
  248.     if (p1->e_token != p2->e_token ||
  249.         p1->e_ival != p2->e_ival)
  250.         return 1;
  251.     return 0;
  252. }
  253.  
  254. define(def, val, args)
  255. NODEP def, val, args;
  256. {
  257.     NODEP oldp;
  258.  
  259.     if (args != NULL) {
  260.         argsmod(val, args);
  261.         freenode(args);
  262.     }
  263.     def->n_right = val;
  264.     if ((oldp = hlook(deflist, def)) != NULL) {
  265.         if (!samedef(oldp, def))
  266.             warnn("redefined", def);
  267.     }
  268. #ifdef DEBUG
  269.     if (debugd) {
  270.         printf("define (%d args)", (int)def->e_ival);
  271.         printnode(def);
  272.     }
  273. #endif
  274.     puthlist(deflist, def);
  275. }
  276.  
  277. argsmod(toks, args)
  278. NODEP toks, args;
  279. {
  280.     register NODE *np, *vp;
  281.  
  282.     for (np=toks; np != NULL; np = np->n_next)
  283.         if (np->e_token == ID) {
  284.             vp = llook(args,np);
  285.             if (vp != NULL) {
  286.                 np->e_token = DPARAM;
  287.                 np->e_ival = vp->e_ival;
  288.                 sprintf(np->n_name, "\\%d", (int)np->e_ival);
  289.             }
  290.         }
  291. }
  292.  
  293. NODE *
  294. def_rgs()
  295. {
  296.     NODE *rv;
  297.     NODE *tail;
  298.     NODE *np;
  299.  
  300.     rv = NULL;
  301.     tail = NULL;
  302.     nxttok();
  303.     if (curtok.tnum == ')') {
  304.         goto out;
  305.     }
  306. more:
  307.     if (curtok.tnum != ID) {
  308.         error("expect ID");
  309.         goto bad;
  310.     }
  311.     np = tok_to_node();
  312.     np->e_ival = defnargs;    /* hold sequence number */
  313.     defnargs++;
  314.     if (tail == NULL) {     /* first one */
  315.         rv = np;
  316.         tail = np;
  317.     } else {            /* more */
  318.         tail->n_next = np;
  319.         tail = np;
  320.     }
  321.     nxttok();
  322.     if (curtok.tnum == ',') {
  323.         nxttok();
  324.         goto more;
  325.     }
  326.     if (curtok.tnum == ')')
  327.         goto out;
  328.     error("define arg syntax");
  329. bad:
  330.     freenode(rv);
  331.     rv = NULL;
  332.     defnargs = 0;
  333. out:
  334.     return rv;
  335. }
  336.  
  337. NODE *
  338. def_val()
  339. {
  340.     NODE *rv;
  341.     NODE *tail;
  342.     NODE *np;
  343.  
  344.     rv = NULL;
  345.     tail = NULL;
  346. more:
  347.     nxttok();
  348.     if (curtok.tnum == NL) {
  349.         goto out;
  350. /*
  351.     } else if (curtok.tnum == '\\') {
  352.         nxttok();
  353.         if (curtok.tnum != NL)
  354.             goto bad;
  355.         goto more;
  356. */
  357.     }
  358.     np = tok_to_node();
  359.     if (tail == NULL) {     /* first one */
  360.         rv = np;
  361.         tail = np;
  362.     } else {            /* more */
  363.         tail->n_next = np;
  364.         tail = np;
  365.     }
  366.     goto more;
  367.  
  368. bad:
  369.     freenode(rv);
  370.     rv = NULL;
  371. out:
  372.     return rv;
  373. }
  374.  
  375. NODE *
  376. gath1(sep)
  377. int *sep;
  378. {
  379.     NODE *np, *rv, *tail;
  380.     int inparen;
  381.  
  382.     inparen = 0;
  383.     rv = NULL;
  384.     tail = NULL;
  385. more:
  386.     np = hi_node();
  387.     if (np == NULL) {
  388.         goto bad;
  389.     }
  390.     switch (np->e_token) {
  391.     case ')':
  392.     case ',':
  393.         if (inparen) {  /* dont end, part of subexpr */
  394.             if (np->e_token == ')')
  395.                 inparen--;
  396.             break;
  397.         }
  398.         *sep = np->e_token;
  399.         freenode(np);
  400.         goto out;
  401.     case '(':
  402.         inparen++;
  403.         break;
  404.     }
  405.     if (tail == NULL) {     /* first one */
  406.         rv = np;
  407.         tail = np;
  408.     } else {            /* more */
  409.         tail->n_next = np;
  410.         tail = np;
  411.     }
  412.     goto more;
  413. bad:
  414.     freenode(rv);
  415.     rv = NULL;
  416.     *sep = 0;
  417. out:
  418.     return rv;
  419. }
  420.  
  421. NODE *
  422. gath_args(n)
  423. {
  424.     NODE *rv;
  425.     NODE *tail;
  426.     NODE *np;
  427.     int sep;
  428.     int getn;
  429.  
  430.     getn = 0;
  431.     rv = NULL;
  432.     tail = NULL;
  433.     np = hi_node();
  434.     if (np->e_token != '(') {
  435.         error("expect (");
  436.         goto bad;
  437.     }
  438.     freenode(np);
  439.     if (n == 0) {
  440.         np = hi_node();
  441.         if (np->e_token != ')') {
  442.             error("expect )");
  443.             goto bad;
  444.         }
  445.         freenode(np);
  446.         return NULL;
  447.     }
  448. more:
  449.     np = gath1(&sep);
  450.     if (np == NULL) {
  451.         error("expect arg");
  452.         goto bad;
  453.     }
  454.     getn++;
  455.     if (tail == NULL) {     /* first one */
  456.         rv = np;
  457.         tail = np;
  458.     } else {            /* more */
  459.         tail->n_right = np;
  460.         tail = np;
  461.     }
  462.     if (sep) switch (sep) {
  463.     case ',':
  464.         goto more;
  465.     case ')':
  466.         if (getn != n) {
  467.             error("arg num mismatch");
  468.             goto bad;
  469.         }
  470.         goto out;
  471.     }
  472.     error("expand arg syntax");
  473. bad:
  474.     freenode(rv);
  475.     rv = NULL;
  476. out:
  477.     return rv;
  478. }
  479.  
  480. NODE *
  481. argfix(val, args, rt)
  482. NODE *val, *args;
  483. NODE **rt;
  484. {
  485.     register NODE *scan, *sub;
  486.     NODE *head;
  487.     NODE *tail, *back;
  488.     NODE *rthnode();
  489.     NODE *copylist();
  490.  
  491.     head = val;
  492.     back = NULL;
  493.     for (scan = val; scan != NULL; back=scan, scan=scan->n_next)
  494.         if (scan->e_token == DPARAM) {
  495.             sub = rthnode(args, (int)scan->e_ival);
  496.             sub = copylist(sub,&tail);
  497.             if (back) {
  498.                 back->n_next = sub;
  499.                 tail->n_next = scan->n_next;
  500.             } else {
  501.                 head = sub;
  502.                 tail->n_next = scan->n_next;
  503.             }
  504.             scan->n_next = NULL;
  505.             freenode(scan);
  506.             scan = tail;
  507.         }
  508.     *rt = back;
  509.     return head;
  510. }
  511.  
  512. expand(dp)
  513. NODEP dp;
  514. {
  515.     int nargs;
  516.     NODEP args;
  517.     register NODEP val;
  518.     NODEP tail;
  519.  
  520.     val = dp->n_right;
  521.     if (val)
  522.         val = copylist(val, &tail);
  523.     nargs = dp->e_ival;
  524.     if (nargs >= 0) {
  525.         args = gath_args(nargs);
  526.         if (args) {
  527.             if (val)
  528.                 val = argfix(val,args,&tail);
  529.             freenode(args);
  530.         }
  531.     }
  532.     if (val == NULL)
  533.         return;
  534. #ifdef DEBUG
  535.     if (debugd > 1) {
  536.         printf("Expand");
  537.         printnode(val);
  538.     }
  539. #endif
  540.     tail->n_next = holdtok;
  541.     holdtok = val;
  542. }
  543.  
  544. p_undef()
  545. {
  546.     NODEP np, tp;
  547.  
  548.     nxttok();
  549.     if (curtok.tnum != ID) {
  550.         error("bad #undef");
  551.         goto out;
  552.     }
  553.     tp = tok_to_node();
  554.     if ((np = hlook(deflist, tp)) != NULL)
  555.         /* quick and dirty */
  556.         np->n_name[0] = '#';
  557.     freenode(tp);
  558. out:
  559.     ;
  560. }
  561.  
  562. p_inc()
  563. {
  564.     int chkhere;
  565.     FILE *newf, *srch_open();
  566.     char *scopy(), *newnm;
  567.  
  568.     tk_flags |= TK_NOESC|TK_LTSTR;
  569.     nxttok();
  570.     switch (curtok.tnum) {
  571.     case SCON:
  572.         chkhere = 1;
  573.         break;
  574.     case SCON2:
  575.         chkhere = 0;
  576.         break;
  577.     case NL:
  578.     case EOF:
  579.         error("bad #include");
  580.         return;
  581.     }
  582.     newf = srch_open(curstr, chkhere);
  583.     if (newf == NULL) {
  584.         fatals("Cant open ", curstr);
  585.         return;
  586.     }
  587.     newnm = scopy(curstr);
  588.     do
  589.         nxttok();
  590.     while (curtok.tnum != NL);
  591.     newfile(newf,newnm);
  592. }
  593.  
  594. int inclvl;
  595. struct svinc {
  596.     int lineno;
  597.     FILE *fd;
  598.     char *filenm;
  599. } svincs[MAXINCL];
  600.  
  601. #if NEEDBUF
  602. char p_buf[MAXINCL][BUFSIZ];
  603. #endif
  604.  
  605. static char obuf[MAXSTR];
  606.  
  607. newfile(fd,s)
  608. FILE *fd;
  609. char *s;
  610. {
  611.     register struct svinc *p;
  612.  
  613.     inclvl++;
  614.     if (inclvl > MAXINCL) {
  615.         inclvl--;
  616.         fclose(fd);
  617.         error("too many includes");
  618.         return;
  619.     }
  620.     p = &svincs[inclvl-1];
  621.     p->lineno = lineno;
  622.     p->fd = input;
  623.     p->filenm = inname;
  624.     input = fd;
  625.     lineno = 1;
  626.     inname = s;
  627. #if NEEDBUF
  628.     setbuf(input, p_buf[inclvl-1]);
  629. #endif
  630. }
  631.  
  632. endfile()
  633. {
  634.     register struct svinc *p;
  635.  
  636.     if (inclvl == 0)
  637.         return 0;
  638.     fclose(input);
  639.     inclvl--;
  640.     p = &svincs[inclvl];
  641.     sfree(inname);
  642.     input = p->fd;
  643.     lineno = p->lineno;
  644.     inname = p->filenm;
  645.     return 1;
  646. }
  647.  
  648. #define MAXIDIR 10
  649.  
  650. char *srchlist[MAXIDIR] = {
  651.     "",
  652.     "\\include\\",
  653.     "\\sozobon\\include\\",
  654.     "",
  655.     0
  656. };
  657.  
  658. static int idir_n = 4;        /* number of entries in above table */
  659. static int idir_put = 1;    /* where to put -I dirs */
  660.  
  661. optincl(s)
  662. char *s;
  663. {
  664.     register char **pp;
  665.  
  666.     if (idir_n >= MAXIDIR-1) {
  667.         warn("too many -I dirs");
  668.         return;
  669.     }
  670.     for (pp = &srchlist[idir_n]; pp > &srchlist[idir_put]; ) {
  671.         pp--;
  672.         pp[1] = pp[0];
  673.     }
  674.     *pp = s;
  675.     idir_put++;
  676.     idir_n++;
  677. }
  678.  
  679. FILE *
  680. srch_open(s, chkhere)
  681. char *s;
  682. {
  683.     char **dir;
  684.     FILE *fd;
  685.  
  686.     dir = srchlist;
  687.     if (chkhere == 0) dir++;
  688.     while (*dir) {
  689.         strcpy(obuf, *dir);
  690.         strcat(obuf, s);
  691.         fd = fopen(obuf, ROPEN);
  692.         if (fd != NULL) {
  693.             return fd;
  694.         }
  695.         dir++;
  696.     }
  697.     return NULL;
  698. }
  699.  
  700. p_if(kind,skipping)
  701. {
  702.     int truth;
  703.     NODEP tp;
  704.  
  705.     if (skipping) {
  706.         ifnest++;
  707.         return;
  708.     }
  709.     switch (kind) {
  710.     case 0:
  711.         truth = if_expr();
  712.         break;
  713.     case 1:
  714.     case 2:
  715.         nxttok();
  716.         if (curtok.tnum != ID) {
  717.             error("bad #if(n)def");
  718.             goto flush;
  719.         }
  720.         tp = tok_to_node();
  721.         truth = (hlook(deflist, tp) != NULL);
  722.         freenode(tp);
  723.         if (kind == 2)
  724.             truth = !truth;
  725.     }
  726.     iflevel++;
  727.     iftruth = truth;
  728. flush:
  729.     ;
  730. }
  731.  
  732.  
  733. extern NODE *cur;
  734. if_expr()
  735. {
  736.     NODE *tp, *questx();
  737.     int rv;
  738.  
  739.     advnode();
  740.     tp = questx();
  741.     if (tp) {
  742.         rv = conxval(tp);
  743.     } else
  744.         rv = 0;
  745.     if (cur->e_token != NL) {
  746.         error("bad #if");
  747.     } else
  748.         freenode(cur);
  749.     return rv;
  750. }
  751.  
  752. p_swit(kind,skipping)
  753. {
  754.     if (skipping && ifnest) {
  755.         if (kind == 1)
  756.             ifnest--;
  757.         return;
  758.     }
  759.     if (iflevel == 0) {
  760.         error("not in #if");
  761.         goto out;
  762.     }
  763.     switch (kind) {
  764.     case 0:     /* else */
  765.         iftruth = !iftruth;
  766.         break;
  767.     case 1:     /* endif */
  768.         iflevel--;
  769.         iftruth = 1;
  770.         break;
  771.     }
  772. out:
  773.     ;
  774. }
  775.  
  776. p_line()
  777. {
  778.     char *scopy();
  779.  
  780.     nxttok();
  781.     if (curtok.tnum != ICON) {
  782.         error("bad #line");
  783.         goto flush;
  784.     }
  785.     tk_flags |= TK_NOESC;
  786.     nxttok();
  787.     if (curtok.tnum == SCON) {
  788.         sfree(inname);
  789.         inname = scopy(curtok.name);
  790.     }
  791.     lineno = curtok.ival;
  792. flush:
  793.     ;
  794. }
  795.  
  796. struct cmds {
  797.     char *name;
  798.     int (*fun)();
  799.     int arg;
  800.     int skip;
  801. } pcmds[] = {
  802.     {"define", p_def, 0, 1},
  803.     {"undef", p_undef, 0, 1},
  804.     {"include", p_inc, 0, 1},
  805.     {"if", p_if, 0, 0},
  806.     {"ifdef", p_if, 1, 0},
  807.     {"ifndef", p_if, 2, 0},
  808.     {"else", p_swit, 0, 0},
  809.     {"endif", p_swit, 1, 0},
  810.     {"line", p_line, 0, 1},
  811.     {0}
  812. };
  813.  
  814. dopound(skipping)
  815. {
  816.     register struct cmds *p;
  817.     register char *cname;
  818.  
  819.     tk_flags |= TK_SEENL;
  820.     sawnl = 0;
  821.     nxttok();
  822.     if (curtok.tnum != ID) {
  823.         error("expect name");
  824.         return;
  825.     }
  826.     cname = curtok.name;
  827.     for (p=pcmds; p->name; p++)
  828.         if (strcmp(p->name, cname) == 0) {
  829.             if (!skipping || !p->skip)
  830.                 (*p->fun)(p->arg, skipping);
  831.             tk_flags = 0;
  832.             if (sawnl == 0)
  833.                 tk_flags |= TK_ONLY1;
  834.             return;
  835.         }
  836.     error("bad # command");
  837. }
  838.  
  839. NODEP
  840. tok_to_node()
  841. {
  842.     register struct tok *tp;
  843.     register NODEP np;
  844.  
  845.     tp = &curtok;
  846.     np = allocnode();
  847.     np->e_token = tp->tnum;
  848.     np->e_flags = tp->flags;
  849.     if (tp->prec)   /* binary op */
  850.         np->e_prec = tp->prec;
  851.     else
  852.     switch (np->e_token) {
  853.     case ICON:
  854.         np->e_ival = tp->ival;
  855.         break;
  856.     case FCON:
  857.         np->e_fval = tp->fval;
  858.         break;
  859.     }
  860.     nscpy(np, tp->name);
  861.     return np;
  862. }
  863.  
  864. NODEP
  865. id_tok(s)
  866. char *s;
  867. {
  868.     NODEP np;
  869.  
  870.     np = allocnode();
  871.     np->e_token = ID;
  872.     nscpy(np, s);
  873.     return np;
  874. }
  875.