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