home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / language / sozobon2 / fun.c < prev    next >
C/C++ Source or Header  |  1993-10-23  |  12KB  |  767 lines

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