Commit | Line | Data |
---|---|---|
3eacddb2 DR |
1 | /* C compiler |
2 | ||
3 | Copyright 1972 Bell Telephone Laboratories, Inc. | |
4 | ||
5 | */ | |
6 | ||
7 | ossiz 250; | |
8 | ospace() {} /* fake */ | |
9 | ||
10 | init(s, t) | |
11 | char s[]; { | |
12 | extern lookup, symbuf, namsiz; | |
13 | char symbuf[], sp[]; | |
14 | int np[], i; | |
15 | ||
16 | i = namsiz; | |
17 | sp = symbuf; | |
18 | while(i--) | |
19 | if ((*sp++ = *s++)=='\0') --s; | |
20 | np = lookup(); | |
21 | *np++ = 1; | |
22 | *np = t; | |
23 | } | |
24 | ||
25 | main(argc, argv) | |
26 | int argv[]; { | |
27 | extern init, flush; | |
28 | extern extdef, eof, open, creat; | |
29 | extern fout, fin, error, exit, nerror, tmpfil; | |
30 | ||
31 | if(argc<4) { | |
32 | error("Arg count"); | |
33 | exit(1); | |
34 | } | |
35 | if((fin=open(argv[1],0))<0) { | |
36 | error("Can't find %s", argv[1]); | |
37 | exit(1); | |
38 | } | |
39 | if((fout=creat(argv[2], 017))<0) { | |
40 | error("Can't create %s", argv[2]); | |
41 | exit(1); | |
42 | } | |
43 | tmpfil = argv[3]; | |
44 | init("int", 0); | |
45 | init("char", 1); | |
46 | init("float", 2); | |
47 | init("double", 3); | |
48 | /* init("long", 4); */ | |
49 | init("auto", 5); | |
50 | init("extern", 6); | |
51 | init("static", 7); | |
52 | init("goto", 10); | |
53 | init("return", 11); | |
54 | init("if", 12); | |
55 | init("while", 13); | |
56 | init("else", 14); | |
57 | init("switch", 15); | |
58 | init("case", 16); | |
59 | init("break", 17); | |
60 | init("continue", 18); | |
61 | init("do", 19); | |
62 | init("default", 20); | |
63 | while(!eof) { | |
64 | extdef(); | |
65 | blkend(); | |
66 | } | |
67 | flush(); | |
68 | flshw(); | |
69 | exit(nerror!=0); | |
70 | } | |
71 | ||
72 | lookup() { | |
73 | extern hshtab[], hshsiz, pssiz, symbuf[]; | |
74 | extern hshlen, hshused, exit, error, nwps; | |
75 | auto i, j, np[], sp[], rp[]; | |
76 | ||
77 | i = 0; | |
78 | sp = symbuf; | |
79 | j = nwps; | |
80 | while(j--) | |
81 | i =+ *sp++; | |
82 | if (i<0) i = -i; | |
83 | i =% hshsiz; | |
84 | i =* pssiz; | |
85 | while(*(np = &hshtab[i+4])) { | |
86 | sp = symbuf; | |
87 | j = nwps; | |
88 | while(j--) | |
89 | if (*np++ != *sp++) goto no; | |
90 | return(&hshtab[i]); | |
91 | no: if ((i =+ pssiz) >= hshlen) i = 0; | |
92 | } | |
93 | if(hshused++ > hshsiz) { | |
94 | error("Symbol table overflow"); | |
95 | exit(1); | |
96 | } | |
97 | rp = np = &hshtab[i]; | |
98 | sp = symbuf; | |
99 | j = 4; | |
100 | while(j--) | |
101 | *np++ = 0; | |
102 | j = nwps; | |
103 | while(j--) | |
104 | *np++ = *sp++; | |
105 | return(rp); | |
106 | } | |
107 | ||
108 | symbol() { | |
109 | extern peeksym, peekc, eof, getchar, subseq, error, line; | |
110 | extern csym[], getstr, symbuf, namsiz, lookup[], ctab, cval; | |
111 | auto b, c; | |
112 | char symbuf[], sp[], ctab[]; | |
113 | ||
114 | if (peeksym>=0) { | |
115 | c = peeksym; | |
116 | peeksym = -1; | |
117 | return(c); | |
118 | } | |
119 | if (peekc) { | |
120 | c = peekc; | |
121 | peekc = 0; | |
122 | } else | |
123 | if (eof) | |
124 | return(0); else | |
125 | c = getchar(); | |
126 | loop: | |
127 | switch(ctab[c]) { | |
128 | ||
129 | case 125: /* newline */ | |
130 | line++; | |
131 | ||
132 | case 126: /* white space */ | |
133 | c = getchar(); | |
134 | goto loop; | |
135 | ||
136 | case 0: /* EOF */ | |
137 | eof++; | |
138 | return(0); | |
139 | ||
140 | case 40: /* + */ | |
141 | return(subseq(c,40,30)); | |
142 | ||
143 | case 41: /* - */ | |
144 | return(subseq(c,41,31)); | |
145 | ||
146 | case 80: /* = */ | |
147 | if (subseq(' ',0,1)) return(80); | |
148 | c = symbol(); | |
149 | if (c>=40 & c<=49) | |
150 | return(c+30); | |
151 | if (c==80) | |
152 | return(60); | |
153 | peeksym = c; | |
154 | return(80); | |
155 | ||
156 | case 63: /* < */ | |
157 | if (subseq(c,0,1)) return(46); | |
158 | return(subseq('=',63,62)); | |
159 | ||
160 | case 65: /* > */ | |
161 | if (subseq(c,0,1)) return(45); | |
162 | return(subseq('=',65,64)); | |
163 | ||
164 | case 34: /* ! */ | |
165 | return(subseq('=',34,61)); | |
166 | ||
167 | case 43: /* / */ | |
168 | if (subseq('*',1,0)) | |
169 | return(43); | |
170 | com: | |
171 | c = getchar(); | |
172 | com1: | |
173 | if (c=='\0') { | |
174 | eof++; | |
175 | error("Nonterminated comment"); | |
176 | return(0); | |
177 | } | |
178 | if (c=='\n') | |
179 | line++; | |
180 | if (c!='*') | |
181 | goto com; | |
182 | c = getchar(); | |
183 | if (c!='/') | |
184 | goto com1; | |
185 | c = getchar(); | |
186 | goto loop; | |
187 | ||
188 | case 124: /* number */ | |
189 | cval = 0; | |
190 | if (c=='0') | |
191 | b = 8; else | |
192 | b = 10; | |
193 | while(ctab[c]==124) { | |
194 | cval = cval*b + c -'0'; | |
195 | c = getchar(); | |
196 | } | |
197 | peekc = c; | |
198 | return(21); | |
199 | ||
200 | case 122: /* " */ | |
201 | return(getstr()); | |
202 | ||
203 | case 121: /* ' */ | |
204 | return(getcc()); | |
205 | ||
206 | case 123: /* letter */ | |
207 | sp = symbuf; | |
208 | while(ctab[c]==123 | ctab[c]==124) { | |
209 | if (sp<symbuf+namsiz) *sp++ = c; | |
210 | c = getchar(); | |
211 | } | |
212 | while(sp<symbuf+namsiz) | |
213 | *sp++ = '\0'; | |
214 | peekc = c; | |
215 | csym = lookup(); | |
216 | if (csym[0]==1) { /* keyword */ | |
217 | cval = csym[1]; | |
218 | return(19); | |
219 | } | |
220 | return(20); | |
221 | ||
222 | case 127: /* unknown */ | |
223 | error("Unknown character"); | |
224 | c = getchar(); | |
225 | goto loop; | |
226 | ||
227 | } | |
228 | return(ctab[c]); | |
229 | } | |
230 | ||
231 | subseq(c,a,b) { | |
232 | extern getchar, peekc; | |
233 | ||
234 | if (!peekc) | |
235 | peekc = getchar(); | |
236 | if (peekc != c) | |
237 | return(a); | |
238 | peekc = 0; | |
239 | return(b); | |
240 | } | |
241 | getstr() { | |
242 | extern isn, cval; | |
243 | auto c; | |
244 | ||
245 | printf(".data;L%d:.byte ", cval=isn++); | |
246 | while((c=mapch('"')) >= 0) | |
247 | printf("%o,", c); | |
248 | printf("0;.even;.text\n"); | |
249 | return(22); | |
250 | } | |
251 | ||
252 | getcc() | |
253 | { | |
254 | extern cval, ncpw; | |
255 | auto c, cc; | |
256 | char cp[]; | |
257 | ||
258 | cval = 0; | |
259 | cp = &cval; | |
260 | cc = 0; | |
261 | while((c=mapch('\'')) >= 0) | |
262 | if(cc++ < ncpw) | |
263 | *cp++ = c; | |
264 | if(cc>ncpw) | |
265 | error("Long character constant"); | |
266 | return(21); | |
267 | } | |
268 | ||
269 | mapch(c) | |
270 | { | |
271 | extern peekc, line; | |
272 | auto a; | |
273 | ||
274 | if((a=getchar())==c) | |
275 | return(-1); | |
276 | switch(a) { | |
277 | ||
278 | case '\n': | |
279 | case 0: | |
280 | error("Nonterminated string"); | |
281 | peekc = a; | |
282 | return(-1); | |
283 | ||
284 | case '\\': | |
285 | switch (a=getchar()) { | |
286 | ||
287 | case 't': | |
288 | return('\t'); | |
289 | ||
290 | case 'n': | |
291 | return('\n'); | |
292 | ||
293 | case '0': | |
294 | return('\0'); | |
295 | ||
296 | case 'r': | |
297 | return('\r'); | |
298 | ||
299 | case '\n': | |
300 | line++; | |
301 | return('\n'); | |
302 | } | |
303 | ||
304 | } | |
305 | return(a); | |
306 | } | |
307 | ||
308 | tree() { | |
309 | extern symbol, block, csym[], ctyp, isn, | |
310 | peeksym, opdope[], build, error, cp[], cmst[], | |
311 | space, ospace, cval, ossiz, exit, errflush, cmsiz; | |
312 | ||
313 | auto op[], opst[20], pp[], prst[20], andflg, o, | |
314 | p, ps, os; | |
315 | ||
316 | space = ospace; | |
317 | op = opst; | |
318 | pp = prst; | |
319 | cp = cmst; | |
320 | *op = 200; /* stack EOF */ | |
321 | *pp = 06; | |
322 | andflg = 0; | |
323 | ||
324 | advanc: | |
325 | switch (o=symbol()) { | |
326 | ||
327 | /* name */ | |
328 | case 20: | |
329 | if (*csym==0) | |
330 | if((peeksym=symbol())==6) | |
331 | *csym = 6; /* extern */ | |
332 | else { | |
333 | if(csym[2]==0) /* unseen so far */ | |
334 | csym[2] = isn++; | |
335 | } | |
336 | if(*csym==6) /* extern */ | |
337 | *cp++ = block(5,20,csym[1],0,*csym, | |
338 | csym[4],csym[5],csym[6],csym[7]); | |
339 | else | |
340 | *cp++ = block(2,20,csym[1],0,*csym,csym[2]); | |
341 | goto tand; | |
342 | ||
343 | /* short constant */ | |
344 | case 21: | |
345 | case21: | |
346 | *cp++ = block(1,21,ctyp,0,cval); | |
347 | goto tand; | |
348 | ||
349 | /* string constant */ | |
350 | case 22: | |
351 | *cp++ = block(1,22,17,0,cval); | |
352 | ||
353 | tand: | |
354 | if(cp>=cmst+cmsiz) { | |
355 | error("Expression overflow"); | |
356 | exit(1); | |
357 | } | |
358 | if (andflg) | |
359 | goto syntax; | |
360 | andflg = 1; | |
361 | goto advanc; | |
362 | ||
363 | /* ++, -- */ | |
364 | case 30: | |
365 | case 31: | |
366 | if (andflg) | |
367 | o =+ 2; | |
368 | goto oponst; | |
369 | ||
370 | /* ! */ | |
371 | case 34: | |
372 | if (andflg) | |
373 | goto syntax; | |
374 | goto oponst; | |
375 | ||
376 | /* - */ | |
377 | case 41: | |
378 | if (!andflg) { | |
379 | peeksym = symbol(); | |
380 | if (peeksym==21) { | |
381 | peeksym = -1; | |
382 | cval = -cval; | |
383 | goto case21; | |
384 | } | |
385 | o = 37; | |
386 | } | |
387 | andflg = 0; | |
388 | goto oponst; | |
389 | ||
390 | /* & */ | |
391 | /* * */ | |
392 | case 47: | |
393 | case 42: | |
394 | if (andflg) | |
395 | andflg = 0; else | |
396 | if(o==47) | |
397 | o = 35; | |
398 | else | |
399 | o = 36; | |
400 | goto oponst; | |
401 | ||
402 | /* ( */ | |
403 | case 6: | |
404 | if (andflg) { | |
405 | o = symbol(); | |
406 | if (o==7) | |
407 | o = 101; else { | |
408 | peeksym = o; | |
409 | o = 100; | |
410 | andflg = 0; | |
411 | } | |
412 | } | |
413 | goto oponst; | |
414 | ||
415 | /* ) */ | |
416 | /* ] */ | |
417 | case 5: | |
418 | case 7: | |
419 | if (!andflg) | |
420 | goto syntax; | |
421 | goto oponst; | |
422 | } | |
423 | ||
424 | /* binaries */ | |
425 | if (!andflg) | |
426 | goto syntax; | |
427 | andflg = 0; | |
428 | ||
429 | oponst: | |
430 | p = (opdope[o]>>9) & 077; | |
431 | opon1: | |
432 | ps = *pp; | |
433 | if (p>ps | p==ps & (opdope[o]&0200)!=0) { /* right-assoc */ | |
434 | putin: | |
435 | switch (o) { | |
436 | ||
437 | case 6: /* ( */ | |
438 | case 4: /* [ */ | |
439 | case 100: /* call */ | |
440 | p = 04; | |
441 | } | |
442 | if(op>=opst+20) { /* opstack size */ | |
443 | error("expression overflow"); | |
444 | exit(1); | |
445 | } | |
446 | *++op = o; | |
447 | *++pp = p; | |
448 | goto advanc; | |
449 | } | |
450 | --pp; | |
451 | switch (os = *op--) { | |
452 | ||
453 | /* EOF */ | |
454 | case 200: | |
455 | peeksym = o; | |
456 | return(*--cp); | |
457 | ||
458 | /* call */ | |
459 | case 100: | |
460 | if (o!=7) | |
461 | goto syntax; | |
462 | build(os); | |
463 | goto advanc; | |
464 | ||
465 | /* mcall */ | |
466 | case 101: | |
467 | *cp++ = 0; /* 0 arg call */ | |
468 | os = 100; | |
469 | goto fbuild; | |
470 | ||
471 | /* ( */ | |
472 | case 6: | |
473 | if (o!=7) | |
474 | goto syntax; | |
475 | goto advanc; | |
476 | ||
477 | /* [ */ | |
478 | case 4: | |
479 | if (o!=5) | |
480 | goto syntax; | |
481 | build(4); | |
482 | goto advanc; | |
483 | } | |
484 | fbuild: | |
485 | build(os); | |
486 | goto opon1; | |
487 | ||
488 | syntax: | |
489 | error("Expression syntax"); | |
490 | errflush(o); | |
491 | return(0); | |
492 | } | |
493 | ||
494 | declare(kw) { | |
495 | extern csym[], symbol, paraml[], parame[]; | |
496 | extern error, cval, errflush, peeksym, exit; | |
497 | int t[], n, o; | |
498 | ||
499 | while((o=symbol())==20) { /* name */ | |
500 | if(kw>=5) { /* type or sort? */ | |
501 | if(*csym>0) | |
502 | error("%p redeclared", csym[4]); | |
503 | *csym = kw; | |
504 | } else { | |
505 | if ((csym[1]&017)!=0) | |
506 | error("%p redeclared", &csym[4]); | |
507 | csym[1] =| csym[1]&0760 | kw; | |
508 | if (*csym==0) | |
509 | *csym = -2; | |
510 | } | |
511 | while((o=symbol())==4) { /* [ */ | |
512 | if((o=symbol())==21) { /* const */ | |
513 | if(csym[1]>=020) | |
514 | error("Bad vector"); | |
515 | csym[3] = cval; | |
516 | o = symbol(); | |
517 | } | |
518 | if (o!=5) /* ] */ | |
519 | goto syntax; | |
520 | csym[1] =+ 020; | |
521 | } | |
522 | if(kw==8) { /* parameter */ | |
523 | *csym = -1; | |
524 | if (paraml==0) | |
525 | paraml = csym; | |
526 | else | |
527 | *parame = csym; | |
528 | parame = csym; | |
529 | } | |
530 | if (o!=9) /* , */ | |
531 | break; | |
532 | } | |
533 | if(o==1 & kw!=8 | o==7 & kw==8) | |
534 | return; | |
535 | syntax: | |
536 | error("Declaration syntax"); | |
537 | errflush(o); | |
538 | } | |
539 | ||
540 | /* storage */ | |
541 | ||
542 | regtab 0; | |
543 | efftab 1; | |
544 | cctab 2; | |
545 | sptab 3; | |
546 | symbuf[4]; | |
547 | pssiz 8; | |
548 | namsiz 8; | |
549 | nwps 4; | |
550 | hshused 0; | |
551 | hshsiz 100; | |
552 | hshlen 800; /* 8*hshsiz */ | |
553 | hshtab[800]; | |
554 | space 0; | |
555 | cp 0; | |
556 | cmsiz 40; | |
557 | cmst[40]; | |
558 | ctyp 0; | |
559 | isn 1; | |
560 | swsiz 120; | |
561 | swtab[120]; | |
562 | swp 0; | |
563 | contlab 0; | |
564 | brklab 0; | |
565 | deflab 0; | |
566 | nreg 4; | |
567 | maprel[] 60,61,64,65,62,63,68,69,66,67; | |
568 | nauto 0; | |
569 | stack 0; | |
570 | peeksym 0177777; | |
571 | peekc 0; | |
572 | eof 0; | |
573 | line 1; | |
574 | csym 0; | |
575 | cval 0; | |
576 | ncpw 2; | |
577 | nerror 0; | |
578 | paraml; | |
579 | parame; | |
580 | tmpfil; | |
581 |