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

  1. #
  2. /*
  3.  * C compiler
  4.  *
  5.  *
  6.  */
  7.  
  8. #include "c0h.c"
  9.  
  10. /*
  11.  * Called from tree, this routine takes the top 1, 2, or 3
  12.  * operands on the expression stack, makes a new node with
  13.  * the operator op, and puts it on the stack.
  14.  * Essentially all the work is in inserting
  15.  * appropriate conversions.
  16.  */
  17. build(op) {
  18.     register int t1;
  19.     int t2, t3, t;
  20.     struct tnode *p3, *disarray();
  21.     register struct tnode *p1, *p2;
  22.     int d, dope, leftc, cvn, pcvn;
  23.  
  24.     /*
  25.      * a[i] => *(a+i)
  26.      */
  27.     if (op==LBRACK) {
  28.         build(PLUS);
  29.         op = STAR;
  30.     }
  31.     dope = opdope[op];
  32.     if ((dope&BINARY)!=0) {
  33.         p2 = chkfun(disarray(*--cp));
  34.         t2 = p2->type;
  35.     }
  36.     p1 = *--cp;
  37.     /*
  38.      * sizeof gets turned into a number here.
  39.      * Bug: sizeof(structure-member-array) is 2 because
  40.      * the array has been turned into a ptr already.
  41.      */
  42.     if (op==SIZEOF) {
  43.         t1 = length(p1);
  44.         p1->op = CON;
  45.         p1->type = INT;
  46.         p1->dimp = 0;
  47.         p1->value = t1;
  48.         *cp++ = p1;
  49.         return;
  50.     }
  51.     if (op!=AMPER) {
  52.         p1 = disarray(p1);
  53.         if (op!=CALL)
  54.             p1 = chkfun(p1);
  55.     }
  56.     t1 = p1->type;
  57.     pcvn = 0;
  58.     t = INT;
  59.     switch (op) {
  60.  
  61.     /* end of expression */
  62.     case 0:
  63.         *cp++ = p1;
  64.         return;
  65.  
  66.     /* no-conversion operators */
  67.     case QUEST:
  68.         if (p2->op!=COLON)
  69.             error("Illegal conditional");
  70.         t = t2;
  71.  
  72.     case COMMA:
  73.     case LOGAND:
  74.     case LOGOR:
  75.         *cp++ = block(2, op, t, 0, p1, p2);
  76.         return;
  77.  
  78.     case CALL:
  79.         if ((t1&XTYPE) != FUNC)
  80.             error("Call of non-function");
  81.         *cp++ = block(2,CALL,decref(t1),p1->dimp,p1,p2);
  82.         return;
  83.  
  84.     case STAR:
  85.         if (p1->op==AMPER ) {
  86.             *cp++ = p1->tr1;
  87.             return;
  88.         }
  89.         if ((t1&XTYPE) == FUNC)
  90.             error("Illegal indirection");
  91.         *cp++ = block(1,STAR,decref(t1),p1->dimp,p1);
  92.         return;
  93.  
  94.     case AMPER:
  95.         if (p1->op==STAR) {
  96.             p1->tr1->dimp = p1->dimp;
  97.             p1->tr1->type = incref(t1);
  98.             *cp++ = p1->tr1;
  99.             return;
  100.         }
  101.         if (p1->op==NAME) {
  102.             *cp++ = block(1,op,incref(t1),p1->dimp,p1);
  103.             return;
  104.         }
  105.         error("Illegal lvalue");
  106.         break;
  107.  
  108.     /*
  109.      * a->b goes to (*a).b
  110.      */
  111.     case ARROW:
  112.         *cp++ = p1;
  113.         chkw(p1, -1);
  114.         p1->type = PTR+STRUCT;
  115.         build(STAR);
  116.         p1 = *--cp;
  117.  
  118.     /*
  119.      * In a.b, a fairly complicated process has to
  120.      * be used to make the left operand look
  121.      * as if it had the type of the second.
  122.      * Also, the offset in the structure has to be
  123.      * given a special type to prevent conversion.
  124.      */
  125.     case DOT:
  126.         if (p2->op!=NAME || (p2->class!=MOS && p2->class!=FMOS))
  127.             error("Illegal structure ref");
  128.         *cp++ = p1;
  129.         t = t2;
  130.         if ((t&XTYPE) == ARRAY) {
  131.             t = decref(t);
  132.             p2->ssp++;
  133.         }
  134.         setype(p1, t, p2->dimp);
  135.         build(AMPER);
  136.         *cp++ = block(1,CON,NOTYPE,0,p2->nloc);
  137.         build(PLUS);
  138.         if ((t2&XTYPE) != ARRAY)
  139.             build(STAR);
  140.         if (p2->class == FMOS)
  141.             *cp++ = block(2, FSEL, t, 0, *--cp, p2->dimp);
  142.         return;
  143.     }
  144.     if ((dope&LVALUE)!=0)
  145.         chklval(p1);
  146.     if ((dope&LWORD)!=0)
  147.         chkw(p1, LONG);
  148.     if ((dope&RWORD)!=0)
  149.         chkw(p2, LONG);
  150.     if ((dope&BINARY)==0) {
  151.         if (op==ITOF)
  152.             t1 = DOUBLE;
  153.         else if (op==FTOI)
  154.             t1 = INT;
  155.         if (!fold(op, p1, 0))
  156.             *cp++ = block(1,op,t1,p1->dimp,p1);
  157.         return;
  158.     }
  159.     cvn = 0;
  160.     if (t1==STRUCT || t2==STRUCT) {
  161.         error("Unimplemented structure operation");
  162.         t1 = t2 = INT;
  163.     }
  164.     if (t2==NOTYPE) {
  165.         t = t1;
  166.         p2->type = INT;    /* no int cv for struct */
  167.         t2 = INT;
  168.     } else
  169.         cvn = cvtab[lintyp(t1)][lintyp(t2)];
  170.     leftc = (cvn>>4)&017;
  171.     cvn =& 017;
  172.     t = leftc? t2:t1;
  173.     if (dope&ASSGOP) {
  174.         t = t1;
  175.         if (op==ASSIGN && (cvn==ITP||cvn==PTI))
  176.             cvn = leftc = 0;
  177.         if (leftc)
  178.             cvn = leftc;
  179.         leftc = 0;
  180.     } else if (op==COLON && t1>=PTR && t1==t2)
  181.         cvn = 0;
  182.     else if (dope&RELAT) {
  183.         if (op>=LESSEQ && (t1>=PTR || t2>=PTR))
  184.             op =+ LESSEQP-LESSEQ;
  185.         if (cvn==PTI)
  186.             cvn = 0;
  187.     }
  188.     if (cvn==PTI) {
  189.         cvn = 0;
  190.         if (op==MINUS) {
  191.             t = INT;
  192.             pcvn++;
  193.         } else {
  194.             if (t1!=t2 || t1!=(PTR+CHAR))
  195.                 cvn = XX;
  196.         }
  197.     }
  198.     if (cvn) {
  199.         t1 = plength(p1);
  200.         t2 = plength(p2);
  201.         if (cvn==XX || (cvn==PTI&&t1!=t2))
  202.             error("Illegal conversion");
  203.         else if (leftc)
  204.             p1 = convert(p1, t, cvn, t2);
  205.         else
  206.             p2 = convert(p2, t, cvn, t1);
  207.     }
  208.     if (dope&RELAT)
  209.         t = INT;
  210.     if (fold(op, p1, p2)==0)
  211.         *cp++ = block(2,op,t,(p1->dimp==0? p2:p1)->dimp,p1,p2);
  212.     if (pcvn && t1!=(PTR+CHAR)) {
  213.         p1 = *--cp;
  214.         *cp++ = convert(p1, 0, PTI, plength(p1->tr1));
  215.     }
  216. }
  217.  
  218. /*
  219.  * Generate the appropirate conversion operator.
  220.  * For pointer <=> integer this is a multiplication
  221.  * or division, otherwise a special operator.
  222.  */
  223. convert(p, t, cvn, len)
  224. struct tnode *p;
  225. {
  226.     register int n;
  227.  
  228.     switch(cvn) {
  229.  
  230.     case PTI:
  231.     case ITP:
  232.         if (len==1)
  233.             return(p);
  234.         return(block(2, (cvn==PTI?DIVIDE:TIMES), t, 0, p,
  235.             block(1, CON, 0, 0, len)));
  236.  
  237.     case ITF:
  238.         n = ITOF;
  239.         break;
  240.     case FTI:
  241.         n = FTOI;
  242.         break;
  243.     case ITL:
  244.         n = ITOL;
  245.         break;
  246.     case LTI:
  247.         n = LTOI;
  248.         break;
  249.     case FTL:
  250.         n = FTOL;
  251.         break;
  252.     case LTF:
  253.         n = LTOF;
  254.         break;
  255.     }
  256.     return(block(1, n, t, 0, p));
  257. }
  258.  
  259. /*
  260.  * Traverse an expression tree, adjust things
  261.  * so the types of things in it are consistent
  262.  * with the view that its top node has
  263.  * type at.
  264.  * Used with structure references.
  265.  */
  266. setype(ap, at, adimptr)
  267. struct tnode *ap;
  268. {
  269.     register struct tnode *p;
  270.     register t, dimptr;
  271.  
  272.     p = ap;
  273.     t = at;
  274.     dimptr = adimptr;
  275.     p->type = t;
  276.     if (dimptr != -1)
  277.         p->dimp = dimptr;
  278.     switch(p->op) {
  279.  
  280.     case AMPER:
  281.         setype(p->tr1, decref(t), dimptr);
  282.         return;
  283.  
  284.     case STAR:
  285.         setype(p->tr1, incref(t), dimptr);
  286.         return;
  287.  
  288.     case PLUS:
  289.     case MINUS:
  290.         setype(p->tr1, t, dimptr);
  291.     }
  292. }
  293.  
  294. /*
  295.  * A mention of a function name is turned into
  296.  * a pointer to that function.
  297.  */
  298. chkfun(ap)
  299. struct tnode *ap;
  300. {
  301.     register struct tnode *p;
  302.     register int t;
  303.  
  304.     p = ap;
  305.     if (((t = p->type)&XTYPE)==FUNC)
  306.         return(block(1,AMPER,incref(t),p->dimp,p));
  307.     return(p);
  308. }
  309.  
  310. /*
  311.  * A mention of an array is turned into
  312.  * a pointer to the base of the array.
  313.  */
  314. struct tnode *disarray(ap)
  315. struct tnode *ap;
  316. {
  317.     register int t;
  318.     register struct tnode *p;
  319.  
  320.     p = ap;
  321.     /* check array & not MOS */
  322.     if (((t = p->type)&XTYPE)!=ARRAY || p->op==NAME&&p->class==MOS)
  323.         return(p);
  324.     p->ssp++;
  325.     *cp++ = p;
  326.     setype(p, decref(t), -1);
  327.     build(AMPER);
  328.     return(*--cp);
  329. }
  330.  
  331. /*
  332.  * make sure that p is a ptr to a node
  333.  * with type int or char or 'okt.'
  334.  * okt might be nonexistent or 'long'
  335.  * (e.g. for <<).
  336.  */
  337. chkw(p, okt)
  338. struct tnode *p;
  339. {
  340.     register int t;
  341.  
  342.     if ((t=p->type)>CHAR && t<PTR && t!=okt)
  343.         error("Integer operand required");
  344.     return;
  345. }
  346.  
  347. /*
  348.  *'linearize' a type for looking up in the
  349.  * conversion table
  350.  */
  351. lintyp(t)
  352. {
  353.     switch(t) {
  354.  
  355.     case INT:
  356.     case CHAR:
  357.         return(0);
  358.  
  359.     case FLOAT:
  360.     case DOUBLE:
  361.         return(1);
  362.  
  363.     case LONG:
  364.         return(2);
  365.  
  366.     default:
  367.         return(3);
  368.     }
  369. }
  370.  
  371. /*
  372.  * Report an error.
  373.  */
  374. error(s, p1, p2, p3, p4, p5, p6)
  375. {
  376.     nerror++;
  377.     printf("%d: ", line);
  378.     printf(s, p1, p2, p3, p4, p5, p6);
  379.     printf("\n");
  380. }
  381.  
  382. /*
  383.  * Generate a node in an expression tree,
  384.  * setting the operator, type, degree (unused in this pass)
  385.  * and the operands.
  386.  */
  387. block(an, op, t, d, p1,p2,p3)
  388. int *p1, *p2, *p3;
  389. {
  390.     register int *ap, *p, n;
  391.     int *oldp;
  392.  
  393.     n = an+3;
  394.     p = gblock(n);
  395.     oldp = p;
  396.     ap = &op;
  397.     do {
  398.         *p++ = *ap++;
  399.     } while (--n);
  400.     return(oldp);
  401. }
  402.  
  403. /*
  404.  * Assign an unitialized block for use in the
  405.  * expression tree.
  406.  */
  407. gblock(n)
  408. {
  409.     register int *p;
  410.  
  411.     p = space;
  412.     if ((space =+ n) >= &osspace[OSSIZ]) {
  413.         error("Expression overflow");
  414.         exit(1);
  415.     }
  416.     return(p);
  417. }
  418.  
  419. /*
  420.  * Check that a tree can be used as an lvalue.
  421.  */
  422. chklval(ap)
  423. struct tnode *ap;
  424. {
  425.     register struct tnode *p;
  426.  
  427.     p = ap;
  428.     if (p->op!=NAME && p->op!=STAR)
  429.         error("Lvalue required");
  430. }
  431.  
  432. /*
  433.  * reduce some forms of `constant op constant'
  434.  * to a constant.  More of this is done in the next pass
  435.  * but this is used to allow constant expressions
  436.  * to be used in switches and array bounds.
  437.  */
  438. fold(op, ap1, ap2)
  439. struct tnode *ap1, *ap2;
  440. {
  441.     register struct tnode *p1;
  442.     register int v1, v2;
  443.  
  444.     p1 = ap1;
  445.     if (p1->op!=CON || (ap2!=0 && ap2->op!=CON))
  446.         return(0);
  447.     v1 = p1->value;
  448.     v2 = ap2->value;
  449.     switch (op) {
  450.  
  451.     case PLUS:
  452.         v1 =+ v2;
  453.         break;
  454.  
  455.     case MINUS:
  456.         v1 =- v2;
  457.         break;
  458.  
  459.     case TIMES:
  460.         v1 =* v2;
  461.         break;
  462.  
  463.     case DIVIDE:
  464.         v1 =/ v2;
  465.         break;
  466.  
  467.     case MOD:
  468.         v1 =% v2;
  469.         break;
  470.  
  471.     case AND:
  472.         v1 =& v2;
  473.         break;
  474.  
  475.     case OR:
  476.         v1 =| v2;
  477.         break;
  478.  
  479.     case EXOR:
  480.         v1 =^ v2;
  481.         break;
  482.  
  483.     case NEG:
  484.         v1 = - v1;
  485.         break;
  486.  
  487.     case COMPL:
  488.         v1 = ~ v1;
  489.         break;
  490.  
  491.     case LSHIFT:
  492.         v1 =<< v2;
  493.         break;
  494.  
  495.     case RSHIFT:
  496.         v1 =>> v2;
  497.         break;
  498.  
  499.     default:
  500.         return(0);
  501.     }
  502.     p1->value = v1;
  503.     *cp++ = p1;
  504.     return(1);
  505. }
  506.  
  507. /*
  508.  * Compile an expression expected to have constant value,
  509.  * for example an array bound or a case value.
  510.  */
  511. conexp()
  512. {
  513.     register struct tnode *t;
  514.  
  515.     initflg++;
  516.     if (t = tree())
  517.         if (t->op != CON)
  518.             error("Constant required");
  519.     initflg--;
  520.     return(t->value);
  521. }
  522.