|
|
1.1 root 1: #include <stdio.h>
2: #include <assert.h>
3: #include "bc.h"
4:
5:
6: /*
7: * Gerror is used by the various grammar actions when a
8: * semantic error is discoverd. It simply prints out a
9: * message and sets allok to FALSE.
10: * It is also called by yyerror to report syntax errors.
11: * It is also called by lexerror to report lexical errors.
12: * Allok, errors, and any partially defined function or statement
13: * will be cleared at the end of the line, except for the
14: * too much code error which clears at the end of the function
15: * or statement which has grown too large.
16: */
17:
18: gerror(str)
19: char *str;
20: {
21: if (allok == TRUE) {
22: if (infnam != NULL)
23: fprintf(stderr, "%s: ", infnam);
24: if (inline != 0)
25: fprintf(stderr, "%d: ", inline);
26: fprintf(stderr, "%r\n", &str);
27: allok = FALSE;
28: }
29: }
30:
31: /*
32: * Chktype verifies that the type of `var' will work in sload, aeload,
33: * or arload. Otherwise it emits an error and returns zero so the
34: * grammar action can abort the parse.
35: */
36: chktype(var, type)
37: register dicent *var;
38: register int type;
39: {
40: if (var->localt == type)
41: return 1;
42: else if (var->localt == UNDEFINED)
43: if (var->globalt == type || var->globalt == UNDEFINED)
44: return 1;
45: else
46: gerror("'%s' is wrong global type", var->word);
47: else
48: gerror("'%s' is wrong local type", var->word);
49: return 0;
50: }
51:
52: /*
53: * Sload emits the code to load the scalar with dictionary entry
54: * var.
55: */
56:
57: sload(var)
58: register dicent *var;
59: {
60: switch (var->localt) {
61: case SCALAR:
62: emitop(PLOSC);
63: emitcnt(var->localv);
64: break;
65: case UNDEFINED:
66: switch (var->globalt) {
67: case UNDEFINED:
68: var->globalt = SCALAR;
69: newscalar(&var->globalv.rvalue);
70: /* fall thru */
71: case SCALAR:
72: emitop(PGLSC);
73: emitnum(&var->globalv.rvalue);
74: break;
75: }
76: }
77: }
78:
79:
80: /*
81: * Aeload emits the code to load the array element with dictionary
82: * entry var.
83: */
84:
85: aeload(var)
86: register dicent *var;
87: {
88: switch (var->localt) {
89: case ARRAY:
90: emitop(PLOAE);
91: emitcnt(var->localv);
92: break;
93: case UNDEFINED:
94: switch (var->globalt) {
95: case UNDEFINED:
96: var->globalt = ARRAY;
97: newarray(&var->globalv.arvalue);
98: /* fall thru */
99: case ARRAY:
100: emitop(PGLAE);
101: emitarry(&var->globalv.arvalue);
102: break;
103: }
104: }
105: }
106:
107:
108: /*
109: * Arload emits the code to load the whole array with dictionary
110: * entry var.
111: */
112:
113: arload(var)
114: register dicent *var;
115: {
116: switch (var->localt) {
117: case ARRAY:
118: emitop(PLOAR);
119: emitcnt(var->localv);
120: break;
121: case UNDEFINED:
122: switch (var->globalt) {
123: case UNDEFINED:
124: var->globalt = ARRAY;
125: newarray(&var->globalv.arvalue);
126: /* fall thru */
127: case ARRAY:
128: emitop(PGLAR);
129: emitarry(&var->globalv.arvalue);
130: break;
131: }
132: }
133: }
134:
135:
136: /*
137: * If there is room for another code item, incloc advances loc
138: * and returns the old loc. If not then incloc calls gerror.
139: * Note that both the value returned by incloc and loc itself
140: * always point to a location in cstream.
141: */
142:
143: code *
144: incloc()
145: {
146: register code *res;
147:
148: res = loc++;
149: if (res >= &cstream[MAXCODE - 1]) {
150: loc = res;
151: gerror("Too much code");
152: }
153: return (res);
154: }
155:
156:
157: /*
158: * Negate returns the opcode which branches on the opposite
159: * condition of when `op' branches.
160: */
161:
162: opcode
163: negate(op)
164: opcode op;
165: {
166: switch (op) {
167: case BRALW:
168: return (BRNEV);
169: case BRNEV:
170: return (BRALW);
171: case BRLT:
172: return (BRGE);
173: case BRLE:
174: return (BRGT);
175: case BREQ:
176: return (BRNE);
177: case BRGE:
178: return (BRLT);
179: case BRGT:
180: return (BRLE);
181: case BRNE:
182: return (BREQ);
183: }
184: assert(FALSE);
185: }
186:
187:
188: /*
189: * Locaddr sets the local addresses (ie frame pointer offsets) for
190: * all local variables and parameters. `vec' is an array of `len'
191: * pointers to dictionary entries and `base' is the frame offset
192: * of the first entry.
193: * Note that locaddr assumes that it is never called with len zero.
194: */
195:
196: locaddr(vec, len, base)
197: register dicent *vec[];
198: register int len,
199: base;
200: {
201: do {
202: (*vec++)->localv = base++;
203: } while (--len > 0);
204: }
205:
206:
207: /*
208: * Chkfunc checks to make sure that the identifier with dictionary
209: * entry pointed to by `dicp' can be used as a function. If it
210: * is not already a function, then the body and types fields of the
211: * func value are set to NULL.
212: */
213:
214: chkfunc(dicp)
215: register dicent *dicp;
216: {
217: if (dicp->globalt == FUNCTION)
218: return 1;
219: if (dicp->globalt == UNDEFINED) {
220: dicp->globalt = FUNCTION;
221: dicp->globalv.fvalue.fcsize = 0;
222: dicp->globalv.fvalue.body = dicp->globalv.fvalue.types = NULL;
223: return 1;
224: }
225: gerror("'%s' is not a function", dicp->word);
226: return 0;
227: }
228:
229: /*
230: * Install installs the definition of the function `fnc'.
231: * `pvec' and `lpvec' (`avec' and `lavec') are the vector
232: * of formal parameters (respectively automatic variables)
233: * and its length.
234: */
235:
236: install(fnc, pvec, lpvec, avec, lavec)
237: register func *fnc;
238: dicent **pvec,
239: **avec;
240: int lpvec,
241: lavec;
242: {
243: int csize;
244:
245: litfree(fnc->body, fnc->body+fnc->fcsize);
246: mpfree(fnc->body);
247: mpfree(fnc->types);
248: fnc->nparams = lpvec;
249: fnc->nautos = lavec;
250: if (lpvec + lavec == 0)
251: fnc->types = NULL;
252: else {
253: fnc->types = (type *)mpalc((lpvec + lavec) * sizeof (type));
254: copylty(pvec, fnc->types, lpvec);
255: copylty(avec, &fnc->types[lpvec], lavec);
256: }
257: fnc->fcsize = loc - cstream;
258: csize = fnc->fcsize * sizeof (code);
259: fnc->body = (code *)mpalc(csize);
260: copy((char *)cstream, (char *)fnc->body, csize);
261: remloc(pvec, lpvec);
262: remloc(avec, lavec);
263: }
264:
265: /*
266: * Copylty copyies the local types from the dictionary vector
267: * `dvec' to the type vector `tvec'. `len' is the number of
268: * entries to copy.
269: */
270:
271: copylty(dvec, tvec, len)
272: register dicent *dvec[];
273: register type tvec[];
274: register int len;
275: {
276: while (--len >= 0)
277: *tvec++ = (*dvec++)->localt;
278: }
279:
280:
281: /*
282: * Copy copyies the block of bytes at `from' to that at `to'.
283: * `len' is the number of bytes to copy. Note that these
284: * blocks should not overlap.
285: */
286:
287: copy(from, to, len)
288: register char *from,
289: *to;
290: register int len;
291: {
292: while (--len >= 0)
293: *to++ = *from++;
294: }
295:
296: /*
297: * Remloc is used to remove the local types from the dictionary
298: * vector `dvec'. `len' is the length of the vector.
299: */
300:
301: remloc(dvec, len)
302: register dicent **dvec;
303: register int len;
304: {
305: while (--len >= 0)
306: (*dvec++)->localt = UNDEFINED;
307: }
308:
309: /*
310: * Litfree recovers literal and string storage from bp to ep.
311: * Called after interp() on cstream to loc,
312: * after function definition abort on cstream to loc,
313: * during function redefinition on the old body.
314: */
315: litfree(pc, end) register code *pc, *end;
316: {
317: register int op;
318: while (pc < end) {
319: op = pc++->opcode;
320: if (pc >= end)
321: break;
322: switch (op) {
323: case BRNEV: /* Why by two? */
324: printf("BRNEV in litfree\n");
325: case CALL:
326: ++pc;
327: case PGLSC:
328: case PLOSC:
329: case PGLAE:
330: case PLOAE:
331: case PGLAR:
332: case PLOAR:
333: case RETURN:
334: case BRALW:
335: case BRLT:
336: case BRLE:
337: case BREQ:
338: case BRGE:
339: case BRGT:
340: case BRNE:
341: ++pc;
342: case LOAD:
343: case LIBASE:
344: case LOBASE:
345: case LSCALE:
346: case STORE:
347: case SIBASE:
348: case SOBASE:
349: case SSCALE:
350: case POP:
351: case PRVAL:
352: case STOP:
353: case INC:
354: case DEC:
355: case PRNUM:
356: case PRNL:
357: case LENGTH:
358: case SCALE:
359: case SQRT:
360: case ADD:
361: case SUB:
362: case MUL:
363: case DIV:
364: case REM:
365: case EXP:
366: case NEG:
367: case EXIT:
368: break;
369: case PLISC:
370: mvfree(&pc->lvalue->mantissa);
371: mpfree(pc++->lvalue);
372: break;
373: case PRSTR:
374: mpfree(pc++->svalue);
375: break;
376: default:
377: fprintf(stderr, "Mixup in litfree\n");
378: exit(1);
379: }
380: }
381: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.