home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / compiler / sozobon / scsrc20 / hcc / fun.c < prev    next >
C/C++ Source or Header  |  1991-02-22  |  12KB  |  766 lines

  1. /* Copyright (c) 1988,1991 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.  *    fun.c
  12.  *
  13.  *    Handle function entry, exit, etc.
  14.  *    Parse statements.
  15.  *    Also, general syntax error recovery strategy.
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include "param.h"
  20. #include "tok.h"
  21. #include "nodes.h"
  22. #include "cookie.h"
  23.  
  24. #if MMCC
  25. overlay "pass2"
  26. #endif
  27.  
  28. extern NODE *cur;
  29.  
  30. int level;
  31. NODE *blktab;
  32. NODE *labels;
  33.  
  34. struct swittbl {
  35.     NODEP    caselist;
  36.     int    deflbl;
  37. } *curswit;
  38.  
  39. int curbrk, curcont;
  40. int funtopl, funbotl, funretl, funstrl;
  41. NODEP funtyp;
  42. int maxregs;
  43. long maxlocs;
  44.  
  45. int skipon;
  46.  
  47. NODEP glb_decls();
  48.  
  49. extern int oflags[];
  50. #define debugl oflags['l'-'a']
  51. #define debugs oflags['s'-'a']
  52. #define debugv oflags['v'-'a']
  53.  
  54. findtok(x)
  55. {
  56.     while (cur->e_token != EOFTOK && cur->e_token != x)
  57.         fadvnode();
  58.     if (cur->e_token == EOFTOK)
  59.         exit(1);
  60. }
  61.  
  62. program()
  63. {
  64.     extern NODEP symtab[];
  65.     NODEP last;
  66.  
  67.     skipon = 0;
  68. more:
  69.     last = glb_decls();
  70.     if (cur->e_token == EOFTOK)
  71.         return;
  72.     if (last) skipon = 0;    /* saw something valid */
  73.     if (last && last->n_tptr && last->n_tptr->t_token == '(') {
  74.     /* possible function definition */
  75.         if (debugs) {
  76.             printf("FUN ");
  77.             put_nnm(last);
  78.         }
  79.         out_fstart(last);
  80. #ifdef OUT_AZ
  81.         last->e_sc = HERE_SC;
  82. #else
  83.         last->e_sc = K_EXTERN;
  84. #endif
  85.         fun_start(last->n_tptr);
  86.         args_blk(last->n_tptr->n_right);
  87.         sub_block();
  88.         fun_end();
  89.         clr_lvl(); /* for args block */
  90.         goto more;
  91.     }
  92.     /* error if get to here */
  93.     if (last) {
  94.         error("missing ;");
  95.         goto more;
  96.     } else {
  97.         skip();
  98.         goto more;
  99.     }
  100. }
  101.  
  102. fun_start(np)
  103. NODEP np;
  104. {
  105.     NODEP functy();
  106.  
  107.     funtyp = functy(np);
  108.     curbrk = curcont = -1;
  109.     funtopl = new_lbl();
  110.     funbotl = new_lbl();
  111.     funretl = new_lbl();
  112.     switch (funtyp->t_token) {
  113.     case K_STRUCT:
  114.     case K_UNION:
  115.         funstrl = new_lbl();
  116.         break;
  117.     default:
  118.         funstrl = 0;
  119.     }
  120.     maxregs = 0;
  121.     maxlocs = 0;
  122.     out_br(funbotl);
  123.     def_lbl(funtopl);
  124. }
  125.  
  126. fun_end()
  127. {
  128.     NODEP np;
  129.  
  130.     if (labels) {
  131.         for (np = labels; np; np = np->n_next)
  132.             if (np->c_defined == 0)
  133.                 errorn("undefined label", np);
  134.         freenode(labels);
  135.         labels = NULL;
  136.     }
  137.     def_lbl(funretl);
  138.     out_fret(maxregs, funstrl);
  139.     def_lbl(funbotl);
  140.     out_fend(maxregs, maxlocs);
  141.     out_br(funtopl);
  142.     if (funstrl)
  143.         out_fs(funstrl, funtyp->t_size);
  144. }
  145.  
  146. skip()
  147. {
  148.     if (skipon == 0) {
  149.         error("syntax (try skipping...)");
  150.         skipon = 1;
  151.     }
  152.     fadvnode();
  153. }
  154.  
  155. block()
  156. {
  157.     int some;
  158.     int sawsome;
  159.  
  160.     some = loc_decls();
  161.     if (cur->e_token == EOFTOK)
  162.         return;
  163.     if (some) skipon = 0;
  164. more:
  165.     sawsome = stmts(); 
  166.     if (sawsome) skipon = 0;
  167.     if (cur->e_token == '}') {
  168.         maxregs |= blktab->b_regs;
  169.         if (blktab->b_size + blktab->b_tsize > maxlocs)
  170.             maxlocs = blktab->b_size + blktab->b_tsize;
  171.         return;
  172.     }
  173.  
  174.     /* error if get to here */
  175.     if (cur->e_token == EOFTOK || is_tykw(cur->e_token))
  176.         /* get out of block */
  177.         return;
  178.     else {
  179.         skip();
  180.         goto more;
  181.     }
  182. }
  183.  
  184. clr_lvl()
  185. {
  186.     NODE *bp;
  187.  
  188.     level--;
  189.     bp = blktab;
  190.     blktab = bp->n_next;
  191.     bp->n_next = NULL;
  192.     if (debugl && bp->b_syms) {
  193.         printf("local syms %d", level);
  194.         printlist(bp->b_syms);
  195.     }
  196. #ifdef OUT_AZ
  197.     xrefl(bp->b_syms);
  198. #endif
  199.     freenode(bp->b_syms);
  200.     if (debugl && bp->b_tags) {
  201.         printf("local tags %d", level);
  202.         printlist(bp->b_tags);
  203.     }
  204.     freenode(bp->b_tags);
  205.     freenode(bp);
  206. }
  207.  
  208. eat(c)
  209. {
  210.     char *p = "assume X";
  211.  
  212.     if (cur->e_token == c)
  213.         fadvnode();
  214.     else {
  215.         p[strlen(p) - 1] = c;
  216.         error(p);
  217.     }
  218. }
  219.  
  220. sub_block()
  221. {
  222.     register NODE *new;
  223.  
  224.     if (debugs)
  225.         printf("{ ");
  226.     eat('{');
  227.     level++;
  228.     new = allocnode();
  229.     new->n_next = blktab;
  230.     sprintf(new->n_name, "sub{");
  231.     blktab = new;
  232.     block();
  233.     clr_lvl();
  234.     eat('}');
  235.     if (debugs)
  236.         printf("}\n");
  237. }
  238.  
  239. args_blk(np)
  240. NODEP np;
  241. {
  242.     register NODE *p;
  243.     register NODE *new;
  244.     NODE *tp;
  245.     NODEP llook();
  246.     long size;
  247.     int rmask;
  248.  
  249.     size = 0;
  250.     rmask = 0;
  251.     new = allocnode();
  252.     new->n_next = blktab;
  253.     sprintf(new->n_name, "arg{");
  254.     blktab = new;
  255.     level++;
  256.     loc_decls();
  257.     /* make sure all decls were in arg list */
  258.     for (p=new->b_syms; p != NULL; p = p->n_next)
  259.         if (llook(np, p) == NULL)
  260.             errorn("ID not param", p);
  261.     /* now make any names not mentioned INT */
  262.     /* and generate offsets and alloc regs */
  263.     for (p=np; p != NULL; p = p->n_next) {
  264.         if ((tp=llook(new->b_syms, p)) == NULL) {
  265.             def_arg(&new->b_syms, p);
  266.             tp = new->b_syms;
  267.         }
  268.         lc_size(&size, &rmask, tp);
  269.         if (tp->e_sc == K_REGISTER)
  270.             reg_arg(&rmask, tp);
  271.         if (debugv) {
  272.             printf("final o%ld r%d ", tp->e_offs, tp->e_rno);
  273.             put_nnm(tp);
  274.             putchar('\n');
  275.         }
  276.         out_advice(tp);
  277.     }
  278.     new->b_regs = rmask;
  279. }
  280.  
  281. reg_arg(rp, xp)
  282. int *rp;
  283. NODEP xp;
  284. {
  285.     if (lc_reg(rp, xp) == 0) {    /* out of regs? */
  286.         xp->e_sc = K_AUTO;
  287.         return;
  288.     }
  289.     out_argreg(xp);
  290. }
  291.  
  292.  
  293. stmts()
  294. {
  295.     int didsome;
  296.  
  297.     didsome = 0;
  298.     while (stmt())
  299.         didsome++;
  300.     return didsome;
  301. }
  302.  
  303. stmt_bc(brk,cont)
  304. {
  305.     int svb, svc;
  306.  
  307.     svb = curbrk;
  308.     svc = curcont;
  309.     curbrk = brk;
  310.     curcont = cont;
  311.  
  312.     stmt();
  313.  
  314.     curbrk = svb;
  315.     curcont = svc;
  316. }
  317.  
  318. stmt_b(brk)
  319. {
  320.     int svb;
  321.  
  322.     svb = curbrk;
  323.     curbrk = brk;
  324.  
  325.     stmt();
  326.  
  327.     curbrk = svb;
  328. }
  329.  
  330. /* do a single statement */
  331. stmt()
  332. {
  333.     register tok;
  334.     NODEP np;
  335.     NODEP getexpr();
  336.     int i;
  337.  
  338. more:
  339.     tok = cur->e_token;
  340.     if (is_stkw(tok)) {
  341.         if (is_blkst(tok)) {
  342.             i = blk_stmt();
  343.         } else if (is_brast(tok)) {
  344.             i = bra_stmt();
  345.         } else if (is_lblst(tok)) {
  346.             i = lbl_stmt();
  347.         } else {
  348.             asm_stmt();
  349.             return 1;
  350.         }
  351.         if (i == 0)
  352.             goto more;
  353.         return 1;
  354.     }
  355.     else if (tok == '{') {
  356.         sub_block();
  357.         return 1;
  358.     } else if (tok == ';') {
  359.         fadvnode();
  360.         return 1;
  361.     }
  362.     np = getexpr();
  363.     if (np) {
  364.         if (cur->e_token == ':') {
  365.             fadvnode();
  366.             label(np);
  367.             goto more;
  368.         }
  369.         expr_stmt(np);
  370.         if (cur->e_token != ';')
  371.             error("missing ;");
  372.         else
  373.             fadvnode();
  374.         return 1;
  375.     }
  376.     return 0;
  377. }
  378.  
  379. expr_stmt(np)
  380. NODEP np;
  381. {
  382.     if (debugs) {
  383.         printf("E_STMT ");
  384.         if (debugs > 1)
  385.             printnode(np);
  386.     }
  387.     do_expr(np, FORSIDE);
  388. }
  389.  
  390. label(np)
  391. NODEP np;
  392. {
  393.     register NODEP tp;
  394.     NODEP llook();
  395.  
  396.     if (debugs) {
  397.         printf("LABEL ");
  398.         if (debugs > 1)
  399.             printnode(np);
  400.     }
  401.     if (np->e_token != ID) {
  402.         error("weird label");
  403.         return;
  404.     }
  405.     tp = llook(labels, np);
  406.     if (tp) {
  407.         freenode(np);
  408.         if (tp->c_defined) {
  409.             error("duplicate label");
  410.             return;
  411.         }
  412.     } else {
  413.         putlist(&labels, np);
  414.         tp = np;
  415.         tp->c_casel = new_lbl();
  416.     }
  417.     tp->c_defined = 1;
  418.     def_lbl(tp->c_casel);
  419. }
  420.  
  421. blk_stmt()
  422. {
  423.     register tok;
  424.     int l1, l2, l3;
  425.     NODEP e1, e2, e3;
  426.     NODEP opt_expr(), paren_expr(), def_type();
  427.     struct swittbl locswit, *oldp;
  428.     extern int lineno;
  429.     int svline, svline2;
  430.  
  431.     tok = cur->e_token;
  432.     fadvnode();
  433.     switch (tok) {
  434.     case K_IF:
  435.         if (debugs)
  436.             printf("IF ");
  437.         l1 = new_lbl();
  438.         e1 = paren_expr();
  439.         gen_brf(e1, l1);
  440.         eat(')');
  441.         stmt();
  442.         opt_else(l1);
  443.         return 1;
  444.     case K_WHILE:
  445.         if (debugs)
  446.             printf("WHILE ");
  447.         e1 = paren_expr();
  448.         l1 = new_lbl();
  449.         l2 = new_lbl();
  450.  
  451.         def_lbl(l1);
  452.         gen_brf(e1,l2);
  453.         eat(')');
  454.  
  455.         stmt_bc(l2,l1);
  456.  
  457.         out_br(l1);
  458.         def_lbl(l2);
  459.         return 1;
  460.     case K_DO:
  461.         if (debugs)
  462.             printf("DO ");
  463.         l1 = new_lbl();
  464.         l2 = new_lbl();
  465.         l3 = new_lbl();
  466.         def_lbl(l1);
  467.  
  468.         stmt_bc(l3,l2);
  469.  
  470.         def_lbl(l2);
  471.         eat(K_WHILE);
  472.         e1 = paren_expr();
  473.         gen_brt(e1, l1);
  474.         eat(')');
  475.         eat(';');
  476.         def_lbl(l3);
  477.         return 1;
  478.     case K_FOR:
  479.         if (debugs)
  480.             printf("FOR ");
  481.         l1 = new_lbl();
  482.         l2 = new_lbl();
  483.         l3 = new_lbl();
  484.         eat('(');
  485.         e1 = opt_expr();
  486.         expr_stmt(e1);
  487.         eat(';');
  488.         def_lbl(l1);
  489.         e2 = opt_expr();
  490.         if (e2)
  491.             gen_brf(e2,l3);
  492.         eat(';');
  493.         e3 = opt_expr();    /* save for later */
  494.         svline = lineno;
  495.         eat(')');
  496.  
  497.         stmt_bc(l3,l2);
  498.  
  499.         def_lbl(l2);
  500.  
  501.         svline2 = lineno;
  502.         lineno = svline;
  503.         expr_stmt(e3);
  504.         lineno = svline2;
  505.  
  506.         out_br(l1);
  507.         def_lbl(l3);
  508.         return 1;
  509.     case K_SWITCH:
  510.         if (debugs)
  511.             printf("SWITCH ");
  512.         e1 = paren_expr();
  513.         l1 = new_lbl();
  514.         l2 = new_lbl();
  515.         to_d0(e1, def_type());
  516.         eat(')');
  517.  
  518.         out_br(l2);
  519.         oldp = curswit;
  520.         curswit = &locswit;
  521.         locswit.caselist = NULL;
  522.         locswit.deflbl = -1;
  523.  
  524.         stmt_b(l1);
  525.  
  526.         out_br(l1);
  527.         def_lbl(l2);
  528.         gen_switch(locswit.caselist, locswit.deflbl);
  529.         curswit = oldp;
  530.         def_lbl(l1);
  531.         return 1;
  532.     case K_ELSE:
  533.         error("unexpected 'else'");
  534.         fadvnode();
  535.         return 0;
  536.     }
  537. }
  538.  
  539. NODEP
  540. paren_expr()
  541. {
  542.     NODEP np;
  543.     NODEP need_expr();
  544.  
  545.     eat('(');
  546.     np = need_expr();
  547.     return np;
  548. }
  549.  
  550. bra_stmt()
  551. {
  552.     register tok;
  553.     NODEP np, tp;
  554.     NODEP opt_expr(), llook();
  555.  
  556.     tok = cur->e_token;
  557.     fadvnode();
  558.     switch (tok) {
  559.     case K_BREAK:
  560.         if (debugs)
  561.             printf("BRK");
  562.         eat(';');
  563.         out_br(curbrk);
  564.         return 1;
  565.     case K_CONTINUE:
  566.         if (debugs)
  567.             printf("CONT ");
  568.         eat(';');
  569.         out_br(curcont);
  570.         return 1;
  571.     case K_RETURN:
  572.         if (debugs)
  573.             printf("RETURN ");
  574.         np = opt_expr();
  575.         if (np) {
  576.             if (funstrl)
  577.                 ret_stru(np);
  578.             else
  579.                 to_d0(np, funtyp);
  580.         }
  581.         out_br(funretl);
  582.         eat(';');
  583.         return 1;
  584.     case K_GOTO:
  585.         if (debugs)
  586.             printf("GOTO ");
  587.         np = cur;  advnode();
  588.         if (np->e_token != ID)
  589.             error("bad goto");
  590.         else {
  591.             tp = llook(labels, np);
  592.             if (tp) {
  593.                 freenode(np);    
  594.             } else {
  595.                 tp = np;
  596.                 putlist(&labels, tp);
  597.                 tp->c_casel = new_lbl();
  598.             }
  599.             out_br(tp->c_casel);
  600.         }
  601.         eat(';');
  602.         return 1;
  603.     }
  604. }
  605.  
  606. lbl_stmt()
  607. {
  608.     register tok;
  609.     NODEP need_expr(), np;
  610.     int l1, i;
  611.  
  612.     l1 = new_lbl();
  613.     tok = cur->e_token;
  614. again:
  615.     fadvnode();
  616.     switch (tok) {
  617.     case K_CASE:
  618.         if (debugs)
  619.             printf("CASE ");
  620.         np = need_expr();
  621.         i = conxval(np);
  622.         if (curswit)
  623.             add_case(i,l1);
  624.         else
  625.             error("'case' outside switch");
  626.         eat(':');
  627.         break;
  628.     case K_DEFAULT:
  629.         if (debugs)
  630.             printf("DEFAULT ");
  631.         if (curswit) {
  632.             if (curswit->deflbl >= 0)
  633.                 error("multiple 'default'");
  634.             curswit->deflbl = l1;
  635.         } else
  636.             error("'default' outside switch");
  637.         eat(':');
  638.     }
  639.     tok = cur->e_token;    /* lookahead for more cases */
  640.     if (tok == K_CASE || tok == K_DEFAULT)
  641.         goto again;
  642.     def_lbl(l1);
  643.     return 0;
  644. }
  645.  
  646. asm_stmt()
  647. {
  648.     NODEP np, getexpr();
  649.  
  650.     fadvnode();
  651.     np = getexpr();
  652.     if (np == NULL || np->e_token != SCON) {
  653.         error("bad asm() func");
  654.     } else {
  655.         out_asm(np);
  656.         freenode(np);
  657.     }
  658.     eat(';');
  659. }
  660.  
  661. NODEP
  662. opt_expr()
  663. {
  664.     NODE *np, *getexpr();
  665.  
  666.     np = getexpr();
  667.     if (np) {
  668.         if (debugs) {
  669.             printf("OXPR ");
  670.             if (debugs > 1)
  671.                 printnode(np);
  672.         }
  673.     }
  674.     return np;
  675. }
  676.  
  677. NODEP
  678. need_expr()
  679. {
  680.     NODE *np, *getexpr();
  681.  
  682.     np = getexpr();
  683.     if (np) {
  684.         if (debugs) {
  685.             printf("NXPR ");
  686.             if (debugs > 1)
  687.                 printnode(np);
  688.         }
  689.     } else
  690.         error("need expr");
  691.     return np;
  692. }
  693.  
  694. opt_else(l1)
  695. {
  696.     int l2;
  697.  
  698.     if (cur->e_token == K_ELSE) {
  699.         if (debugs)
  700.             printf("ELSE ");
  701.         fadvnode();
  702.         l2 = new_lbl();
  703.         out_br(l2);
  704.         def_lbl(l1);
  705.         stmt();
  706.         def_lbl(l2);
  707.     } else
  708.         def_lbl(l1);
  709. }
  710.  
  711. add_case(val, lbl)
  712. {
  713.     NODEP np, last, p;
  714.  
  715.     np = allocnode();
  716.     np->c_casev = val;
  717.     np->c_casel = lbl;
  718.     sprintf(np->n_name, "%d:%d", val, lbl);
  719.  
  720.     last = NULL;
  721.     for (p = curswit->caselist; p; last=p, p=p->n_next)
  722.         if (p->c_casev == val) {
  723.             error("duplicate case");
  724.             return;
  725.         } else if (p->c_casev > val)
  726.             break;
  727.     if (last) {
  728.         last->n_next = np;
  729.         np->n_next = p;
  730.     } else {
  731.         curswit->caselist = np;
  732.         np->n_next = p;
  733.     }
  734.     if (debugs) {
  735.         printf("CASELIST\n");
  736.         printnode(curswit->caselist);
  737.     }
  738. }
  739.  
  740. to_d0(np, typ)
  741. NODEP np, typ;
  742. {
  743.     NODEP tp;
  744.  
  745.     tp = allocnode();
  746.     tp->e_token = TCONV;
  747.     tp->n_tptr = typ;
  748.     tp->n_flags |= N_COPYT;
  749.     tp->n_left = np;
  750.     tp->e_type = E_UNARY;
  751.     strcpy(tp->n_name, "r cast");
  752.  
  753.     do_expr(tp, IND0);
  754. }
  755.  
  756. ret_stru(np)
  757. NODEP np;
  758. {
  759.     p2_expr(&np);
  760.     if (same_type(np->n_tptr, funtyp) == 0) {
  761.         error("bad struct return type");
  762.         return;
  763.     }
  764.     genx(np, RETSTRU);    
  765. }
  766.