home *** CD-ROM | disk | FTP | other *** search
/ CD Shareware Magazine 1996 December / CD_shareware_12-96.iso / DOS / Programa / CCDL122.ZIP / SOURCE / STMT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-03  |  22.2 KB  |  787 lines

  1. /*
  2.  * 68K/386 32-bit C compiler.
  3.  *
  4.  * copyright (c) 1996, David Lindauer
  5.  * 
  6.  * This compiler is intended for educational use.  It may not be used
  7.  * for profit without the express written consent of the author.
  8.  *
  9.  * It may be freely redistributed, as long as this notice remains intact
  10.  * and sources are distributed along with any executables derived from them.
  11.  *
  12.  * The author is not responsible for damages, either direct or consequential,
  13.  * that may arise from use of this software.
  14.  *
  15.  * v1.5 August 1996
  16.  * David Lindauer, gclind01@starbase.spd.louisville.edu
  17.  *
  18.  * Credits to Mathew Brandt for original K&R C compiler
  19.  *
  20.  */
  21. #include        <stdio.h> 
  22. #include        "expr.h" 
  23. #include        "c.h" 
  24. #include        "gen.h"
  25. #include        "cglbdec.h" 
  26.  
  27. extern SYM *currentfunc;
  28. extern int skm_closepa[];
  29. extern int incldepth;
  30. extern int inline[4096];
  31. extern int goodcode;
  32. extern TABLE oldlsym;
  33. extern int prm_cplusplus;
  34.  
  35. int skm_openpa[] = { openpa, begin, semicolon, 0 };
  36. int skm_semi[] = { semicolon, end, 0 };
  37.  
  38. static char phibuf[4096];
  39. static int lastlineno = 0;
  40.  
  41. SNODE *cbautoinithead, *cbautoinittail;
  42.  
  43. int scanassign(ENODE *node)
  44. {  
  45.         if( node == 0 )
  46.                 return 0;
  47.         switch( node->nodetype ) {
  48.                 case en_rcon:
  49.                 case en_icon:
  50.                 case en_nalabcon:
  51.                 case en_napccon:
  52.                 case en_nacon:
  53.                                 case en_absacon:
  54.                 case en_autocon:
  55.                 case en_autoreg:
  56.                                                 return FALSE;
  57.                                 case en_bits:
  58.                                 case en_floatref:
  59.                                 case en_doubleref:
  60.                                 case en_longdoubleref:
  61.                 case en_b_ref:
  62.                 case en_w_ref:
  63.                 case en_ul_ref:
  64.                 case en_l_ref:
  65.                 case en_ub_ref:
  66.                 case en_uw_ref:
  67.                 case en_uminus:
  68.                 case en_compl:  case en_ainc:
  69.                 case en_adec:   case en_not:
  70.                                 case en_cb: case en_cub:
  71.                                 case en_cw: case en_cuw:
  72.                                 case en_cl: case en_cul:
  73.                                 case en_cf: case en_cd: case en_cp: case en_cld:
  74.                                             return scanassign(node->v.p[0]);
  75.                 case en_eq:     case en_ne:
  76.                 case en_gt:     case en_ge:
  77.                 case en_lt:     case en_le:
  78.                                 case en_ugt:    case en_uge: case en_ult: case en_ule:
  79.                                             return 0;        /* No error if a conditional is higher than an equate */
  80.                 case en_asadd:  case en_assub:
  81.                                 case en_asalsh: case en_asarsh: case en_alsh: case en_arsh:
  82.                 case en_asmul:  case en_asdiv:
  83.                 case en_asmod:  case en_aslsh:
  84.                                 case en_asumod: case en_asudiv: case en_asumul:
  85.                 case en_mul:    case en_div:
  86.                 case en_umul:    case en_udiv: case en_umod:
  87.                 case en_lsh:    case en_rsh:
  88.                 case en_mod:    case en_and:
  89.                 case en_or:     case en_xor:
  90.                 case en_lor:    case en_land:
  91.                               case en_pmul:
  92.                 case en_asrsh:  case en_asand:  case en_pdiv:
  93.                 case en_asor:   case en_cond:
  94.                 case en_void:   
  95.                                 case en_moveblock: case en_stackblock:
  96.                 case en_add:    case en_sub: case en_refassign:
  97.                         return scanassign(node->v.p[0]) || scanassign(node->v.p[1]);
  98.                                 case en_assign:
  99.                                                 return 1;    /* Error if assign higher than conditional */
  100.                 }
  101.     return 0;
  102. }
  103. TYP *doassign(ENODE **exp, int canerror, int *skm)
  104. {
  105.     TYP *tp;
  106.   if( (tp =expression(exp)) == 0 )  {
  107.         if (canerror)
  108.         generror(ERR_EXPREXPECT,0,skm); 
  109.         *exp = 0;
  110.   }
  111.     else {
  112.         if (scanassign(*exp))
  113.             generror(ERR_BADEQUATE,0,0);
  114.     }
  115.     return tp;
  116. }
  117. SNODE    *whilestmt(void) 
  118. /* 
  119.  *      whilestmt parses the c while statement. 
  120.  */ 
  121. {       SNODE    *snp; 
  122.                 int ogc = goodcode;
  123.                 goodcode |= GF_INLOOP;
  124.         snp = xalloc(sizeof(SNODE)); 
  125.         snp->stype = st_while; 
  126.                 snp->s1 = 0;
  127.         getsym(); 
  128.                 needpunc(openpa,0);
  129.                 doassign(&snp->exp,TRUE,0);
  130.                 
  131.         needpunc( closepa,skm_closepa );
  132.                 goodcode |= GF_CONTINUABLE; 
  133.         snp->s1 = cppblockedstatement(); 
  134.                 goodcode = ogc; 
  135.         return snp; 
  136.   
  137. SNODE    *dostmt(void) 
  138. /* 
  139.  *      dostmt parses the c do-while construct. 
  140.  */ 
  141. {       SNODE    *snp; 
  142.                 int ogc = goodcode;
  143.                 goodcode |= GF_INLOOP;
  144.         snp = xalloc(sizeof(SNODE)); 
  145.         snp->stype = st_do; 
  146.         getsym(); 
  147.                 goodcode |= GF_CONTINUABLE; 
  148.         snp->s1 = cppblockedstatement(); 
  149.                 goodcode = ogc; 
  150.         if( lastst != kw_while ) 
  151.                                 gensymerror(ERR_IDENTEXPECT,lastid);
  152.         else   
  153.           getsym();
  154.                 needpunc(openpa,0); 
  155.                 doassign(&snp->exp,TRUE,0);
  156.         needpunc(closepa,skm_closepa); 
  157.         if( lastst != end && lastst != eof)
  158.           needpunc( semicolon,0 );
  159.         return snp; 
  160.   
  161. SNODE    *forstmt(void) 
  162. {       SNODE    *snp; 
  163.                 int ogc = goodcode;
  164.                 int plussemi = 0;
  165.                 goodcode |= GF_INLOOP;
  166.         snp = xalloc(sizeof(SNODE)); 
  167.         getsym(); 
  168.                 snp->label = snp->exp = snp->s2 = 0;
  169.         snp->stype = st_for; 
  170.         if (needpunc(openpa,skm_closepa)) { 
  171.                     if (castbegin(lastst)) {
  172.                         if (prm_cplusplus) {
  173.                             ENODE *exp=0,**next = &exp;
  174.                             cbautoinithead = cbautoinittail = 0;
  175.                             dodecl(sc_auto);
  176.                             while (cbautoinithead) {
  177.                                 if (*next) {
  178.                                     *next = makenode(en_void,(*next),cbautoinithead->exp);
  179.                                     next = &(*next)->v.p[1];
  180.                                 }
  181.                                 else *next = cbautoinithead->exp;
  182.                                 cbautoinithead = cbautoinithead->next;
  183.                             }
  184.                             snp->label = exp;
  185.                             plussemi = 1;
  186.                         }
  187.                         else {
  188.                             generror(ERR_NODECLARE,0,0);
  189.                             while (castbegin(lastst))
  190.                                 getsym();
  191.                             goto forjoin;
  192.                         }
  193.                     }
  194.                     else {
  195. forjoin:
  196.                         if( expression(&snp->label) == 0 ) 
  197.                             snp->label = 0;
  198.                         plussemi = needpunc(semicolon,0);
  199.                     }
  200.                     if (plussemi) {
  201.                         doassign(&snp->exp,FALSE,0);
  202.                         if (needpunc(semicolon,0)) {
  203.                             if( expression(&snp->s2) == 0 )  {
  204.                                 snp->s2 = 0;
  205.                             }
  206.                       }
  207.                     }
  208.             needpunc(closepa,skm_closepa); 
  209.                 }
  210.                 goodcode |= GF_CONTINUABLE; 
  211.         snp->s1 = cppblockedstatement(); 
  212.                 goodcode = ogc; 
  213.         return snp; 
  214.   
  215. SNODE    *ifstmt(void) 
  216. /* 
  217.  *      ifstmt parses the c if statement and an else clause if 
  218.  *      one is present. 
  219.  */ 
  220. {       SNODE    *snp;
  221.                 int ogc = goodcode; 
  222.                 int temp=0;
  223.         snp = xalloc(sizeof(SNODE)); 
  224.         snp->stype = st_if; 
  225.         getsym();
  226.                 needpunc(openpa,0); 
  227.                 doassign(&snp->exp,TRUE,0);
  228.         needpunc( closepa,skm_closepa ); 
  229.         snp->s1 = cppblockedstatement(); 
  230.         if( lastst == kw_else ) { 
  231.                     temp = goodcode & (GF_RETURN | GF_BREAK | GF_CONTINUE | GF_GOTO);
  232.                     goodcode = ogc;
  233.           getsym(); 
  234.           snp->s2 = cppblockedstatement(); 
  235.                     temp = temp & goodcode;
  236.         } 
  237.         else 
  238.           snp->s2 = 0; 
  239.                 goodcode = ogc | temp;
  240.         return snp; 
  241.   
  242. SNODE    *casestmt(void) 
  243. /* 
  244.  *      cases are returned as seperate statements. for normal 
  245.  *      cases label is the case value and s2 is zero. for the 
  246.  *      default case s2 is nonzero. 
  247.  */ 
  248. {       SNODE    *snp; 
  249.         SNODE    *head, *tail; 
  250.         snp = xalloc(sizeof(SNODE)); 
  251.         if( lastst == kw_case ) { 
  252.                 getsym(); 
  253.                 snp->s2 = 0;
  254.                 snp->stype = st_case;
  255.                 snp->label = (SNODE *)intexpr(0);
  256.                 } 
  257.         else if( lastst == kw_default) { 
  258.                                 goodcode |= GF_DEF;
  259.                 getsym(); 
  260.                 snp->stype = st_case;
  261.                 snp->s2 = (SNODE *)1; 
  262.                 } 
  263.         else    { 
  264.                 generror(ERR_NOCASE,0,0); 
  265.                 return 0; 
  266.                 } 
  267.         needpunc(colon,0); 
  268.         head = 0; 
  269.         while( lastst != end && lastst != eof &&
  270.                 lastst != kw_case && 
  271.                 lastst != kw_default ) { 
  272.                                 if (goodcode & (GF_RETURN | GF_BREAK | GF_CONTINUE | GF_GOTO)) {
  273.                                     generror(ERR_UNREACHABLE,0,0);
  274.                                 }
  275.                                 goodcode &= ~(GF_RETURN | GF_BREAK | GF_CONTINUE | GF_GOTO);
  276.                 if( head == 0 ) 
  277.                         head = tail = statement(); 
  278.                 else    { 
  279.                         tail->next = statement(); 
  280.                         } 
  281.                 while( tail->next != 0 ) 
  282.                   tail = tail->next; 
  283.                 }
  284.                 if (goodcode & GF_BREAK)
  285.                     goodcode &= ~GF_UNREACH;
  286.         snp->s1 = head; 
  287.         return snp; 
  288.   
  289. int     checkcases(SNODE *head) 
  290. /* 
  291.  *      checkcases will check to see if any duplicate cases 
  292.  *      exist in the case list pointed to by head. 
  293.  */ 
  294. {     
  295.     SNODE    *top, *cur;
  296.     top = head;
  297.     while( top != 0 )
  298.     {
  299.         cur = top->next;
  300.         while( cur != 0 )
  301.         {
  302.             if( (!(cur->s1 || cur->s2) && cur->label == top->label)
  303.                 || (cur->s2 && top->s2) )
  304.             {
  305.                 generror(ERR_DUPCASE,(int)cur->label,0);
  306.                 return 1;
  307.             }
  308.             cur = cur->next;
  309.         }
  310.         top = top->next;
  311.     }
  312.     return 0;
  313.   
  314. SNODE    *switchstmt(void) 
  315. {       SNODE    *snp; 
  316.         SNODE    *head, *tail; 
  317.                 TYP *tp;
  318.                 int ogc = goodcode;
  319.     TABLE oldoldlsym;
  320.     long oldlcauto;
  321.     if (prm_cplusplus) {
  322.         oldlcauto = lc_auto;
  323.         oldoldlsym = oldlsym;
  324.         oldlsym = lsyms;
  325.     }
  326.         snp = xalloc(sizeof(SNODE)); 
  327.         snp->stype = st_switch; 
  328.         getsym(); 
  329.         needpunc(openpa,0); 
  330.                 tp = doassign(&snp->exp,TRUE,0);
  331.                 if (tp) {
  332.                     switch  (tp->type) {
  333.                         case bt_char:
  334.                         case bt_unsignedchar:
  335.                         case bt_short:
  336.                         case bt_unsignedshort:
  337.                         case bt_long:
  338.                         case bt_unsigned:
  339.                         case bt_enum:
  340.                             break;
  341.                         default:
  342.                             generror(ERR_SWITCHINT,0,0);
  343.                     }
  344.                 }
  345.         needpunc(closepa, skm_closepa); 
  346.         needpunc(begin,0); 
  347.         head = 0; 
  348.                 goodcode |= GF_UNREACH;
  349.                 goodcode &= ~GF_DEF;
  350.         while( lastst != end && lastst != eof) { 
  351.                                 goodcode &= ~(GF_RETURN | GF_BREAK | GF_CONTINUE | GF_GOTO);
  352.                 if( head == 0 ) 
  353.                         head = tail = casestmt(); 
  354.                 else    { 
  355.                         tail->next = casestmt(); 
  356.                         if( tail->next != 0 ) 
  357.                                 tail = tail->next; 
  358.                         } 
  359.                 tail->next = 0; 
  360.                 } 
  361.                 if (goodcode & GF_RETURN) {
  362.                     if ((goodcode & GF_UNREACH)  && (goodcode & GF_DEF)) 
  363.                         ogc |= GF_RETURN;
  364.                 }
  365.                 goodcode = ogc;
  366.         snp->s1 = head; 
  367.         getsym(); 
  368.         checkcases(head);
  369.     if (prm_cplusplus) {
  370.         check_funcused(&oldlsym,&lsyms);
  371.         gather_labels(&oldlsym,&lsyms);
  372.         if (lc_auto > lc_maxauto) {
  373.             lc_maxauto = lc_auto;
  374.         }
  375.         cseg();
  376.         lc_auto = oldlcauto;
  377.         lsyms = oldlsym;
  378.         oldlsym.head = oldoldlsym.head;
  379.     }
  380.         return snp; 
  381.   
  382. SNODE    *retstmt(void) 
  383. {       SNODE    *snp; 
  384.                 TYP *tp;
  385.         snp = xalloc(sizeof(SNODE)); 
  386.         snp->stype = st_return; 
  387.                 snp->exp = 0;
  388.         getsym(); 
  389.                 if (lastst == end || lastst == semicolon) {
  390.                     if (currentfunc->tp->btp->type != bt_void)
  391.                         generror(ERR_RETMISMATCH,0,0);
  392.                     if (lastst == semicolon)
  393.                         getsym();
  394.                 }
  395.                 else {
  396.                     int ogc = goodcode;
  397.                     goodcode |= GF_SUPERAND;
  398.             tp = expression(&(snp->exp));
  399.                     goodcode = ogc;
  400.             if( lastst != end  && lastst != eof)
  401.                 needpunc( semicolon, 0 );
  402.                     if (tp->type == bt_void) {
  403.                         generror(ERR_NOVOIDRET,0,0);
  404.                     }
  405.                     else
  406.                         if (tp->type == bt_pointer && tp->val_flag)
  407.                             generror(ERR_NOFUNCARRAY,0,0);
  408.                         else
  409.                             if (!checktype(tp,currentfunc->tp->btp))
  410.                                 if (isscalar(tp) && isscalar(currentfunc->tp->btp))
  411.                                     promote_type(currentfunc->tp->btp, &(snp->exp));
  412.                                 else
  413.                                     if (currentfunc->tp->btp->type != bt_pointer ||
  414.                                             floatrecurse(snp->exp))
  415.                                         generror(ERR_RETMISMATCH,0,0);
  416.                 }
  417.         return snp; 
  418.   
  419. SNODE    *breakstmt(void) 
  420. {       SNODE    *snp; 
  421.         snp = xalloc(sizeof(SNODE)); 
  422.         snp->stype = st_break; 
  423.         getsym(); 
  424.         if( lastst != end && lastst != eof)
  425.                 needpunc( semicolon,0 );
  426.         return snp; 
  427.   
  428. SNODE    *contstmt(void) 
  429. {       SNODE    *snp; 
  430.         snp = xalloc(sizeof(SNODE)); 
  431.         snp->stype = st_continue; 
  432.                 if (!(goodcode & GF_CONTINUABLE))
  433.                     generror(ERR_NOCONTINUE,0,0);
  434.         getsym();
  435.         if( lastst != end && lastst != eof)
  436.                 needpunc( semicolon,0 );
  437.         return snp;
  438. }
  439. SNODE *_genwordstmt(void)
  440. {
  441.                 SNODE *snp;
  442.                 snp = xalloc(sizeof(SNODE));
  443.                 snp->stype = st__genword;
  444.                 snp->exp = 0;
  445.                 getsym();
  446.                 if (lastst != openpa) {
  447.                     generror(ERR_PUNCT,openpa,skm_semi);
  448.                     getsym();
  449.                     snp = 0;
  450.                 }
  451.                 else {
  452.                     getsym();
  453.                     snp->exp = (ENODE *) intexpr(0);
  454.                     if (lastst != closepa) {
  455.                         generror(ERR_PUNCT,closepa,skm_semi);
  456.                         snp = 0;
  457.                     }
  458.                     getsym();
  459.                 }
  460.                 if (lastst != end && lastst != eof)
  461.                     needpunc(semicolon,0);
  462.                 return(snp);
  463. }
  464. SNODE    *exprstmt(void) 
  465. /* 
  466.  *      exprstmt is called whenever a statement does not begin 
  467.  *      with a keyword. the statement should be an expression. 
  468.  */ 
  469. {       SNODE    *snp; 
  470.         snp = xalloc(sizeof(SNODE)); 
  471.         snp->stype = st_expr; 
  472.                 goodcode &= ~(GF_ASSIGN);
  473.               if( expression(&snp->exp) == 0 )  {
  474.                 generror(ERR_EXPREXPECT,0,skm_semi); 
  475.                     snp->exp = 0;
  476.               }
  477.                 if (!(goodcode & GF_ASSIGN))
  478.                     generror(ERR_CODENONE,0,0);
  479.         if( lastst != end && lastst != eof)
  480.                 needpunc( semicolon,0 );
  481.         return snp; 
  482.   
  483. SNODE *snp_line(void)
  484. {
  485.     SNODE *snp3 = 0;
  486.                 if (!incldepth && lineno != lastlineno && lastst != semicolon && lastst != begin) {
  487.                     int i = 0,j,l=pstrlen(inline);
  488.                     snp3 = xalloc(sizeof(SNODE));
  489.                     snp3->stype = st_line;
  490.                     snp3->exp = (ENODE *)lineno;
  491.                     snp3->next = 0;
  492.                     for (j=0; j<l; j++)
  493.                         i+= installphichar(inline[j],phibuf,i);
  494.                     if (phibuf[i-1] == '\n')
  495.                         i--;
  496.                     phibuf[i] = 0;
  497.                     if ((phibuf[i-1] & 0xf0) == 0x90)
  498.                         phibuf[i-1] = 0x90;
  499.                     snp3->label = (SNODE *)xalloc(i+1);
  500.                     strcpy(snp3->label, phibuf);
  501.                     lastlineno = lineno;
  502.                 }
  503.     return snp3;
  504. }
  505. void dodefaultinit(SYM *sp)
  506. {
  507.     TYP *tp;
  508.     if (lastst == assign) {
  509.         getsym();
  510.         if ((tp =autoasnop(&(sp->defalt), sp)) == 0) {
  511.              generror(ERR_EXPREXPECT,0,0);
  512.             getsym();
  513.         }
  514.         else sp->defalt = sp->defalt->v.p[1];
  515.     }
  516. }
  517. void doautoinit(SYM *sym)
  518. /*
  519.  * This is here rather than in init because autoinit is a type of 
  520.  * statement
  521.  */
  522. {
  523.         if (lastst == assign) {
  524.             SNODE *snp = snp_line();
  525.             if (snp) 
  526.                 if (cbautoinithead == 0)
  527.                     cbautoinithead = cbautoinittail = snp;
  528.                 else {
  529.                     cbautoinittail->next = snp;
  530.                     cbautoinittail= snp;
  531.                 }
  532.             getsym();
  533.             snp = xalloc(sizeof(SNODE));
  534.             snp->stype = st_expr;
  535.             if (autoasnop(&(snp->exp), sym) == 0) {
  536.                 generror(ERR_EXPREXPECT,0,0);
  537.                 getsym();
  538.             }
  539.             else {
  540.                 if (cbautoinithead == 0)
  541.                     cbautoinithead = cbautoinittail = snp;
  542.                 else {
  543.                     cbautoinittail->next = snp;
  544.                     cbautoinittail= snp;
  545.                 }
  546.             }
  547.         }
  548. }
  549.         
  550. SNODE    *compound(void) 
  551. /* 
  552.  *      compound processes a block of statements and forms a linked 
  553.  *      list of the statements within the block. 
  554.  * 
  555.  *      compound expects the input pointer to already be past the 
  556.  *      begin symbol of the block. 
  557.  */ 
  558. {       SNODE    *head, *tail; 
  559.         head = cbautoinithead;
  560.                 tail = cbautoinittail;
  561.                 goodcode &= ~(GF_RETURN | GF_BREAK | GF_CONTINUE | GF_GOTO);
  562.         while( lastst != end  && lastst != eof) { 
  563.                                 if (goodcode & (GF_RETURN | GF_BREAK | GF_CONTINUE | GF_GOTO)) 
  564.                                     generror(ERR_UNREACHABLE,0,0);
  565.                                 goodcode &= ~(GF_RETURN | GF_BREAK| GF_CONTINUE | GF_GOTO);
  566.                 if( head == 0 ) 
  567.                         head = tail = statement(); 
  568.                 else    { 
  569.                         tail->next = statement(); 
  570.                         } 
  571.                 while( tail->next != 0 ) 
  572.                   tail = tail->next; 
  573.                 } 
  574.                 if (head)
  575.                     tail->next = snp_line();
  576.                 if (lastst == eof)
  577.                     generror(ERR_PUNCT,end,0);
  578.                 else
  579.             getsym(); 
  580.  
  581.         return head; 
  582.   
  583. SNODE    *labelstmt(void) 
  584. /* 
  585.  *      labelstmt processes a label that appears before a 
  586.  *      statement as a seperate statement. 
  587.  */ 
  588. {       SNODE    *snp; 
  589.         SYM             *sp; 
  590.         snp = xalloc(sizeof(SNODE)); 
  591.         snp->stype = st_label; 
  592.         if( (sp = search(lastid,&lsyms)) == 0 ) { 
  593.                 sp = xalloc(sizeof(SYM)); 
  594.                 sp->name = litlate(lastid); 
  595.                 sp->storage_class = sc_label; 
  596.                                 sp->tp = xalloc(sizeof(TYP));
  597.                                 sp->tp->type = bt_unsigned;
  598.                                 sp->tp->uflags = 0;
  599.                 sp->value.i = nextlabel++; 
  600.                 insert(sp,&lsyms); 
  601.                 } 
  602.         else    { 
  603.                 if( sp->storage_class != sc_ulabel ) 
  604.                         gensymerror(ERR_DUPLABEL,sp->name); 
  605.                 else 
  606.                         sp->storage_class = sc_label; 
  607.                 } 
  608.         getsym();       /* get past id */ 
  609.         needpunc(colon,0); 
  610.         if( sp->storage_class == sc_label ) { 
  611.                 snp->label = (SNODE *)sp->value.i; 
  612.                 snp->next = 0; 
  613.                 return snp; 
  614.                 } 
  615.         return 0; 
  616.   
  617. SNODE    *gotostmt(void) 
  618. /* 
  619.  *      gotostmt processes the goto statement and puts undefined 
  620.  *      labels into the symbol table. 
  621.  */ 
  622. {       SNODE    *snp; 
  623.         SYM             *sp; 
  624.         getsym(); 
  625.         if( lastst != id ) { 
  626.                 generror(ERR_IDEXPECT,0,0); 
  627.                 return 0; 
  628.                 } 
  629.         snp = xalloc(sizeof(SNODE)); 
  630.         if( (sp = search(lastid,&lsyms)) == 0 ) { 
  631.                 sp = xalloc(sizeof(SYM)); 
  632.                 sp->name = litlate(lastid); 
  633.                 sp->value.i = nextlabel++; 
  634.                 sp->storage_class = sc_ulabel; 
  635.                                 sp->tp = xalloc(sizeof(TYP));
  636.                                 sp->tp->type = bt_unsigned;
  637.                 insert(sp,&lsyms); 
  638.                 } 
  639.                 sp->tp->uflags = UF_USED;
  640.         getsym();       /* get past label name */ 
  641.         if( lastst != end && lastst != eof)
  642.                 needpunc( semicolon,0 );
  643.         if( sp->storage_class != sc_label && sp->storage_class != sc_ulabel) 
  644.                 gensymerror( ERR_LABEL,sp->name); 
  645.         else    { 
  646.                 snp->stype = st_goto; 
  647.                 snp->label = (SNODE *)sp->value.i; 
  648.                 snp->next = 0; 
  649.                 return snp; 
  650.                 } 
  651.         return 0; 
  652.   
  653. SNODE    *statement(void) 
  654. /* 
  655.  *      statement figures out which of the statement processors 
  656.  *      should be called and transfers control to the proper 
  657.  *      routine. 
  658.  */ 
  659. {       SNODE    *snp, *snp2; 
  660.                 SNODE         *snp3=snp_line();
  661.  
  662.         switch( lastst ) { 
  663.                 case semicolon: 
  664.                         getsym(); 
  665.                         snp = 0; 
  666.                         break; 
  667.                 case begin: 
  668.                         getsym(); 
  669.                         snp2 = compoundblock(); 
  670.                                                 snp = xalloc(sizeof(SNODE));
  671.                                                 snp->exp = snp2;
  672.                                                 snp->stype = st_block;
  673.                                                 break;
  674.                 case kw_if: 
  675.                         snp = ifstmt(); 
  676.                         break; 
  677.                 case kw_while: 
  678.                         snp = whilestmt(); 
  679.                                                 snp->lst = snp3;
  680.                                                 snp3 = 0;
  681.                         break; 
  682.                 case kw_for: 
  683.                         snp = forstmt(); 
  684.                                                 snp->lst = snp3;
  685.                                                 snp3 = 0;
  686.                         break; 
  687.                 case kw_return: 
  688.                         snp = retstmt(); 
  689.                                                 goodcode |= GF_RETURN;
  690.                         break; 
  691.                 case kw_break: 
  692.                                                 goodcode |= GF_BREAK;
  693.                         snp = breakstmt(); 
  694.                         break; 
  695.                 case kw_goto: 
  696.                                                 goodcode |= GF_GOTO;
  697.                         snp = gotostmt(); 
  698.                         break; 
  699.                 case kw_continue: 
  700.                                                 goodcode |= GF_CONTINUE;
  701.                         snp = contstmt(); 
  702.                         break; 
  703.                 case kw_do: 
  704.                         snp = dostmt(); 
  705.                         break; 
  706.                 case kw_switch: 
  707.                         snp = switchstmt(); 
  708.                         break; 
  709.                                 case kw_else:
  710.                                                 generror(ERR_ELSE,0,0);
  711.                                                 getsym();
  712.                                                 break;
  713.                                 case kw__genword:
  714.                                                 snp = _genwordstmt();
  715.                                                 break;
  716.                 case id: 
  717.                         while( isspace(lastch) ) 
  718.                                 getch(); 
  719.                         if( lastch == ':' ) 
  720.                                 return labelstmt(); 
  721.                         /* else fall through to process expression */ 
  722.                 default:
  723.                                                 if (castbegin(lastst)) {
  724.                                                     if (prm_cplusplus) {
  725.                                                         cbautoinithead = cbautoinittail = 0;
  726.                                                         dodecl(sc_auto);
  727.                                                         snp = cbautoinithead;
  728.                                                     }
  729.                                                     else {
  730.                                                       generror(ERR_NODECLARE,0,skm_semi);
  731.                                                       snp = 0;
  732.                                                     }
  733.                                                 }
  734.                                                 else {
  735.                                snp = exprstmt(); 
  736.                                                     if (!goodcode)
  737.                                                         generror(ERR_CODENONE,0,0);
  738.                                                 }
  739.                         break; 
  740.                 } 
  741.         if( snp != 0 ) {
  742.                 snp->next = 0;
  743.                                 if (snp3) {
  744.                                     snp3->next = snp;
  745.                                     snp = snp3;
  746.                                 }
  747.                 } 
  748.         return snp; 
  749. }
  750. SNODE *cppblockedstatement(void)
  751. {
  752.     SNODE *snp;
  753.     TABLE oldoldlsym;
  754.     long oldlcauto;
  755.     if (prm_cplusplus) {
  756.         oldlcauto = lc_auto;
  757.         oldoldlsym = oldlsym;
  758.         oldlsym = lsyms;
  759.     }
  760.     snp = statement();
  761.     if (prm_cplusplus) {
  762.         check_funcused(&oldlsym,&lsyms);
  763.         gather_labels(&oldlsym,&lsyms);
  764.         if (lc_auto > lc_maxauto) {
  765.             lc_maxauto = lc_auto;
  766.         }
  767.         cseg();
  768.         lc_auto = oldlcauto;
  769.         lsyms = oldlsym;
  770.         oldlsym.head = oldoldlsym.head;
  771.     }
  772.     return(snp);
  773. }
  774.