home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / c / c04.c < prev    next >
Encoding:
C/C++ Source or Header  |  1979-05-07  |  6.4 KB  |  429 lines

  1. #
  2. /*
  3.  * C compiler
  4.  *
  5.  *
  6.  */
  7.  
  8. #include "c0.h"
  9.  
  10. /*
  11.  * Reduce the degree-of-reference by one.
  12.  * e.g. turn "ptr-to-int" into "int".
  13.  */
  14. decref(at)
  15. {
  16.     register t;
  17.  
  18.     t = at;
  19.     if ((t & ~TYPE) == 0) {
  20.         error("Illegal indirection");
  21.         return(t);
  22.     }
  23.     return((t>>TYLEN) & ~TYPE | t&TYPE);
  24. }
  25.  
  26. /*
  27.  * Increase the degree of reference by
  28.  * one; e.g. turn "int" to "ptr-to-int".
  29.  */
  30. incref(t)
  31. {
  32.     return(((t&~TYPE)<<TYLEN) | (t&TYPE) | PTR);
  33. }
  34.  
  35. /*
  36.  * Make a tree that causes a branch to lbl
  37.  * if the tree's value is non-zero together with the cond.
  38.  */
  39. cbranch(t, lbl, cond)
  40. struct tnode *t;
  41. {
  42.     treeout(t, 0);
  43.     outcode("BNNN", CBRANCH, lbl, cond, line);
  44. }
  45.  
  46. /*
  47.  * Write out a tree.
  48.  */
  49. rcexpr(atp)
  50. struct tnode *atp;
  51. {
  52.     register struct tnode *tp;
  53.  
  54.     /*
  55.      * Special optimization
  56.      */
  57.     if ((tp=atp)->op==INIT && tp->tr1->op==CON) {
  58.         if (tp->type==CHAR) {
  59.             outcode("B1N0", BDATA, tp->tr1->value);
  60.             return;
  61.         } else if (tp->type==INT || tp->type==UNSIGN) {
  62.             outcode("BN", SINIT, tp->tr1->value);
  63.             return;
  64.         }
  65.     }
  66.     treeout(tp, 0);
  67.     outcode("BN", EXPR, line);
  68. }
  69.  
  70. treeout(atp, isstruct)
  71. struct tnode *atp;
  72. {
  73.     register struct tnode *tp;
  74.     register struct hshtab *hp;
  75.     register nextisstruct;
  76.  
  77.     if ((tp = atp) == 0) {
  78.         outcode("B", NULLOP);
  79.         return;
  80.     }
  81.     nextisstruct = tp->type==STRUCT;
  82.     switch(tp->op) {
  83.  
  84.     case NAME:
  85.         hp = tp->tr1;
  86.         if (hp->hclass==TYPEDEF)
  87.             error("Illegal use of type name");
  88.         outcode("BNN", NAME, hp->hclass==0?STATIC:hp->hclass, tp->type);
  89.         if (hp->hclass==EXTERN)
  90.             outcode("S", hp->name);
  91.         else
  92.             outcode("N", hp->hoffset);
  93.         break;
  94.  
  95.     case LCON:
  96.         outcode("BNNN", tp->op, tp->type, tp->lvalue);
  97.         break;
  98.  
  99.     case CON:
  100.         outcode("BNN", tp->op, tp->type, tp->value);
  101.         break;
  102.  
  103.     case FCON:
  104.         outcode("BNF", tp->op, tp->type, tp->cstr);
  105.         break;
  106.  
  107.     case STRING:
  108.         outcode("BNNN", NAME, STATIC, tp->type, tp->tr1);
  109.         break;
  110.  
  111.     case FSEL:
  112.         treeout(tp->tr1, nextisstruct);
  113.         outcode("BNNN",tp->op,tp->type,tp->tr2->bitoffs,tp->tr2->flen);
  114.         break;
  115.  
  116.     case ETYPE:
  117.         error("Illegal use of type");
  118.         break;
  119.  
  120.     case AMPER:
  121.         treeout(tp->tr1, 1);
  122.         outcode("BN", tp->op, tp->type);
  123.         break;
  124.  
  125.  
  126.     case CALL:
  127.         treeout(tp->tr1, 1);
  128.         treeout(tp->tr2, 0);
  129.         outcode("BN", CALL, tp->type);
  130.         break;
  131.  
  132.     default:
  133.         treeout(tp->tr1, nextisstruct);
  134.         if (opdope[tp->op]&BINARY)
  135.             treeout(tp->tr2, nextisstruct);
  136.         outcode("BN", tp->op, tp->type);
  137.         break;
  138.     }
  139.     if (nextisstruct && isstruct==0)
  140.         outcode("BNN", STRASG, STRUCT, tp->strp->ssize);
  141. }
  142.  
  143. /*
  144.  * Generate a branch
  145.  */
  146. branch(lab)
  147. {
  148.     outcode("BN", BRANCH, lab);
  149. }
  150.  
  151. /*
  152.  * Generate a label
  153.  */
  154. label(l)
  155. {
  156.     outcode("BN", LABEL, l);
  157. }
  158.  
  159. /*
  160.  * ap is a tree node whose type
  161.  * is some kind of pointer; return the size of the object
  162.  * to which the pointer points.
  163.  */
  164. plength(ap)
  165. struct tname *ap;
  166. {
  167.     register t, l;
  168.     register struct tnode *p;
  169.  
  170.     p = ap;
  171.     if (p==0 || ((t=p->type)&~TYPE) == 0)        /* not a reference */
  172.         return(1);
  173.     p->type = decref(t);
  174.     l = length(p);
  175.     p->type = t;
  176.     return(l);
  177. }
  178.  
  179. /*
  180.  * return the number of bytes in the object
  181.  * whose tree node is acs.
  182.  */
  183. length(acs)
  184. struct tnode *acs;
  185. {
  186.     register t, elsz;
  187.     long n;
  188.     register struct tnode *cs;
  189.     int nd;
  190.  
  191.     cs = acs;
  192.     t = cs->type;
  193.     n = 1;
  194.     nd = 0;
  195.     while ((t&XTYPE) == ARRAY) {
  196.         t = decref(t);
  197.         n =* cs->subsp[nd++];
  198.     }
  199.     if ((t&~TYPE)==FUNC)
  200.         return(0);
  201.     if (t>=PTR)
  202.         elsz = SZPTR;
  203.     else switch(t&TYPE) {
  204.  
  205.     case INT:
  206.     case UNSIGN:
  207.         elsz = SZINT;
  208.         break;
  209.  
  210.     case CHAR:
  211.         elsz = 1;
  212.         break;
  213.  
  214.     case FLOAT:
  215.         elsz = SZFLOAT;
  216.         break;
  217.  
  218.     case LONG:
  219.         elsz = SZLONG;
  220.         break;
  221.  
  222.     case DOUBLE:
  223.         elsz = SZDOUB;
  224.         break;
  225.  
  226.     case STRUCT:
  227.         if ((elsz = cs->strp->ssize) == 0)
  228.             error("Undefined structure");
  229.         break;
  230.     default:
  231.         error("Compiler error (length)");
  232.         return(0);
  233.     }
  234.     n *= elsz;
  235.     if (n >= (unsigned)50000) {
  236.         error("Warning: very large data structure");
  237.         nerror--;
  238.     }
  239.     return(n);
  240. }
  241.  
  242. /*
  243.  * The number of bytes in an object, rounded up to a word.
  244.  */
  245. rlength(cs)
  246. struct tnode *cs;
  247. {
  248.     return((length(cs)+ALIGN) & ~ALIGN);
  249. }
  250.  
  251. /*
  252.  * After an "if (...) goto", look to see if the transfer
  253.  * is to a simple label.
  254.  */
  255. simplegoto()
  256. {
  257.     register struct hshtab *csp;
  258.  
  259.     if ((peeksym=symbol())==NAME && nextchar()==';') {
  260.         csp = csym;
  261.         if (csp->hblklev == 0)
  262.             pushdecl(csp);
  263.         if (csp->hclass==0 && csp->htype==0) {
  264.             csp->htype = ARRAY;
  265.             csp->hflag =| FLABL;
  266.             if (csp->hoffset==0)
  267.                 csp->hoffset = isn++;
  268.         }
  269.         if ((csp->hclass==0||csp->hclass==STATIC)
  270.          &&  csp->htype==ARRAY) {
  271.             peeksym = -1;
  272.             return(csp->hoffset);
  273.         }
  274.     }
  275.     return(0);
  276. }
  277.  
  278. /*
  279.  * Return the next non-white-space character
  280.  */
  281. nextchar()
  282. {
  283.     while (spnextchar()==' ')
  284.         peekc = 0;
  285.     return(peekc);
  286. }
  287.  
  288. /*
  289.  * Return the next character, translating all white space
  290.  * to blank and handling line-ends.
  291.  */
  292. spnextchar()
  293. {
  294.     register c;
  295.  
  296.     if ((c = peekc)==0)
  297.         c = getchar();
  298.     if (c=='\t' || c=='\014')    /* FF */
  299.         c = ' ';
  300.     else if (c=='\n') {
  301.         c = ' ';
  302.         if (inhdr==0)
  303.             line++;
  304.         inhdr = 0;
  305.     } else if (c=='\001') {    /* SOH, insert marker */
  306.         inhdr++;
  307.         c = ' ';
  308.     }
  309.     peekc = c;
  310.     return(c);
  311. }
  312.  
  313. /*
  314.  * is a break or continue legal?
  315.  */
  316. chconbrk(l)
  317. {
  318.     if (l==0)
  319.         error("Break/continue error");
  320. }
  321.  
  322. /*
  323.  * The goto statement.
  324.  */
  325. dogoto()
  326. {
  327.     register struct tnode *np;
  328.  
  329.     *cp++ = tree();
  330.     build(STAR);
  331.     chkw(np = *--cp, -1);
  332.     rcexpr(block(JUMP,0,NULL,NULL,np));
  333. }
  334.  
  335. /*
  336.  * The return statement, which has to convert
  337.  * the returned object to the function's type.
  338.  */
  339. doret()
  340. {
  341.     register struct tnode *t;
  342.  
  343.     if (nextchar() != ';') {
  344.         t = tree();
  345.         *cp++ = &funcblk;
  346.         *cp++ = t;
  347.         build(ASSIGN);
  348.         cp[-1] = cp[-1]->tr2;
  349.         if (funcblk.type==CHAR)
  350.             cp[-1] = block(ITOC, INT, NULL, NULL, cp[-1]);
  351.         build(RFORCE);
  352.         rcexpr(*--cp);
  353.     }
  354.     branch(retlab);
  355. }
  356.  
  357. /*
  358.  * Write a character on the error output.
  359.  */
  360. /*
  361.  * Coded output:
  362.  *   B: beginning of line; an operator
  363.  *   N: a number
  364.  *   S: a symbol (external)
  365.  *   1: number 1
  366.  *   0: number 0
  367.  */
  368. outcode(s, a)
  369. char *s;
  370. {
  371.     register *ap;
  372.     register FILE *bufp;
  373.     int n;
  374.     register char *np;
  375.  
  376.     bufp = stdout;
  377.     if (strflg)
  378.         bufp = sbufp;
  379.     ap = &a;
  380.     for (;;) switch(*s++) {
  381.     case 'B':
  382.         putc(*ap++, bufp);
  383.         putc(0376, bufp);
  384.         continue;
  385.  
  386.     case 'N':
  387.         putc(*ap, bufp);
  388.         putc(*ap++>>8, bufp);
  389.         continue;
  390.  
  391.     case 'F':
  392.         n = 1000;
  393.         np = *ap++;
  394.         goto str;
  395.  
  396.     case 'S':
  397.         n = NCPS;
  398.         np = *ap++;
  399.         if (*np)
  400.             putc('_', bufp);
  401.     str:
  402.         while (n-- && *np) {
  403.             putc(*np++&0177, bufp);
  404.         }
  405.         putc(0, bufp);
  406.         continue;
  407.  
  408.     case '1':
  409.         putc(1, bufp);
  410.         putc(0, bufp);
  411.         continue;
  412.  
  413.     case '0':
  414.         putc(0, bufp);
  415.         putc(0, bufp);
  416.         continue;
  417.  
  418.     case '\0':
  419.         if (ferror(bufp)) {
  420.             error("Write error on temp");
  421.             exit(1);
  422.         }
  423.         return;
  424.  
  425.     default:
  426.         error("Botch in outcode");
  427.     }
  428. }
  429.