STMT.C
上传用户:hlzzc88
上传日期:2007-01-06
资源大小:220k
文件大小:25k
源码类别:

编译器/解释器

开发平台:

Others

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