1File: STMT.C Page 1 1 /* 2 Copyright 1982 3 Alcyon Corporation 4 8716 Production Ave. 5 San Diego, Ca. 92121 6 */ 7 8 #include "parser.h" 9 #define labgen(l,sl) sl=l;l=nextlabel++; 10 int swp -1; 11 12 13 /* stmt - process a single statement*/ 14 stmt() /* returns - none*/ 15 { 16 register int token, lab, i; 17 register struct tnode *tp; 18 register char *p; 19 20 while( 1 ) { 21 switch(token=gettok()) { 22 23 case LCURBR: /*handle { ... }*/ 24 while( !next(EOF) ) { 25 if( next(RCURBR) ) 26 return; 27 stmt(); 28 } 29 case EOF: 30 error("{ not matched by }"); 31 case SEMI: /*null statement*/ 32 return; 33 34 case RCURBR: 35 pbtok(token); 36 return; 37 38 case SYMBOL: /*symbol: statement*/ 39 if( peekc(':') ) { 40 dolabel(); 41 continue; 42 } 43 default: /*anything else...*/ 44 pbtok(token); 45 outexpr(expr()); 46 break; 47 48 case RESWORD: 49 switch(cvalue) { 50 51 case R_BREAK: 52 lab = brklabel(); 53 outgoto(lab); /*branch to break label*/ 54 break; 55 56 case R_CASE: 57 docase(); 58 continue; 59 1File: STMT.C Page 2 60 case R_CONTINUE: 61 lab = contlabel(); /*branch to continue label*/ 62 outgoto(lab); 63 break; 64 65 case R_DEFAULT: 66 dodefault(); 67 continue; 68 69 case R_DO: 70 dodo(); 71 break; 72 73 case R_FOR: 74 dofor(); 75 return; 76 77 case R_GOTO: 78 lab = gotolabel(); 79 outgoto(lab); 80 break; 81 82 case R_IF: 83 doif(); 84 return; 85 86 case R_RETURN: 87 doreturn(); 88 break; 89 90 case R_SWITCH: 91 doswitch(); 92 return; 93 94 case R_WHILE: 95 dowhile(); 96 return; 97 98 default: 99 synerr("invalid keyword"); 100 return; 101 } 102 } 103 if( !next(SEMI) ) 104 synerr("missing semicolon"); 105 return; 106 } 107 } 108 109 /* balpar - handle expression within parenthesis for while and if*/ 110 /* Merely checks for left and right parens and builds expression.*/ 111 char *balpar() /* returns pointer to expression*/ 112 { 113 register struct tnode *tp; 114 115 if( next(LPAREN) ) { 116 reducep = 1; 117 tp = expr(); 118 reducep = 0; 1File: STMT.C Page 3 119 if( next(RPAREN) ) 120 return(tp); 121 } 122 synerr("parenthesized expression syntax"); 123 return(0); 124 } 125 126 /* synerr - syntax error*/ 127 /* Outputs error message and tries to resyncronize input.*/ 128 synerr(s,x1,x2,x3,x4,x5,x6) /* returns - none*/ 129 char *s; /* printf format string*/ 130 int x1, x2, x3, x4, x5, x6; /* printf arguments*/ 131 { 132 register int token; 133 134 error(s,x1,x2,x3,x4,x5,x6); 135 while( (token=gettok()) != SEMI && token != EOF && token != LCURBR && 136 token != RCURBR ) 137 ; 138 pbtok(token); 139 } 140 141 /* gotolabel - gets label id for goto*/ 142 /* This is used for both: goto symbol and if(...)goto symbol*/ 143 gotolabel() /* returns 0 if not, else label id*/ 144 { 145 register struct symbol *sp; 146 147 if( !next(SYMBOL) ) 148 synerr("expected label"); 149 else { 150 sp = csp; 151 if( !(sp->s_sc) ) { 152 sp->s_type = LLABEL; 153 if( !sp->s_offset ) 154 sp->s_offset = nextlabel++; 155 } 156 if( (!sp->s_sc || sp->s_sc == STATIC ) && sp->s_type == LLABEL ) 157 return(sp->s_offset); 158 synerr("invalid label"); 159 } 160 return(0); 161 } 162 163 /* dolabel - do statement label*/ 164 /* Checks current symbol for already being defined, then sets*/ 165 /* symbol attributes for label.*/ 166 dolabel() /* returns - none*/ 167 { 168 register struct symbol *sp; 169 170 sp = csp; 171 if( sp->s_sc ) 172 error("label redeclaration: %.8s",sp->s_symbol); 173 else { 174 sp->s_attrib =| SDEFINED; 175 sp->s_sc = STATIC; 176 sp->s_type = LLABEL; 177 if( !sp->s_offset ) 1File: STMT.C Page 4 178 sp->s_offset = nextlabel++; 179 outlab(sp->s_offset); 180 } 181 } 182 183 /* brklabel - generate break label*/ 184 /* Checks if break label is undefined, and if so, generates message*/ 185 brklabel() /* returns label number*/ 186 { 187 if( !blabel ) 188 error("invalid break statement"); 189 return(blabel); 190 } 191 192 /* contlabel - generate continue label*/ 193 /* Checks if continue label is undefined, and if so, generates message*/ 194 contlabel() /* returns label number*/ 195 { 196 if( !clabel ) 197 error("invalid continue statement"); 198 return(clabel); 199 } 200 201 /* docase - handles: case constant : statement*/ 202 /* Checks for being in a switch statement, adds entry to switch table*/ 203 docase() /* returns - none*/ 204 { 205 register int value, lab; 206 207 colonstop++; 208 value = cexpr(); /*get case value*/ 209 colonstop--; 210 if( !next(COLON) ) /*check for colon*/ 211 synerr("missing colon"); 212 if( swp < 0 ) 213 error("case not inside a switch block"); 214 else if( swp >= (SWSIZE-1) ) 215 error("too many cases in switch"); 216 else { 217 addswitch(&swtab[cswp],swp-cswp,value,lab=nextlabel++); 218 outlab(lab); 219 swp++; 220 } 221 } 222 223 /* dodefault - handles: default : statement*/ 224 /* Checks for colon and being in a switch statement*/ 225 dodefault() /* returns - none*/ 226 { 227 if( !next(COLON) ) 228 error("missing colon"); 229 if( swp < 0 ) 230 error("default not inside a switch block"); 231 else { 232 dlabel = nextlabel++; /*allocate default label*/ 233 outlab(dlabel); /*output default label*/ 234 } 235 } 236 1File: STMT.C Page 5 237 /* dodo - handles: do statement while ( expression )*/ 238 dodo() /* returns - none*/ 239 { 240 register int lab, saveblab, saveclab; 241 242 labgen(blabel,saveblab); 243 labgen(clabel,saveclab); 244 lab = nextlabel++; 245 outlab(lab); /*branch back to here*/ 246 stmt(); /*do statement*/ 247 outlab(clabel); /*continue label*/ 248 if( !nextrw(R_WHILE) ) { 249 error("missing while"); /*only advisory...*/ 250 outgoto(lab); 251 } 252 else 253 outifgoto(balpar(),TRUE,lab); /*while expression*/ 254 outlab(blabel); /*break label*/ 255 blabel = saveblab; /*restore labels*/ 256 clabel = saveclab; 257 } 258 259 /* 260 * dofor - handle: for ( expression ; expression ; expression ) statement 261 * Hard part is handling re-initialization expression, which is 262 * parsed and saved, then the statement is parsed, then the reinit 263 * clause expression tree is output. 264 */ 265 dofor() /* returns - none*/ 266 { 267 register int lab, saveblab, saveclab, reinit, clineno; 268 register char *savep; 269 register struct tnode *tp; 270 271 labgen(blabel,saveblab); 272 labgen(clabel,saveclab); 273 if( !next(LPAREN) ) { 274 forerr: 275 synerr("invalid for statement"); 276 return; 277 } 278 if( !next(SEMI) ) { /*do init expression*/ 279 outexpr(expr()); 280 if( !next(SEMI) ) 281 goto forerr; 282 } 283 outlab(clabel); /*branch back to here*/ 284 if( !next(SEMI) ) { /*do for condition*/ 285 outifgoto(expr(),FALSE,blabel); 286 if( !next(SEMI) ) 287 goto forerr; 288 } 289 if( next(RPAREN) ) { /*no re-init - easy case*/ 290 stmt(); /*output statement*/ 291 outgoto(clabel); /*output continue label*/ 292 } 293 else { /*there is a re-init clause*/ 294 labgen(clabel,lab); 295 savep = exprp; 1File: STMT.C Page 6 296 tp = expr(); /*save re-init tree until done*/ 297 exprp = opap; /*remember until reinit is output*/ 298 reinit = lineno; 299 if( !next(RPAREN) ) 300 goto forerr; 301 stmt(); /*do statment*/ 302 clineno = lineno; 303 lineno = reinit; 304 outlab(clabel); /*we branch to here for reinit*/ 305 outexpr(tp); /*output re-init clause*/ 306 exprp = savep; 307 lineno = clineno; 308 outgoto(lab); /*branch back to top of loop*/ 309 } 310 outlab(blabel); /*break to here*/ 311 blabel = saveblab; 312 clabel = saveclab; /*restore labels*/ 313 } 314 315 /* doif - handles: if ( expression ) statement [ else statement ]*/ 316 /* Handles special cases for goto, break, continue and return.*/ 317 doif() /* returns - none*/ 318 { 319 register struct tnode *tp; 320 register int elselab, exitlab; 321 322 tp = balpar(); /*if( expr )...*/ 323 exitlab = 0; 324 if( nextrw(R_GOTO) ) 325 exitlab = gotolabel(); 326 else if( nextrw(R_BREAK) ) 327 exitlab = brklabel(); 328 else if( nextrw(R_CONTINUE) ) 329 exitlab = contlabel(); 330 else if( nextrw(R_RETURN) ) { 331 if( peekc(';') ) { 332 exitlab = rlabel; 333 putback(';'); 334 } 335 else 336 pbtok(RESWORD); 337 } 338 if( exitlab ) { /*easy goto, do branch if true*/ 339 outifgoto(tp,TRUE,exitlab); 340 if( !next(SEMI) ) 341 synerr("missing semicolon"); 342 if( nextrw(R_ELSE) ) /*else clause, just output it*/ 343 stmt(); 344 } 345 else { /*hard goto, branch over statement*/ 346 elselab = nextlabel++; 347 outifgoto(tp,FALSE,elselab); 348 stmt(); 349 if( nextrw(R_ELSE) ) { 350 exitlab = nextlabel++; /*branches over else clause*/ 351 outgoto(exitlab); /*branch out of then clause*/ 352 outlab(elselab); /*label to start else clause*/ 353 stmt(); /*else statement*/ 354 outlab(exitlab); 1File: STMT.C Page 7 355 } 356 else 357 outlab(elselab); /*no else, just branch out*/ 358 } 359 } 360 361 /* 362 * doreturn - handles: return [ expression ] ; 363 * Expression is the hard part, must create an assignment expression 364 * to assign expression to the type of the function, then get it 365 * loaded into a specific register. 366 */ 367 doreturn() /* returns - none*/ 368 { 369 register struct tnode *tp; 370 371 if( !peekc(';') ) /*need to compute return?*/ 372 outforreg(FRETURN,frp,expr()); 373 else 374 putback(';'); 375 outgoto(rlabel); /*branch to the return label*/ 376 } 377 378 /* 379 * doswitch - handles: switch ( expression ) statement 380 * Evaluates the expression, forces the result into a known register 381 * collects the case statements in swtab, then outputs the switch 382 * operator and switch cases. 383 */ 384 doswitch() /* returns - none*/ 385 { 386 register int saveblab, swlab, savedlab, saveswp, i; 387 register struct tnode *tp; 388 389 labgen(blabel,saveblab); 390 tp = balpar(); 391 integral(tp,-1); /*must be integral type result*/ 392 outforreg(ASSIGN,snalloc(INT,AUTO,0,0,0),tp); 393 saveswp = swp; /*remember old switch pointer*/ 394 if( saveswp < 0 ) 395 swp++; 396 i = cswp; 397 cswp = swp; /*remember real first entry*/ 398 swlab = nextlabel++; 399 outgoto(swlab); /*branch to switch code*/ 400 savedlab = dlabel; 401 dlabel = 0; 402 stmt(); /*do switch statement*/ 403 outgoto(blabel); /*output branch just in case*/ 404 outlab(swlab); /*here we now do the switch code*/ 405 if( !dlabel ) 406 dlabel = blabel; 407 outswitch(swp-cswp,dlabel,&swtab[cswp]); 408 outlab(blabel); /*break to here*/ 409 cswp = i; 410 swp = saveswp; 411 blabel = saveblab; 412 dlabel = savedlab; 413 } 1File: STMT.C Page 8 414 415 /* dowhile - handles: while ( expression ) statement*/ 416 /* This is fairly straight-forward.*/ 417 dowhile() /* returns - none*/ 418 { 419 register int saveclab, saveblab; 420 421 labgen(blabel,saveblab); 422 labgen(clabel,saveclab); 423 outlab(clabel); /*continue label*/ 424 outifgoto(balpar(),FALSE,blabel); /*condition clause*/ 425 stmt(); /*statement*/ 426 outgoto(clabel); /*branch back to top of loop*/ 427 outlab(blabel); /*break to here*/ 428 blabel = saveblab; 429 clabel = saveclab; /*restore labels*/ 430 } 431 432 /* nextrw - is next token the specified reserved word?*/ 433 nextrw(rw) /* returns 1 if match, 0 otherwise*/ 434 int rw; /* reserved word to match*/ 435 { 436 register int token; 437 438 if( (token=gettok()) != RESWORD || cvalue != rw ) { 439 pbtok(token); 440 return(0); 441 } 442 return(1); 443 } 444 445 /* 446 * addswitch - add an entry into current switch table, bubble sorting 447 * This makes it easier on the code generator and also checks for 448 * duplicate labels at the "right" time. 449 */ 450 addswitch(sp,ncases,nval,nlab) /* returns - none*/ 451 struct swtch *sp; /* switch table pointer*/ 452 int ncases; /* number of cases in switch*/ 453 int nval; /* new value*/ 454 int nlab; /* new label*/ 455 { 456 register struct swtch *nswp, *s; 457 register int temp, i; 458 459 nswp = &sp[ncases]; 460 nswp->sw_value = nval; 461 nswp->sw_label = nlab; 462 s = nswp--; 463 for( ; --ncases >= 0; s--, nswp-- ) { 464 if( s->sw_value == nswp->sw_value ) 465 error("duplicate case value"); 466 if( s->sw_value < nswp->sw_value ) { 467 temp = s->sw_value; 468 s->sw_value = nswp->sw_value; 469 nswp->sw_value = temp; 470 temp = s->sw_label; 471 s->sw_label = nswp->sw_label; 472 nswp->sw_label = temp; 1File: STMT.C Page 9 473 } 474 } 475 } 476 477 /* outforreg - generate assignment for switch and return*/ 478 outforreg(op,ltp,rtp) /*returns - none*/ 479 int op; /*operator for build tree*/ 480 struct tnode *ltp; /*left expression tree*/ 481 struct tnode *rtp; /*right expression tree*/ 482 { 483 register struct tnode *tp; 484 485 opp = opstack; 486 opdp = opdstack; 487 pushopd(ltp); 488 pushopd(rtp); 489 maketree(op); 490 if( tp = popopd() ) 491 outcforreg(tp->t_right); 492 opp = opdp = 0; 493 } 494 495 /* outassign - generate assignment for function args*/ 496 outassign(ltp,rtp) /*returns - none*/ 497 struct tnode *ltp; /*left expression tree*/ 498 struct tnode *rtp; /*right expression tree*/ 499 { 500 opp = opstack; 501 opdp = opdstack; 502 pushopd(ltp); 503 pushopd(rtp); 504 maketree(ASSIGN); 505 outexpr(popopd()); 506 opp = opdp = 0; 507 }