|
|
1.1 root 1: /*
2: * C compiler
3: */
4:
5: #include "c0.h"
6:
7: /*
8: * Reduce the degree-of-reference by one.
9: * e.g. turn "ptr-to-int" into "int".
10: */
11: decref(t)
12: register int t;
13: {
14: if ((t & ~TYPE) == 0) {
15: error("Illegal indirection");
16: return(t);
17: }
18: return((t>>TYLEN) & ~TYPE | t&TYPE);
19: }
20:
21: /*
22: * Increase the degree of reference by
23: * one; e.g. turn "int" to "ptr-to-int".
24: */
25: incref(t)
26: register int t;
27: {
28: return(((t&~TYPE)<<TYLEN) | (t&TYPE) | PTR);
29: }
30:
31: /*
32: * Make a tree that causes a branch to lbl
33: * if the tree's value is non-zero together with the cond.
34: */
35: cbranch(t, lbl, cond)
36: union tree *t;
37: {
38: treeout(t, 0);
39: outcode("BNNN", CBRANCH, lbl, cond, line);
40: }
41:
42: /*
43: * Write out a tree.
44: */
45: rcexpr(tp)
46: register union tree *tp;
47: {
48: /*
49: * Special optimization
50: */
51: if (tp->t.op==INIT && tp->t.tr1->t.op==CON) {
52: if (tp->t.type==CHAR || tp->t.type==UNCHAR) {
53: outcode("B1N0", BDATA, tp->t.tr1->c.value);
54: return;
55: } else if (tp->t.type==INT || tp->t.type==UNSIGN) {
56: outcode("BN", SINIT, tp->t.tr1->c.value);
57: return;
58: }
59: }
60: treeout(tp, 0);
61: outcode("BN", EXPR, line);
62: }
63:
64: treeout(tp, isstruct)
65: register union tree *tp;
66: {
67: register struct nmlist *hp;
68: register nextisstruct;
69:
70: if (tp == NULL || tp->t.op==NULLOP) {
71: outcode("B", XNULLOP);
72: return;
73: }
74: nextisstruct = tp->t.type==STRUCT;
75: switch(tp->t.op) {
76:
77: case NAME:
78: hp = &tp->t.tr1->n;
79: if (hp->hclass==TYPEDEF)
80: error("Illegal use of type name");
81: outcode("BNN", NAME, hp->hclass==0?STATIC:hp->hclass, tp->t.type);
82: if (hp->hclass==EXTERN)
83: outcode("S", hp->name);
84: else
85: outcode("N", hp->hoffset);
86: break;
87:
88: case LCON:
89: outcode("BNNN", tp->l.op, tp->l.type, (unsigned short)(tp->l.lvalue>>16),
90: (unsigned short)tp->l.lvalue);
91: break;
92:
93: case CON:
94: outcode("BNN", tp->c.op, tp->c.type, tp->c.value);
95: break;
96:
97: case FCON:
98: outcode("BNF", tp->f.op, tp->f.type, tp->f.cstr);
99: break;
100:
101: case STRING:
102: outcode("BNNN", NAME, STATIC, tp->t.type, tp->t.tr1);
103: break;
104:
105: case FSEL:
106: treeout(tp->t.tr1, nextisstruct);
107: outcode("BNNN", tp->t.op, tp->t.type,
108: tp->t.tr2->fld.bitoffs, tp->t.tr2->fld.flen);
109: break;
110:
111: case ETYPE:
112: error("Illegal use of type");
113: break;
114:
115: case AMPER:
116: treeout(tp->t.tr1, 1);
117: outcode("BN", tp->t.op, tp->t.type);
118: break;
119:
120:
121: case CALL:
122: treeout(tp->t.tr1, 1);
123: treeout(tp->t.tr2, 0);
124: outcode("BN", CALL, tp->t.type);
125: break;
126:
127: default:
128: treeout(tp->t.tr1, nextisstruct);
129: if (opdope[tp->t.op]&BINARY)
130: treeout(tp->t.tr2, nextisstruct);
131: outcode("BN", tp->t.op, tp->t.type);
132: break;
133: }
134: if (nextisstruct && isstruct==0)
135: outcode("BNN", STRASG, STRUCT, tp->t.strp->S.ssize);
136: }
137:
138: /*
139: * Generate a branch
140: */
141: branch(lab)
142: {
143: outcode("BN", BRANCH, lab);
144: }
145:
146: /*
147: * Generate a label
148: */
149: label(l)
150: {
151: outcode("BN", LABEL, l);
152: }
153:
154: /*
155: * ap is a tree node whose type
156: * is some kind of pointer; return the size of the object
157: * to which the pointer points.
158: */
159: plength(p)
160: register union tree *p;
161: {
162: register t, l;
163:
164: if (p==0 || ((t=p->t.type)&~TYPE) == 0) /* not a reference */
165: return(1);
166: p->t.type = decref(t);
167: l = length(p);
168: p->t.type = t;
169: return(l);
170: }
171:
172: /*
173: * return the number of bytes in the object
174: * whose tree node is acs.
175: */
176: length(cs)
177: union tree *cs;
178: {
179: register t, elsz;
180: long n;
181: int nd;
182:
183: t = cs->t.type;
184: n = 1;
185: nd = 0;
186: while ((t&XTYPE) == ARRAY) {
187: t = decref(t);
188: n *= cs->t.subsp[nd++];
189: }
190: if ((t&~TYPE)==FUNC)
191: return(0);
192: if (t>=PTR)
193: elsz = SZPTR;
194: else switch(t&TYPE) {
195:
196: case VOID:
197: error("Illegal use of void object");
198: return(2);
199:
200: case INT:
201: case UNSIGN:
202: elsz = SZINT;
203: break;
204:
205: case CHAR:
206: case UNCHAR:
207: elsz = 1;
208: break;
209:
210: case FLOAT:
211: elsz = SZFLOAT;
212: break;
213:
214: case LONG:
215: elsz = SZLONG;
216: break;
217:
218: case DOUBLE:
219: elsz = SZDOUB;
220: break;
221:
222: case STRUCT:
223: if ((elsz = cs->t.strp->S.ssize) == 0)
224: error("Undefined structure");
225: break;
226: default:
227: error("Compiler error (length)");
228: return(0);
229: }
230: n *= elsz;
231: if (n >= (unsigned)50000) {
232: error("Warning: very large data structure");
233: nerror--;
234: }
235: return(n);
236: }
237:
238: /*
239: * The number of bytes in an object, rounded up to a word.
240: */
241: rlength(cs)
242: union tree *cs;
243: {
244: return((length(cs)+ALIGN) & ~ALIGN);
245: }
246:
247: /*
248: * After an "if (...) goto", look to see if the transfer
249: * is to a simple label.
250: */
251: simplegoto()
252: {
253: register struct nmlist *csp;
254:
255: if ((peeksym=symbol())==NAME && nextchar()==';') {
256: csp = csym;
257: if (csp->hblklev == 0)
258: csp = pushdecl(csp);
259: if (csp->hclass==0 && csp->htype==0) {
260: csp->htype = ARRAY;
261: csp->hflag |= FLABL;
262: if (csp->hoffset==0)
263: csp->hoffset = isn++;
264: }
265: if ((csp->hclass==0||csp->hclass==STATIC)
266: && csp->htype==ARRAY) {
267: peeksym = -1;
268: return(csp->hoffset);
269: }
270: }
271: return(0);
272: }
273:
274: /*
275: * Return the next non-white-space character
276: */
277: nextchar()
278: {
279: while (spnextchar()==' ')
280: peekc = 0;
281: return(peekc);
282: }
283:
284: /*
285: * Return the next character, translating all white space
286: * to blank and handling line-ends.
287: */
288: spnextchar()
289: {
290: register c;
291:
292: if ((c = peekc)==0)
293: c = getchar();
294: if (c=='\t' || c=='\014') /* FF */
295: c = ' ';
296: else if (c=='\n') {
297: c = ' ';
298: line++;
299: }
300: peekc = c;
301: return(c);
302: }
303:
304: /*
305: * is a break or continue legal?
306: */
307: chconbrk(l)
308: {
309: if (l==0)
310: error("Break/continue error");
311: }
312:
313: /*
314: * The goto statement.
315: */
316: dogoto()
317: {
318: register union tree *np;
319: register char *st;
320:
321: st = starttree();
322: *cp++ = tree(0);
323: build(STAR);
324: chkw(np = *--cp, -1);
325: rcexpr(block(JUMP, 0, (int *)NULL, (union str *)NULL, np, TNULL));
326: endtree(st);
327: }
328:
329: /*
330: * The return statement, which has to convert
331: * the returned object to the function's type.
332: */
333: doret()
334: {
335: register union tree *t;
336:
337: if (nextchar() != ';') {
338: register char *st;
339:
340: st = starttree();
341: *cp++ = (union tree *)&funcblk;
342: *cp++ = tree(0);
343: build(ASSIGN);
344: cp[-1] = cp[-1]->t.tr2;
345: build(RFORCE);
346: rcexpr(*--cp);
347: endtree(st);
348: }
349: branch(retlab);
350: }
351:
352: /*
353: * Write a character on the error output.
354: */
355: /*
356: * Coded output:
357: * B: beginning of line; an operator
358: * N: a number
359: * S: a symbol (external)
360: * 1: number 1
361: * 0: number 0
362: */
363: /* VARARGS1 */
364: outcode(s, a)
365: char *s;
366: {
367: register *ap;
368: register FILE *bufp;
369: int n;
370: register char *np;
371:
372: bufp = stdout;
373: if (strflg)
374: bufp = sbufp;
375: ap = &a;
376: for (;;) switch(*s++) {
377: case 'B':
378: putc(*ap++, bufp);
379: putc(0376, bufp);
380: continue;
381:
382: case 'N':
383: putc(*ap, bufp);
384: putc(*ap++>>8, bufp);
385: continue;
386:
387: case 'F':
388: n = 1000;
389: np = (char *)*ap++;
390: goto str;
391:
392: case 'S':
393: n = NCPS;
394: np = (char *)*ap++;
395: if (*np)
396: putc('_', bufp);
397: str:
398: while (n-- && *np) {
399: putc(*np++&0177, bufp);
400: }
401: putc(0, bufp);
402: continue;
403:
404: case '1':
405: putc(1, bufp);
406: putc(0, bufp);
407: continue;
408:
409: case '0':
410: putc(0, bufp);
411: putc(0, bufp);
412: continue;
413:
414: case '\0':
415: if (ferror(bufp)) {
416: error("Write error on temp");
417: exit(1);
418: }
419: return;
420:
421: default:
422: error("Botch in outcode");
423: }
424: }
425:
426: unsigned
427: hash(sp)
428: register char *sp;
429: {
430: register unsigned h;
431: register c;
432:
433: h = 0;
434: c = 7;
435: do {
436: if (*sp == 0)
437: break;
438: h += h;
439: h += *sp++;
440: } while (--c != 0);
441: return(h%HSHSIZ);
442: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.