home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V6 / usr / source / c / c00.c next >
Encoding:
C/C++ Source or Header  |  1975-07-18  |  11.2 KB  |  710 lines

  1. #
  2. /* C compiler
  3.  *
  4.  *
  5.  *
  6.  * Called from cc:
  7.  *   c0 source temp1 temp2 [ profileflag ]
  8.  * temp1 contains some ascii text and the binary expression
  9.  * trees.  Each tree is introduced by the # character.
  10.  * Strings are put on temp2, which cc tacks onto
  11.  * temp1 for assembly.
  12.  */
  13.  
  14. #include "c0h.c"
  15.  
  16. int    isn    1;
  17. int    stflg    1;
  18. int    peeksym    -1;
  19. int    line    1;
  20. int    debug    0;
  21. int    dimp    0;
  22. struct    tname    funcblk { NAME, 0, 0, REG, 0, 0 };
  23. int    *treespace { osspace };
  24.  
  25. struct kwtab {
  26.     char    *kwname;
  27.     int    kwval;
  28. } kwtab[]
  29. {
  30.     "int",        INT,
  31.     "char",        CHAR,
  32.     "float",    FLOAT,
  33.     "double",    DOUBLE,
  34.     "struct",    STRUCT,
  35.     "long",        LONG,
  36.     "auto",        AUTO,
  37.     "extern",    EXTERN,
  38.     "static",    STATIC,
  39.     "register",    REG,
  40.     "goto",        GOTO,
  41.     "return",    RETURN,
  42.     "if",        IF,
  43.     "while",    WHILE,
  44.     "else",        ELSE,
  45.     "switch",    SWITCH,
  46.     "case",        CASE,
  47.     "break",    BREAK,
  48.     "continue",    CONTIN,
  49.     "do",        DO,
  50.     "default",    DEFAULT,
  51.     "for",        FOR,
  52.     "sizeof",    SIZEOF,
  53.     0,        0,
  54. };
  55.  
  56. main(argc, argv)
  57. char *argv[];
  58. {
  59.     extern fin;
  60.     register char *sp;
  61.     register i;
  62.     register struct kwtab *ip;
  63.  
  64.     if(argc<3) {
  65.         error("Arg count");
  66.         exit(1);
  67.     }
  68.     if((fin=open(argv[1],0))<0) {
  69.         error("Can't find %s", argv[1]);
  70.         exit(1);
  71.     }
  72.     if (fcreat(argv[2], obuf)<0 || fcreat(argv[3], sbuf)<0) {
  73.         error("Can't create temp");
  74.         exit(1);
  75.     }
  76.     if (argc>4)
  77.         proflg++;
  78.     /*
  79.      * The hash table locations of the keywords
  80.      * are marked; if an identifier hashes to one of
  81.      * these locations, it is looked up in in the keyword
  82.      * table first.
  83.      */
  84.     for (ip=kwtab; (sp = ip->kwname); ip++) {
  85.         i = 0;
  86.         while (*sp)
  87.             i =+ *sp++;
  88.         hshtab[i%hshsiz].hflag = FKEYW;
  89.     }
  90.     while(!eof) {
  91.         extdef();
  92.         blkend();
  93.     }
  94.     outcode("B", EOF);
  95.     strflg++;
  96.     outcode("B", EOF);
  97.     fflush(obuf);
  98.     fflush(sbuf);
  99.     exit(nerror!=0);
  100. }
  101.  
  102. /*
  103.  * Look up the identifier in symbuf in the symbol table.
  104.  * If it hashes to the same spot as a keyword, try the keyword table
  105.  * first.  An initial "." is ignored in the hash.
  106.  * Return is a ptr to the symbol table entry.
  107.  */
  108. lookup()
  109. {
  110.     int ihash;
  111.     register struct hshtab *rp;
  112.     register char *sp, *np;
  113.  
  114.     ihash = 0;
  115.     sp = symbuf;
  116.     if (*sp=='.')
  117.         sp++;
  118.     while (sp<symbuf+ncps)
  119.         ihash =+ *sp++;
  120.     rp = &hshtab[ihash%hshsiz];
  121.     if (rp->hflag&FKEYW)
  122.         if (findkw())
  123.             return(KEYW);
  124.     while (*(np = rp->name)) {
  125.         for (sp=symbuf; sp<symbuf+ncps;)
  126.             if (*np++ != *sp++)
  127.                 goto no;
  128.         csym = rp;
  129.         return(NAME);
  130.     no:
  131.         if (++rp >= &hshtab[hshsiz])
  132.             rp = hshtab;
  133.     }
  134.     if(++hshused >= hshsiz) {
  135.         error("Symbol table overflow");
  136.         exit(1);
  137.     }
  138.     rp->hclass = 0;
  139.     rp->htype = 0;
  140.     rp->hoffset = 0;
  141.     rp->dimp = 0;
  142.     rp->hflag =| xdflg;
  143.     sp = symbuf;
  144.     for (np=rp->name; sp<symbuf+ncps;)
  145.         *np++ = *sp++;
  146.     csym = rp;
  147.     return(NAME);
  148. }
  149.  
  150. /*
  151.  * Search the keyword table.
  152.  * Ignore initial "." to avoid member-of-structure
  153.  * problems.
  154.  */
  155. findkw()
  156. {
  157.     register struct kwtab *kp;
  158.     register char *p1, *p2;
  159.     char *wp;
  160.  
  161.     wp = symbuf;
  162.     if (*wp=='.')
  163.         wp++;
  164.     for (kp=kwtab; (p2 = kp->kwname); kp++) {
  165.         p1 = wp;
  166.         while (*p1 == *p2++)
  167.             if (*p1++ == '\0') {
  168.                 cval = kp->kwval;
  169.                 return(1);
  170.             }
  171.     }
  172.     return(0);
  173. }
  174.  
  175.  
  176. /*
  177.  * Return the next symbol from the input.
  178.  * peeksym is a pushed-back symbol, peekc is a pushed-back
  179.  * character (after peeksym).
  180.  * mosflg means that the next symbol, if an identifier,
  181.  * is a member of structure or a structure tag, and it
  182.  * gets a "." prepended to it to distinguish
  183.  * it from other identifiers.
  184.  */
  185. symbol() {
  186.     register c;
  187.     register char *sp;
  188.  
  189.     if (peeksym>=0) {
  190.         c = peeksym;
  191.         peeksym = -1;
  192.         if (c==NAME)
  193.             mosflg = 0;
  194.         return(c);
  195.     }
  196.     if (peekc) {
  197.         c = peekc;
  198.         peekc = 0;
  199.     } else
  200.         if (eof)
  201.             return(EOF);
  202.         else
  203.             c = getchar();
  204. loop:
  205.     switch(ctab[c]) {
  206.  
  207.     case INSERT:        /* ignore newlines */
  208.         inhdr = 1;
  209.         c = getchar();
  210.         goto loop;
  211.  
  212.     case NEWLN:
  213.         if (!inhdr)
  214.             line++;
  215.         inhdr = 0;
  216.  
  217.     case SPACE:
  218.         c = getchar();
  219.         goto loop;
  220.  
  221.     case EOF:
  222.         eof++;
  223.         return(0);
  224.  
  225.     case PLUS:
  226.         return(subseq(c,PLUS,INCBEF));
  227.  
  228.     case MINUS:
  229.         return(subseq(c,subseq('>',MINUS,ARROW),DECBEF));
  230.  
  231.     case ASSIGN:
  232.         if (subseq(' ',0,1)) return(ASSIGN);
  233.         c = symbol();
  234.         if (c>=PLUS && c<=EXOR) {
  235.             if (spnextchar() != ' '
  236.              && (c==MINUS || c==AND || c==TIMES)) {
  237.                 error("Warning: assignment operator assumed");
  238.                 nerror--;
  239.             }
  240.             return(c+ASPLUS-PLUS);
  241.         }
  242.         if (c==ASSIGN)
  243.             return(EQUAL);
  244.         peeksym = c;
  245.         return(ASSIGN);
  246.  
  247.     case LESS:
  248.         if (subseq(c,0,1)) return(LSHIFT);
  249.         return(subseq('=',LESS,LESSEQ));
  250.  
  251.     case GREAT:
  252.         if (subseq(c,0,1)) return(RSHIFT);
  253.         return(subseq('=',GREAT,GREATEQ));
  254.  
  255.     case EXCLA:
  256.         return(subseq('=',EXCLA,NEQUAL));
  257.  
  258.     case DIVIDE:
  259.         if (subseq('*',1,0))
  260.             return(DIVIDE);
  261.         while ((c = spnextchar()) != EOF) {
  262.             peekc = 0;
  263.             if (c=='*') {
  264.                 if (spnextchar() == '/') {
  265.                     peekc = 0;
  266.                     c = getchar();
  267.                     goto loop;
  268.                 }
  269.             }
  270.         }
  271.         eof++;
  272.             error("Nonterminated comment");
  273.             return(0);
  274.  
  275.     case PERIOD:
  276.     case DIGIT:
  277.         peekc = c;
  278.         if ((c=getnum(c=='0'?8:10)) == FCON)
  279.             cval = isn++;
  280.         return(c);
  281.  
  282.     case DQUOTE:
  283.         return(getstr());
  284.  
  285.     case SQUOTE:
  286.         return(getcc());
  287.  
  288.     case LETTER:
  289.         sp = symbuf;
  290.         if (mosflg) {
  291.             *sp++ = '.';
  292.             mosflg = 0;
  293.         }
  294.         while(ctab[c]==LETTER || ctab[c]==DIGIT) {
  295.             if (sp<symbuf+ncps) *sp++ = c;
  296.             c = getchar();
  297.         }
  298.         while(sp<symbuf+ncps)
  299.             *sp++ = '\0';
  300.         peekc = c;
  301.         if ((c=lookup())==KEYW && cval==SIZEOF)
  302.             c = SIZEOF;
  303.         return(c);
  304.  
  305.     case AND:
  306.         return(subseq('&', AND, LOGAND));
  307.  
  308.     case OR:
  309.         return(subseq('|', OR, LOGOR));
  310.  
  311.     case UNKN:
  312.         error("Unknown character");
  313.         c = getchar();
  314.         goto loop;
  315.  
  316.     }
  317.     return(ctab[c]);
  318. }
  319.  
  320. /*
  321.  * If the next input character is c, return a and advance.
  322.  * Otherwise push back the character and return a.
  323.  */
  324. subseq(c,a,b)
  325. {
  326.     if (spnextchar() != c)
  327.         return(a);
  328.     peekc = 0;
  329.     return(b);
  330. }
  331.  
  332. /*
  333.  * Read a double-quoted string, placing it on the
  334.  * string buffer.
  335.  */
  336. getstr()
  337. {
  338.     register int c;
  339.     register char *sp;
  340.  
  341.     nchstr = 1;
  342.     sp = savstr;
  343.     while((c=mapch('"')) >= 0) {
  344.         nchstr++;
  345.         if (sp >= &savstr[STRSIZ]) {
  346.             sp = savstr;
  347.             error("String too long");
  348.         }
  349.         *sp++ = c;
  350.     }
  351.     strptr = sp;
  352.     cval = isn++;
  353.     return(STRING);
  354. }
  355.  
  356. /*
  357.  * Write out a string, either in-line
  358.  * or in the string temp file labelled by
  359.  * lab.
  360.  */
  361. putstr(lab)
  362. {
  363.     register char *sp;
  364.  
  365.     if (lab) {
  366.         strflg++;
  367.         outcode("BNB", LABEL, lab, BDATA);
  368.     } else
  369.         outcode("B", BDATA);
  370.     for (sp = savstr; sp<strptr; )
  371.         outcode("1N", *sp++ & 0377);
  372.     outcode("100");
  373.     strflg = 0;
  374. }
  375.  
  376. /*
  377.  * read a single-quoted character constant.
  378.  * The routine is sensitive to the layout of
  379.  * characters in a word.
  380.  */
  381. getcc()
  382. {
  383.     register int c, cc;
  384.     register char *ccp;
  385.  
  386.     cval = 0;
  387.     ccp = &cval;
  388.     cc = 0;
  389.     while((c=mapch('\'')) >= 0)
  390.         if(cc++ < NCPW)
  391.             *ccp++ = c;
  392.     if(cc>NCPW)
  393.         error("Long character constant");
  394.     return(CON);
  395. }
  396.  
  397. /*
  398.  * Read a character in a string or character constant,
  399.  * detecting the end of the string.
  400.  * It implements the escape sequences.
  401.  */
  402. mapch(ac)
  403. {
  404.     register int a, c, n;
  405.     static mpeek;
  406.  
  407.     c = ac;
  408.     if (a = mpeek)
  409.         mpeek = 0;
  410.     else
  411.         a = getchar();
  412. loop:
  413.     if (a==c)
  414.         return(-1);
  415.     switch(a) {
  416.  
  417.     case '\n':
  418.     case '\0':
  419.         error("Nonterminated string");
  420.         peekc = a;
  421.         return(-1);
  422.  
  423.     case '\\':
  424.         switch (a=getchar()) {
  425.  
  426.         case 't':
  427.             return('\t');
  428.  
  429.         case 'n':
  430.             return('\n');
  431.  
  432.         case 'b':
  433.             return('\b');
  434.  
  435.         case '0': case '1': case '2': case '3':
  436.         case '4': case '5': case '6': case '7':
  437.             n = 0;
  438.             c = 0;
  439.             while (++c<=3 && '0'<=a && a<='7') {
  440.                 n =<< 3;
  441.                 n =+ a-'0';
  442.                 a = getchar();
  443.             }
  444.             mpeek = a;
  445.             return(n);
  446.  
  447.         case 'r':
  448.             return('\r');
  449.  
  450.         case '\n':
  451.             if (!inhdr)
  452.                 line++;
  453.             inhdr = 0;
  454.             a = getchar();
  455.             goto loop;
  456.         }
  457.     }
  458.     return(a);
  459. }
  460.  
  461. /*
  462.  * Read an expression and return a pointer to its tree.
  463.  * It's the classical bottom-up, priority-driven scheme.
  464.  * The initflg prevents the parse from going past
  465.  * "," or ":" because those delimitesrs are special
  466.  * in initializer (and some other) expressions.
  467.  */
  468. tree()
  469. {
  470. #define    SEOF    200
  471. #define    SSIZE    20
  472.     int *op, opst[SSIZE], *pp, prst[SSIZE];
  473.     register int andflg, o;
  474.     register struct hshtab *cs;
  475.     int p, ps, os;
  476.  
  477.     space = treespace;
  478.     op = opst;
  479.     pp = prst;
  480.     cp = cmst;
  481.     *op = SEOF;
  482.     *pp = 06;
  483.     andflg = 0;
  484.  
  485. advanc:
  486.     switch (o=symbol()) {
  487.  
  488.     case NAME:
  489.         cs = csym;
  490.         if (cs->hclass==0 && cs->htype==0)
  491.             if(nextchar()=='(') {
  492.                 /* set function */
  493.                 cs->hclass = EXTERN;
  494.                 cs->htype = FUNC;
  495.             } else if (initflg)
  496.                 cs->hclass = EXTERN;
  497.             else {
  498.                 /* set label */
  499.                 cs->htype = ARRAY;
  500.                 if (cs->hoffset==0)
  501.                     cs->hoffset = isn++;
  502.             }
  503.         *cp++ = copname(cs);
  504.         goto tand;
  505.  
  506.     case FCON:
  507.         if (!initflg)
  508.             outcode("BBNB1N1N1N1N0B", DATA,LABEL,
  509.                 cval, WDATA, fcval, PROG);
  510.  
  511.     case CON:
  512.     case SFCON:
  513.         *cp++ = block(1,o,(o==CON?INT:DOUBLE),0,cval);
  514.         goto tand;
  515.  
  516.     /* fake a static char array */
  517.     case STRING:
  518.         putstr(cval);
  519.         *cp++ = block(3, NAME, ARRAY+CHAR,0,STATIC,0,cval);
  520.  
  521. tand:
  522.         if(cp>=cmst+cmsiz) {
  523.             error("Expression overflow");
  524.             exit(1);
  525.         }
  526.         if (andflg)
  527.             goto syntax;
  528.         andflg = 1;
  529.         goto advanc;
  530.  
  531.     case INCBEF:
  532.     case DECBEF:
  533.         if (andflg)
  534.             o =+ 2;
  535.         goto oponst;
  536.  
  537.     case COMPL:
  538.     case EXCLA:
  539.     case SIZEOF:
  540.         if (andflg)
  541.             goto syntax;
  542.         goto oponst;
  543.  
  544.     case MINUS:
  545.         if (!andflg)  {
  546.             if ((peeksym=symbol())==FCON) {
  547.                 fcval = - fcval;
  548.                 goto advanc;
  549.             }
  550.             if (peeksym==SFCON) {
  551.                 fcval = - fcval;
  552.                 cval =^ 0100000;
  553.                 goto advanc;
  554.             }
  555.             o = NEG;
  556.         }
  557.         andflg = 0;
  558.         goto oponst;
  559.  
  560.     case AND:
  561.     case TIMES:
  562.         if (andflg)
  563.             andflg = 0; else
  564.             if(o==AND)
  565.                 o = AMPER;
  566.             else
  567.                 o = STAR;
  568.         goto oponst;
  569.  
  570.     case LPARN:
  571.         if (andflg) {
  572.             o = symbol();
  573.             if (o==RPARN)
  574.                 o = MCALL;
  575.             else {
  576.                 peeksym = o;
  577.                 o = CALL;
  578.                 andflg = 0;
  579.             }
  580.         }
  581.         goto oponst;
  582.  
  583.     case RBRACK:
  584.     case RPARN:
  585.         if (!andflg)
  586.             goto syntax;
  587.         goto oponst;
  588.  
  589.     case DOT:
  590.     case ARROW:
  591.         mosflg++;
  592.         break;
  593.  
  594.     }
  595.     /* binaries */
  596.     if (!andflg)
  597.         goto syntax;
  598.     andflg = 0;
  599.  
  600. oponst:
  601.     p = (opdope[o]>>9) & 077;
  602.     if ((o==COMMA || o==COLON) && initflg)
  603.         p = 05;
  604. opon1:
  605.     ps = *pp;
  606.     if (p>ps || p==ps && (opdope[o]&RASSOC)!=0) {
  607.         switch (o) {
  608.  
  609.         case INCAFT:
  610.         case DECAFT:
  611.             p = 37;
  612.             break;
  613.         case LPARN:
  614.         case LBRACK:
  615.         case CALL:
  616.             p = 04;
  617.         }
  618.         if (op >= &opst[SSIZE-1]) {
  619.             error("expression overflow");
  620.             exit(1);
  621.         }
  622.         *++op = o;
  623.         *++pp = p;
  624.         goto advanc;
  625.     }
  626.     --pp;
  627.     switch (os = *op--) {
  628.  
  629.     case SEOF:
  630.         peeksym = o;
  631.         build(0);        /* flush conversions */
  632.         return(*--cp);
  633.  
  634.     case CALL:
  635.         if (o!=RPARN)
  636.             goto syntax;
  637.         build(os);
  638.         goto advanc;
  639.  
  640.     case MCALL:
  641.         *cp++ = block(0,0,0,0);    /* 0 arg call */
  642.         os = CALL;
  643.         break;
  644.  
  645.     case INCBEF:
  646.     case INCAFT:
  647.     case DECBEF:
  648.     case DECAFT:
  649.         *cp++ = block(1, CON, INT, 0, 1);
  650.         break;
  651.  
  652.     case LPARN:
  653.         if (o!=RPARN)
  654.             goto syntax;
  655.         goto advanc;
  656.  
  657.     case LBRACK:
  658.         if (o!=RBRACK)
  659.             goto syntax;
  660.         build(LBRACK);
  661.         goto advanc;
  662.     }
  663.     build(os);
  664.     goto opon1;
  665.  
  666. syntax:
  667.     error("Expression syntax");
  668.     errflush(o);
  669.     return(0);
  670. }
  671.  
  672. /*
  673.  * Generate a tree node for a name.
  674.  * All the relevant info from the symbol table is
  675.  * copied out, including the name if it's an external.
  676.  * This is because the symbol table is gone in the next
  677.  * pass, so a ptr isn't sufficient.
  678.  */
  679. copname(acs)
  680. struct hshtab *acs;
  681. {
  682.     register struct hshtab *cs;
  683.     register struct tname *tp;
  684.     register char *cp1;
  685.     int i;
  686.     char *cp2;
  687.  
  688.     cs = acs;
  689.     tp = gblock(sizeof(*tp)/NCPW);
  690.     tp->op = NAME;
  691.     tp->type = cs->htype;
  692.     tp->dimp = cs->hdimp;
  693.     if ((tp->class = cs->hclass)==0)
  694.         tp->class = STATIC;
  695.     tp->offset = 0;
  696.     tp->nloc = cs->hoffset;
  697.     if (cs->hclass==EXTERN) {
  698.         gblock((ncps-NCPW)/NCPW);
  699.         cp1 = tp->nname;
  700.         cp2 = cs->name;
  701.         i = ncps;
  702.         do {
  703.             *cp1++ = *cp2++;
  704.         } while (--i);
  705.     }
  706.     if (cs->hflag&FFIELD)
  707.         tp->class = FMOS;
  708.     return(tp);
  709. }
  710.