Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
718 | jacekm | 1 | /* |
2 | ** Small-C Compiler -- Part 1 -- Top End. |
||
3 | ** Copyright 1982, 1983, 1985, 1988 J. E. Hendrix |
||
4 | ** Copyright 1998 H T Walheim |
||
5 | ** All rights reserved. |
||
6 | */ |
||
7 | |||
8 | #include |
||
9 | #include "notice.h" |
||
10 | #include "cc.h" |
||
11 | |||
12 | /* |
||
13 | ** miscellaneous storage |
||
14 | */ |
||
15 | int |
||
16 | nogo, /* disable goto statements? */ |
||
17 | noloc, /* disable block locals? */ |
||
18 | opindex, /* index to matched operator */ |
||
19 | opsize, /* size of operator in characters */ |
||
20 | swactive, /* inside a switch? */ |
||
21 | swdefault,/* default label #, else 0 */ |
||
22 | *swnext, /* address of next entry */ |
||
23 | *swend, /* address of last entry */ |
||
24 | *stage, /* staging buffer address */ |
||
25 | *wq, /* while queue */ |
||
26 | argcs, /* static argc */ |
||
27 | *argvs, /* static argv */ |
||
28 | *wqptr, /* ptr to next entry */ |
||
29 | litptr, /* ptr to next entry */ |
||
30 | macptr, /* macro buffer index */ |
||
31 | pptr, /* ptr to parsing buffer */ |
||
32 | ch, /* current character of input line */ |
||
33 | nch, /* next character of input line */ |
||
34 | declared, /* # of local bytes to declare, -1 when declared */ |
||
35 | iflevel, /* #if... nest level */ |
||
36 | skiplevel,/* level at which #if... skipping started */ |
||
37 | nxtlab, /* next avail label # */ |
||
38 | litlab, /* label # assigned to literal pool */ |
||
39 | csp, /* compiler relative stk ptr */ |
||
40 | argstk, /* function arg sp */ |
||
41 | argtop, /* highest formal argument offset */ |
||
42 | ncmp, /* # open compound statements */ |
||
43 | errflag, /* true after 1st error in statement */ |
||
44 | eof, /* true on final input eof */ |
||
45 | output, /* fd for output file */ |
||
46 | files, /* true if file list specified on cmd line */ |
||
47 | filearg = 0, /* cur file arg index */ |
||
48 | input = EOF, /* fd for input file */ |
||
49 | input2 = EOF, /* fd for "#include" file */ |
||
50 | usexpr = YES, /* true if value of expression is used */ |
||
51 | ccode = YES, /* true while parsing C code */ |
||
52 | *snext, /* next addr in stage */ |
||
53 | *stail, /* last addr of data in stage */ |
||
54 | *slast, /* last addr in stage */ |
||
55 | listfp, /* file pointer to list device */ |
||
56 | lastst, /* last parsed statement type */ |
||
57 | oldseg; /* current segment (0, DATASEG, CODESEG) */ |
||
58 | |||
59 | char |
||
60 | optimize, /* optimize output of staging buffer? */ |
||
61 | alarm, /* audible alarm on errors? */ |
||
62 | monitor, /* monitor function headers? */ |
||
63 | pause, /* pause for operator on errors? */ |
||
64 | *symtab, /* symbol table */ |
||
65 | *litq, /* literal pool */ |
||
66 | *macn, /* macro name buffer */ |
||
67 | *macq, /* macro string buffer */ |
||
68 | *pline, /* parsing buffer */ |
||
69 | *mline, /* macro buffer */ |
||
70 | *line, /* ptr to pline or mline */ |
||
71 | *lptr, /* ptr to current character in "line" */ |
||
72 | *glbptr, /* global symbol table */ |
||
73 | *locptr, /* next local symbol table entry */ |
||
74 | quote[2] = {'"'}, /* literal string for '"' */ |
||
75 | *cptr, /* work ptrs to any char buffer */ |
||
76 | *cptr2, |
||
77 | *cptr3, |
||
78 | msname[NAMESIZE], /* macro symbol name */ |
||
79 | ssname[NAMESIZE]; /* static symbol name */ |
||
80 | |||
81 | int op[16] = { /* p-codes of signed binary operators */ |
||
82 | OR12, /* level5 */ |
||
83 | XOR12, /* level6 */ |
||
84 | AND12, /* level7 */ |
||
85 | EQ12, NE12, /* level8 */ |
||
86 | LE12, GE12, LT12, GT12, /* level9 */ |
||
87 | ASR12, ASL12, /* level10 */ |
||
88 | ADD12, SUB12, /* level11 */ |
||
89 | MUL12, DIV12, MOD12 /* level12 */ |
||
90 | }; |
||
91 | |||
92 | int op2[16] = { /* p-codes of unsigned binary operators */ |
||
93 | OR12, /* level5 */ |
||
94 | XOR12, /* level6 */ |
||
95 | AND12, /* level7 */ |
||
96 | EQ12, NE12, /* level8 */ |
||
97 | LE12u, GE12u, LT12u, GT12u, /* level9 */ |
||
98 | ASR12, ASL12, /* level10 */ |
||
99 | ADD12, SUB12, /* level11 */ |
||
100 | MUL12u, DIV12u, MOD12u /* level12 */ |
||
101 | }; |
||
102 | |||
103 | /* |
||
104 | ** execution begins here |
||
105 | */ |
||
106 | main(argc, argv) int argc, *argv; { |
||
107 | fputs(VERSION, stdout); |
||
108 | fputs(CRIGHT1, stdout); |
||
109 | fputs(CRIGHT2, stdout); |
||
110 | argcs = argc; |
||
111 | argvs = argv; |
||
112 | swnext = calloc(SWTABSZ, 1); |
||
113 | swend = swnext+(SWTABSZ-SWSIZ); |
||
114 | stage = calloc(STAGESIZE, 2*INTSIZE); |
||
115 | wqptr = |
||
116 | wq = calloc(WQTABSZ, INTSIZE); |
||
117 | litq = calloc(LITABSZ, 1); |
||
118 | macn = calloc(MACNSIZE, 1); |
||
119 | macq = calloc(MACQSIZE, 1); |
||
120 | pline = calloc(LINESIZE, 1); |
||
121 | mline = calloc(LINESIZE, 1); |
||
122 | slast = stage+(STAGESIZE*2*INTSIZE); |
||
123 | symtab = calloc((NUMLOCS*SYMAVG + NUMGLBS*SYMMAX), 1); |
||
124 | locptr = STARTLOC; |
||
125 | glbptr = STARTGLB; |
||
126 | |||
127 | ask(); /* get user options */ |
||
128 | openfile(); /* and initial input file */ |
||
129 | preprocess(); /* fetch first line */ |
||
130 | header(); /* intro code */ |
||
131 | setcodes(); /* initialize code pointer array */ |
||
132 | parse(); /* process ALL input */ |
||
133 | trailer(); /* follow-up code */ |
||
134 | fclose(output); /* explicitly close output */ |
||
135 | } |
||
136 | |||
137 | /******************** high level parsing *******************/ |
||
138 | |||
139 | /* |
||
140 | ** process all input text |
||
141 | ** |
||
142 | ** At this level, only static declarations, |
||
143 | ** defines, includes and function |
||
144 | ** definitions are legal... |
||
145 | */ |
||
146 | parse() { |
||
147 | while (eof == 0) { |
||
148 | if (amatch("extern", 6)) dodeclare(EXTERNAL); |
||
149 | else if(dodeclare(STATIC)) ; |
||
150 | else if( match("#asm")) doasm(); |
||
151 | else if( match("#include")) doinclude(); |
||
152 | else if( match("#define")) dodefine(); |
||
153 | else dofunction(); |
||
154 | blanks(); /* force eof if pending */ |
||
155 | } |
||
156 | } |
||
157 | |||
158 | /* |
||
159 | ** test for global declarations |
||
160 | */ |
||
161 | dodeclare(class) int class; { |
||
162 | if (amatch("char", 4)) declglb(CHR, class); |
||
163 | else if(amatch("unsigned", 8)) { |
||
164 | if (amatch("char", 4)) declglb(UCHR, class); |
||
165 | else {amatch("int", 3); declglb(UINT, class);} |
||
166 | } |
||
167 | else if(amatch("int", 3) |
||
168 | || class == EXTERNAL) declglb(INT, class); |
||
169 | else return 0; |
||
170 | ns(); |
||
171 | return 1; |
||
172 | } |
||
173 | |||
174 | /* |
||
175 | ** declare a static variable |
||
176 | */ |
||
177 | declglb(type, class) |
||
178 | int type, class; |
||
179 | { |
||
180 | int id, dim; |
||
181 | |||
182 | while(1) |
||
183 | { |
||
184 | if(endst()) |
||
185 | return; /* do line */ |
||
186 | if(match("*")) |
||
187 | { |
||
188 | id = POINTER; dim = 0; |
||
189 | } |
||
190 | else |
||
191 | { |
||
192 | id = VARIABLE; dim = 1; |
||
193 | } |
||
194 | if(symname(ssname) == 0) |
||
195 | illname(); |
||
196 | if(findglb(ssname)) |
||
197 | multidef(ssname); |
||
198 | if(id == VARIABLE) |
||
199 | { |
||
200 | if (match("(")) |
||
201 | { |
||
202 | id = FUNCTION; need(")"); |
||
203 | } |
||
204 | else if(match("[")) |
||
205 | { |
||
206 | id = ARRAY; dim = needsub(); |
||
207 | } |
||
208 | } |
||
209 | if (class == EXTERNAL) |
||
210 | external(ssname, type >> 2, id); |
||
211 | else if (id != FUNCTION) |
||
212 | initials(type >> 2, id, dim); |
||
213 | if(id == POINTER) |
||
214 | addsym(ssname, id, type, PTRSIZE, 0, &glbptr, class); |
||
215 | else |
||
216 | addsym(ssname, id, type, dim * (type >> 2), 0, &glbptr, class); |
||
217 | if(match(",") == 0) |
||
218 | return; |
||
219 | } |
||
220 | } |
||
221 | |||
222 | /* |
||
223 | ** initialize global objects |
||
224 | */ |
||
225 | initials(size, ident, dim) int size, ident, dim; { |
||
226 | int savedim; |
||
227 | litptr = 0; |
||
228 | if(dim == 0) dim = -1; /* *... or ...[] */ |
||
229 | savedim = dim; |
||
230 | /* public(ident); */ |
||
231 | if(match("=")) { |
||
232 | if(match("{")) { |
||
233 | while(dim) { |
||
234 | init(size, ident, &dim); |
||
235 | if(match(",") == 0) break; |
||
236 | } |
||
237 | need("}"); |
||
238 | } |
||
239 | else init(size, ident, &dim); |
||
240 | } |
||
241 | if(savedim == -1 && dim == -1) { |
||
242 | if(ident == ARRAY) error("need array size"); |
||
243 | stowlit(0, size = PTRSIZE); |
||
244 | } |
||
245 | |||
246 | /* FASM */ |
||
247 | public(ident); |
||
248 | if(litptr>0) dumplits(size); |
||
249 | else if(dim>0) |
||
250 | {/*In FASM: " |
||
251 | fputc(':',output); |
||
252 | } |
||
253 | dumpzero(size, dim); /* only if dim > 0 */ |
||
254 | /* FASM */ |
||
255 | } |
||
256 | |||
257 | /* |
||
258 | ** evaluate one initializer |
||
259 | */ |
||
260 | init(size, ident, dim) int size, ident, *dim; { |
||
261 | int value; |
||
262 | if(string(&value)) { |
||
263 | if(ident == VARIABLE || size != 1) |
||
264 | error("must assign to char pointer or char array"); |
||
265 | *dim -= (litptr - value); |
||
266 | if(ident == POINTER) point(); |
||
267 | } |
||
268 | else if(constexpr(&value)) { |
||
269 | if(ident == POINTER) error("cannot assign to pointer"); |
||
270 | stowlit(value, size); |
||
271 | *dim -= 1; |
||
272 | } |
||
273 | } |
||
274 | |||
275 | /* |
||
276 | ** get required array size |
||
277 | */ |
||
278 | needsub() { |
||
279 | int val; |
||
280 | if(match("]")) return 0; /* null size */ |
||
281 | if(constexpr(&val) == 0) val = 1; |
||
282 | if(val < 0) { |
||
283 | error("negative size illegal"); |
||
284 | val = -val; |
||
285 | } |
||
286 | need("]"); /* force single dimension */ |
||
287 | return val; /* and return size */ |
||
288 | } |
||
289 | |||
290 | /* |
||
291 | ** open an include file |
||
292 | */ |
||
293 | doinclude() { |
||
294 | int i; char str[30]; |
||
295 | blanks(); /* skip over to name */ |
||
296 | if(*lptr == '"' || *lptr == '<') ++lptr; |
||
297 | i = 0; |
||
298 | while(lptr[i] |
||
299 | && lptr[i] != '"' |
||
300 | && lptr[i] != '>' |
||
301 | && lptr[i] != '\n') { |
||
302 | str[i] = lptr[i]; |
||
303 | ++i; |
||
304 | } |
||
305 | str[i] = NULL; |
||
306 | if((input2 = fopen(str,"r")) == NULL) { |
||
307 | input2 = EOF; |
||
308 | error("open failure on include file"); |
||
309 | } |
||
310 | kill(); /* make next read come from new file (if open) */ |
||
311 | } |
||
312 | |||
313 | /* |
||
314 | ** define a macro symbol |
||
315 | */ |
||
316 | dodefine() { |
||
317 | int k; |
||
318 | if(symname(msname) == 0) { |
||
319 | illname(); |
||
320 | kill(); |
||
321 | return; |
||
322 | } |
||
323 | /* |
||
324 | puts (msname); |
||
325 | puts (" is #defined\n"); |
||
326 | */ |
||
327 | k = 0; |
||
328 | if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0) == 0) { |
||
329 | if(cptr2 = cptr) |
||
330 | while(*cptr2++ = msname[k++]) ; |
||
331 | else { |
||
332 | error("macro name table full"); |
||
333 | return; |
||
334 | } |
||
335 | } |
||
336 | putint(macptr, cptr+NAMESIZE, 2 /*INTSIZE*/); |
||
337 | while(white()) gch(); |
||
338 | while(putmac(gch())); |
||
339 | if(macptr >= MACMAX) { |
||
340 | error("macro string queue full"); |
||
341 | exit(ERRCODE); |
||
342 | } |
||
343 | } |
||
344 | |||
345 | putmac(c) char c; { |
||
346 | macq[macptr] = c; |
||
347 | if(macptr < MACMAX) ++macptr; |
||
348 | return c; |
||
349 | } |
||
350 | |||
351 | /* |
||
352 | ** begin a function |
||
353 | ** |
||
354 | ** called from "parse" and tries to make a function |
||
355 | ** out of the following text |
||
356 | */ |
||
357 | dofunction() { |
||
358 | char *ptr; |
||
359 | nogo = /* enable goto statements */ |
||
360 | noloc = /* enable block-local declarations */ |
||
361 | lastst = /* no statement yet */ |
||
362 | litptr = 0; /* clear lit pool */ |
||
363 | litlab = getlabel(); /* label next lit pool */ |
||
364 | locptr = STARTLOC; /* clear local variables */ |
||
365 | if(match("void")) blanks(); /* skip "void" & locate header */ |
||
366 | if(monitor) lout(line, stderr); |
||
367 | if(symname(ssname) == 0) { |
||
368 | error("illegal function or declaration"); |
||
369 | errflag = 0; |
||
370 | kill(); /* invalidate line */ |
||
371 | return; |
||
372 | } |
||
373 | if(ptr = findglb(ssname)) { /* already in symbol table? */ |
||
374 | if(ptr[CLASS] == AUTOEXT) |
||
375 | ptr[CLASS] = STATIC; |
||
376 | else multidef(ssname); |
||
377 | } |
||
378 | else addsym(ssname, FUNCTION, INT, 0, 0, &glbptr, STATIC); |
||
379 | public(FUNCTION); |
||
380 | argstk = 0; /* init arg count */ |
||
381 | if(match("(") == 0) error("no open paren"); |
||
382 | while(match(")") == 0) { /* then count args */ |
||
383 | if(symname(ssname)) { |
||
384 | if(findloc(ssname)) multidef(ssname); |
||
385 | else { |
||
386 | addsym(ssname, 0, 0, 0, argstk, &locptr, AUTOMATIC); |
||
387 | argstk += INTSIZE; |
||
388 | } |
||
389 | } |
||
390 | else { |
||
391 | error("illegal argument name"); |
||
392 | skip(); |
||
393 | } |
||
394 | blanks(); |
||
395 | if(streq(lptr,")") == 0 && match(",") == 0) |
||
396 | error("no comma"); |
||
397 | if(endst()) break; |
||
398 | } |
||
399 | csp = 0; /* preset stack ptr */ |
||
400 | argtop = argstk+INTSIZE; /* account for the pushed BP */ |
||
401 | while(argstk) { |
||
402 | if (amatch("char", 4)) {doargs(CHR); ns();} |
||
403 | else if(amatch("int", 3)) {doargs(INT); ns();} |
||
404 | else if(amatch("unsigned", 8)) { |
||
405 | if (amatch("char", 4)) {doargs(UCHR); ns();} |
||
406 | else {amatch("int", 3); doargs(UINT); ns();} |
||
407 | } |
||
408 | else {error("wrong number of arguments"); break;} |
||
409 | } |
||
410 | gen(ENTER, 0); |
||
411 | statement(); |
||
412 | if(lastst != STRETURN && lastst != STGOTO) |
||
413 | gen(RETURN, 0); |
||
414 | if(litptr) { |
||
415 | toseg(DATASEG); |
||
416 | gen(REFm, litlab); |
||
417 | dumplits(1); /* dump literals */ |
||
418 | } |
||
419 | } |
||
420 | |||
421 | /* |
||
422 | ** declare argument types |
||
423 | */ |
||
424 | doargs(type) int type; { |
||
425 | int id, sz; |
||
426 | char c, *ptr; |
||
427 | while(1) { |
||
428 | if(argstk == 0) return; /* no arguments */ |
||
429 | if(decl(type, POINTER, &id, &sz)) { |
||
430 | if(ptr = findloc(ssname)) { |
||
431 | ptr[IDENT] = id; |
||
432 | ptr[TYPE] = type; |
||
433 | putint(sz, ptr+SIZE, INTSIZE); |
||
434 | putint(argtop-getint(ptr+OFFSET, INTSIZE), ptr+OFFSET, INTSIZE); |
||
435 | } |
||
436 | else error("not an argument"); |
||
437 | } |
||
438 | argstk = argstk - INTSIZE; /* cnt down */ |
||
439 | if(endst()) return; |
||
440 | if(match(",") == 0) error("no comma"); |
||
441 | } |
||
442 | } |
||
443 | |||
444 | /* |
||
445 | ** parse next local or argument declaration |
||
446 | */ |
||
447 | decl(type, aid, id, sz) |
||
448 | int type, aid, *id, *sz; |
||
449 | { |
||
450 | int n, p; |
||
451 | int mod; |
||
452 | if(match("(")) p = 1; |
||
453 | else p = 0; |
||
454 | if(match("*")) {*id = POINTER; *sz = PTRSIZE;} |
||
455 | else {*id = VARIABLE; *sz = type >> 2;} |
||
456 | if((n = symname(ssname)) == 0) illname(); |
||
457 | if(p && match(")")) ; |
||
458 | if(match("(")) |
||
459 | { |
||
460 | if(!p || *id != POINTER) |
||
461 | error("try (*...)()"); |
||
462 | need(")"); |
||
463 | } |
||
464 | else if(*id == VARIABLE && match("[")) |
||
465 | { |
||
466 | *id = aid; |
||
467 | if((*sz *= needsub()) == 0) |
||
468 | { |
||
469 | if(aid == ARRAY) error("need array size"); |
||
470 | *sz = PTRSIZE; /* size of pointer argument */ |
||
471 | } |
||
472 | } |
||
473 | mod = *sz % ALIGN; |
||
474 | |||
475 | if (mod) |
||
476 | { |
||
477 | *sz = *sz + (ALIGN-mod); |
||
478 | } |
||
479 | return n; |
||
480 | } |
||
481 | |||
482 | /******************** start 2nd level parsing *******************/ |
||
483 | |||
484 | /* |
||
485 | ** statement parser |
||
486 | */ |
||
487 | statement() { |
||
488 | if(ch == 0 && eof) return; |
||
489 | else if(amatch("char", 4)) {declloc(CHR); ns();} |
||
490 | else if(amatch("int", 3)) {declloc(INT); ns();} |
||
491 | else if(amatch("unsigned", 8)) { |
||
492 | if (amatch("char", 4)) {declloc(UCHR); ns();} |
||
493 | else {amatch("int", 3); declloc(UINT); ns();} |
||
494 | } |
||
495 | else { |
||
496 | if(declared >= 0) { |
||
497 | if(ncmp > 1) nogo = declared; /* disable goto */ |
||
498 | gen(ADDSP, csp - declared); |
||
499 | declared = -1; |
||
500 | } |
||
501 | if(match("{")) compound(); |
||
502 | else if(amatch("if", 2)) {doif(); lastst = STIF;} |
||
503 | else if(amatch("while", 5)) {dowhile(); lastst = STWHILE;} |
||
504 | else if(amatch("do", 2)) {dodo(); lastst = STDO;} |
||
505 | else if(amatch("for", 3)) {dofor(); lastst = STFOR;} |
||
506 | else if(amatch("switch", 6)) {doswitch(); lastst = STSWITCH;} |
||
507 | else if(amatch("case", 4)) {docase(); lastst = STCASE;} |
||
508 | else if(amatch("default", 7)) {dodefault(); lastst = STDEF;} |
||
509 | else if(amatch("goto", 4)) {dogoto(); lastst = STGOTO;} |
||
510 | else if(dolabel()) lastst = STLABEL; |
||
511 | else if(amatch("return", 6)) {doreturn(); ns(); lastst = STRETURN;} |
||
512 | else if(amatch("break", 5)) {dobreak(); ns(); lastst = STBREAK;} |
||
513 | else if(amatch("continue", 8)) {docont(); ns(); lastst = STCONT;} |
||
514 | else if(match(";")) errflag = 0; |
||
515 | else if(match("#asm")) {doasm(); lastst = STASM;} |
||
516 | else {doexpr(NO); ns(); lastst = STEXPR;} |
||
517 | } |
||
518 | return lastst; |
||
519 | } |
||
520 | |||
521 | /* |
||
522 | ** declare local variables |
||
523 | */ |
||
524 | declloc(type) int type; { |
||
525 | int id, sz; |
||
526 | if(swactive) error("not allowed in switch"); |
||
527 | if(noloc) error("not allowed with goto"); |
||
528 | if(declared < 0) error("must declare first in block"); |
||
529 | while(1) { |
||
530 | if(endst()) return; |
||
531 | decl(type, ARRAY, &id, &sz); |
||
532 | declared += sz; |
||
533 | addsym(ssname, id, type, sz, csp - declared, &locptr, AUTOMATIC); |
||
534 | if(match(",") == 0) return; |
||
535 | } |
||
536 | } |
||
537 | |||
538 | compound() { |
||
539 | int savcsp; |
||
540 | char *savloc; |
||
541 | savcsp = csp; |
||
542 | savloc = locptr; |
||
543 | declared = 0; /* may now declare local variables */ |
||
544 | ++ncmp; /* new level open */ |
||
545 | while (match("}") == 0) |
||
546 | if(eof) { |
||
547 | error("no final }"); |
||
548 | break; |
||
549 | } |
||
550 | else statement(); /* do one */ |
||
551 | if(--ncmp /* close current level */ |
||
552 | && lastst != STRETURN |
||
553 | && lastst != STGOTO) |
||
554 | gen(ADDSP, savcsp); /* delete local variable space */ |
||
555 | cptr = savloc; /* retain labels */ |
||
556 | while(cptr < locptr) { |
||
557 | cptr2 = nextsym(cptr); |
||
558 | if(cptr[IDENT] == LABEL) { |
||
559 | while(cptr < cptr2) *savloc++ = *cptr++; |
||
560 | } |
||
561 | else cptr = cptr2; |
||
562 | } |
||
563 | locptr = savloc; /* delete local symbols */ |
||
564 | declared = -1; /* may not declare variables */ |
||
565 | } |
||
566 | |||
567 | doif() { |
||
568 | int flab1, flab2; |
||
569 | test(flab1 = getlabel(), YES); /* get expr, and branch false */ |
||
570 | statement(); /* if true, do a statement */ |
||
571 | if(amatch("else", 4) == 0) { /* if...else ? */ |
||
572 | /* simple "if"...print false label */ |
||
573 | gen(LABm, flab1); |
||
574 | return; /* and exit */ |
||
575 | } |
||
576 | flab2 = getlabel(); |
||
577 | if(lastst != STRETURN && lastst != STGOTO) |
||
578 | gen(JMPm, flab2); |
||
579 | gen(LABm, flab1); /* print false label */ |
||
580 | statement(); /* and do "else" clause */ |
||
581 | gen(LABm, flab2); /* print true label */ |
||
582 | } |
||
583 | |||
584 | dowhile() { |
||
585 | int wq[4]; /* allocate local queue */ |
||
586 | addwhile(wq); /* add entry to queue for "break" */ |
||
587 | gen(LABm, wq[WQLOOP]); /* loop label */ |
||
588 | test(wq[WQEXIT], YES); /* see if true */ |
||
589 | statement(); /* if so, do a statement */ |
||
590 | gen(JMPm, wq[WQLOOP]); /* loop to label */ |
||
591 | gen(LABm, wq[WQEXIT]); /* exit label */ |
||
592 | delwhile(); /* delete queue entry */ |
||
593 | } |
||
594 | |||
595 | dodo() { |
||
596 | int wq[4]; |
||
597 | addwhile(wq); |
||
598 | gen(LABm, wq[WQLOOP]); |
||
599 | statement(); |
||
600 | need("while"); |
||
601 | test(wq[WQEXIT], YES); |
||
602 | gen(JMPm, wq[WQLOOP]); |
||
603 | gen(LABm, wq[WQEXIT]); |
||
604 | delwhile(); |
||
605 | ns(); |
||
606 | } |
||
607 | |||
608 | dofor() { |
||
609 | int wq[4], lab1, lab2; |
||
610 | addwhile(wq); |
||
611 | lab1 = getlabel(); |
||
612 | lab2 = getlabel(); |
||
613 | need("("); |
||
614 | if(match(";") == 0) { |
||
615 | doexpr(NO); /* expr 1 */ |
||
616 | ns(); |
||
617 | } |
||
618 | gen(LABm, lab1); |
||
619 | if(match(";") == 0) { |
||
620 | test(wq[WQEXIT], NO); /* expr 2 */ |
||
621 | ns(); |
||
622 | } |
||
623 | gen(JMPm, lab2); |
||
624 | gen(LABm, wq[WQLOOP]); |
||
625 | if(match(")") == 0) { |
||
626 | doexpr(NO); /* expr 3 */ |
||
627 | need(")"); |
||
628 | } |
||
629 | gen(JMPm, lab1); |
||
630 | gen(LABm, lab2); |
||
631 | statement(); |
||
632 | gen(JMPm, wq[WQLOOP]); |
||
633 | gen(LABm, wq[WQEXIT]); |
||
634 | delwhile(); |
||
635 | } |
||
636 | |||
637 | doswitch() { |
||
638 | int wq[4], endlab, swact, swdef, *swnex, *swptr; |
||
639 | swact = swactive; |
||
640 | swdef = swdefault; |
||
641 | swnex = swptr = swnext; |
||
642 | addwhile(wq); |
||
643 | *(wqptr + WQLOOP - WQSIZ) = 0; |
||
644 | need("("); |
||
645 | doexpr(YES); /* evaluate switch expression */ |
||
646 | need(")"); |
||
647 | swdefault = 0; |
||
648 | swactive = 1; |
||
649 | gen(JMPm, endlab = getlabel()); |
||
650 | statement(); /* cases, etc. */ |
||
651 | gen(JMPm, wq[WQEXIT]); |
||
652 | gen(LABm, endlab); |
||
653 | gen(SWITCH, 0); /* match cases */ |
||
654 | while(swptr < swnext) { |
||
655 | gen(NEARm, *swptr++); |
||
656 | #ifdef INT32 |
||
657 | gen(DWORDn, *swptr++); /* case value */ |
||
658 | #else |
||
659 | gen(WORDn, *swptr++); /* case value */ |
||
660 | #endif |
||
661 | } |
||
662 | #ifdef INT32 |
||
663 | gen(DWORDn, 0); |
||
664 | #else |
||
665 | gen(WORDn, 0); |
||
666 | #endif |
||
667 | if(swdefault) gen(JMPm, swdefault); |
||
668 | gen(LABm, wq[WQEXIT]); |
||
669 | delwhile(); |
||
670 | swnext = swnex; |
||
671 | swdefault = swdef; |
||
672 | swactive = swact; |
||
673 | } |
||
674 | |||
675 | docase() { |
||
676 | if(swactive == 0) error("not in switch"); |
||
677 | if(swnext > swend) { |
||
678 | error("too many cases"); |
||
679 | return; |
||
680 | } |
||
681 | gen(LABm, *swnext++ = getlabel()); |
||
682 | constexpr(swnext++); |
||
683 | need(":"); |
||
684 | } |
||
685 | |||
686 | dodefault() { |
||
687 | if(swactive) { |
||
688 | if(swdefault) error("multiple defaults"); |
||
689 | } |
||
690 | else error("not in switch"); |
||
691 | need(":"); |
||
692 | gen(LABm, swdefault = getlabel()); |
||
693 | } |
||
694 | |||
695 | dogoto() { |
||
696 | if(nogo > 0) error("not allowed with block-locals"); |
||
697 | else noloc = 1; |
||
698 | if(symname(ssname)) gen(JMPm, addlabel(NO)); |
||
699 | else error("bad label"); |
||
700 | ns(); |
||
701 | } |
||
702 | |||
703 | dolabel() { |
||
704 | char *savelptr; |
||
705 | blanks(); |
||
706 | savelptr = lptr; |
||
707 | if(symname(ssname)) { |
||
708 | if(gch() == ':') { |
||
709 | gen(LABm, addlabel(YES)); |
||
710 | return 1; |
||
711 | } |
||
712 | else bump(savelptr-lptr); |
||
713 | } |
||
714 | return 0; |
||
715 | } |
||
716 | |||
717 | addlabel(def) int def; { |
||
718 | if(cptr = findloc(ssname)) { |
||
719 | if(cptr[IDENT] != LABEL) error("not a label"); |
||
720 | else if(def) { |
||
721 | if(cptr[TYPE]) error("duplicate label"); |
||
722 | else cptr[TYPE] = YES; |
||
723 | } |
||
724 | } |
||
725 | else cptr = addsym(ssname, LABEL, def, 0, getlabel(), &locptr, LABEL); |
||
726 | return (getint(cptr+OFFSET, INTSIZE)); |
||
727 | } |
||
728 | |||
729 | doreturn() { |
||
730 | int savcsp; |
||
731 | if(endst() == 0) doexpr(YES); |
||
732 | savcsp = csp; |
||
733 | gen(RETURN, 0); |
||
734 | csp = savcsp; |
||
735 | } |
||
736 | |||
737 | dobreak() { |
||
738 | int *ptr; |
||
739 | if((ptr = readwhile(wqptr)) == 0) return; |
||
740 | gen(ADDSP, ptr[WQSP]); |
||
741 | gen(JMPm, ptr[WQEXIT]); |
||
742 | } |
||
743 | |||
744 | docont() { |
||
745 | int *ptr; |
||
746 | ptr = wqptr; |
||
747 | while (1) { |
||
748 | if((ptr = readwhile(ptr)) == 0) return; |
||
749 | if(ptr[WQLOOP]) break; |
||
750 | } |
||
751 | gen(ADDSP, ptr[WQSP]); |
||
752 | gen(JMPm, ptr[WQLOOP]); |
||
753 | } |
||
754 | |||
755 | doasm() { |
||
756 | ccode = 0; /* mark mode as "asm" */ |
||
757 | while (1) { |
||
758 | inline(); |
||
759 | if(match("#endasm")) break; |
||
760 | if(eof)break; |
||
761 | fputs(line, output); |
||
762 | } |
||
763 | kill(); |
||
764 | ccode = 1; |
||
765 | } |
||
766 | |||
767 | doexpr(use) int use; { |
||
768 | int constant, val; |
||
769 | int *before, *start; |
||
770 | usexpr = use; /* tell isfree() whether expr value is used */ |
||
771 | while(1) { |
||
772 | setstage(&before, &start); |
||
773 | expression(&constant, &val); |
||
774 | clearstage(before, start); |
||
775 | if(ch != ',') break; |
||
776 | bump(1); |
||
777 | } |
||
778 | usexpr = YES; /* return to normal value */ |
||
779 | } |
||
780 | |||
781 | /******************** miscellaneous functions *******************/ |
||
782 | |||
783 | /* |
||
784 | ** get run options |
||
785 | */ |
||
786 | ask() |
||
787 | { |
||
788 | int i; |
||
789 | int j; |
||
790 | i = listfp = nxtlab = 0; |
||
791 | output = stdout; |
||
792 | #ifdef LATER |
||
793 | optimize = YES; // Not working for 32 bit int's yer |
||
794 | #else |
||
795 | optimize = NO; |
||
796 | #endif |
||
797 | alarm = monitor = pause = NO; |
||
798 | line = mline; |
||
799 | while(getarg(++i, line, LINESIZE, argcs, argvs) != EOF) |
||
800 | { |
||
801 | if(line[0] != '-' && line[0] != '/') |
||
802 | continue; |
||
803 | if(toupper(line[1]) == 'L' // List |
||
804 | && isdigit(line[2]) |
||
805 | && line[3] <= ' ') |
||
806 | { |
||
807 | listfp = line[2]-'0'; |
||
808 | continue; |
||
809 | } |
||
810 | if(toupper(line[1]) == 'N' // No optimize |
||
811 | && toupper(line[2]) == 'O' |
||
812 | && line[3] <= ' ') |
||
813 | { |
||
814 | optimize = NO; |
||
815 | continue; |
||
816 | } |
||
817 | if(toupper(line[1]) == 'D') |
||
818 | { |
||
819 | j = 0; |
||
820 | ch = line[j+2]; |
||
821 | lptr = line + j+2; |
||
822 | /* |
||
823 | while (line[j+2] != ' ') |
||
824 | { |
||
825 | if (j < (NAMEMAX-1)) |
||
826 | { |
||
827 | msname[j] = line[j+1]; |
||
828 | ++j; |
||
829 | } |
||
830 | else |
||
831 | { |
||
832 | break; |
||
833 | } |
||
834 | } |
||
835 | msname[j] = '\0'; |
||
836 | */ |
||
837 | dodefine (); |
||
838 | continue; |
||
839 | } |
||
840 | |||
841 | if(line[2] <= ' ') |
||
842 | { |
||
843 | if(toupper(line[1]) == 'A') {alarm = YES; continue;} |
||
844 | if(toupper(line[1]) == 'M') {monitor = YES; continue;} |
||
845 | if(toupper(line[1]) == 'P') {pause = YES; continue;} |
||
846 | } |
||
847 | fputs("usage: cc [file]... [-m] [-a] [-p] [-l#] [-no] [-d |
||
848 | fputs(" -m monitor\n", stderr); |
||
849 | fputs(" -a alarm\n", stderr); |
||
850 | fputs(" -p pause\n", stderr); |
||
851 | fputs(" -l# list\n", stderr); |
||
852 | fputs(" -no no optimize\n", stderr); |
||
853 | fputs(" -d |
||
854 | exit(ERRCODE); |
||
855 | } |
||
856 | } |
||
857 | |||
858 | /* |
||
859 | ** input and output file opens |
||
860 | */ |
||
861 | openfile() { /* entire function revised */ |
||
862 | char outfn[15]; |
||
863 | int i, j, ext; |
||
864 | input = EOF; |
||
865 | while(getarg(++filearg, pline, LINESIZE, argcs, argvs) != EOF) { |
||
866 | if(pline[0] == '-' || pline[0] == '/') continue; |
||
867 | ext = NO; |
||
868 | i = -1; |
||
869 | j = 0; |
||
870 | while(pline[++i]) { |
||
871 | if(pline[i] == '.') { |
||
872 | ext = YES; |
||
873 | break; |
||
874 | } |
||
875 | if(j < 10) outfn[j++] = pline[i]; |
||
876 | } |
||
877 | if(!ext) strcpy(pline + i, ".C"); |
||
878 | input = mustopen(pline, "r"); |
||
879 | #ifdef _MSC_VER |
||
880 | |||
881 | if(!files) { |
||
882 | strcpy(outfn + j, ".ASM"); |
||
883 | output = mustopen(outfn, "w"); |
||
884 | } |
||
885 | |||
886 | #else |
||
887 | if(!files /* && iscons(stdout)*/) { |
||
888 | strcpy(outfn + j, ".ASM"); |
||
889 | output = mustopen(outfn, "w"); |
||
890 | } |
||
891 | #endif |
||
892 | files = YES; |
||
893 | kill(); |
||
894 | return; |
||
895 | } |
||
896 | if(files++) eof = YES; |
||
897 | else input = stdin; |
||
898 | kill(); |
||
899 | } |
||
900 | |||
901 | /* |
||
902 | ** open a file with error checking |
||
903 | */ |
||
904 | mustopen(fn, mode) char *fn, *mode; { |
||
905 | int fd; |
||
906 | if(fd = fopen(fn, mode)) return fd; |
||
907 | fputs("open error on ", stderr); |
||
908 | lout(fn, stderr); |
||
909 | exit(ERRCODE); |
||
910 | }>=>>=>=>>>>>>')>> |
||
911 |