mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 08:24:18 +00:00
517 lines
17 KiB
Plaintext
517 lines
17 KiB
Plaintext
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 }
|