|
|
1.1 root 1: /* Copyright (c) 1979 Regents of the University of California */
2: #
3: /*
4: * pi - Pascal interpreter code translator
5: *
6: * Charles Haley, Bill Joy UCB
7: * Version 1.2 November 1978
8: */
9:
10: #include "whoami"
11: #include "0.h"
12: #include "tree.h"
13: #include "opcode.h"
14:
15: int cntpatch;
16: int nfppatch;
17:
18: /*
19: * Funchdr inserts
20: * declaration of a the
21: * prog/proc/func into the
22: * namelist. It also handles
23: * the arguments and puts out
24: * a transfer which defines
25: * the entry point of a procedure.
26: */
27:
28: struct nl *
29: funchdr(r)
30: int *r;
31: {
32: register struct nl *p;
33: register *il, **rl;
34: int *rll;
35: struct nl *cp, *dp, *sp;
36: int o, *pp;
37:
38: if (inpflist(r[2])) {
39: opush('l');
40: yyretrieve(); /* kludge */
41: }
42: pfcnt++;
43: line = r[1];
44: if (r[3] == NIL && (p=lookup1(r[2])) != NIL && bn == cbn) {
45: /*
46: * Symbol already defined
47: * in this block. it is either
48: * a redeclared symbol (error)
49: * or a forward declaration.
50: */
51: if ((p->class == FUNC || p->class == PROC) && (p->nl_flags & NFORWD) != 0) {
52: /*
53: * Grammar doesnt forbid
54: * types on a resolution
55: * of a forward function
56: * declaration.
57: */
58: if (p->class == FUNC && r[4])
59: error("Function type should be given only in forward declaration");
60: if (monflg)
61: putcnt();
62: # ifdef PTREE
63: /*
64: * mark this proc/func as forward
65: * in the pTree.
66: */
67: pDEF( p -> inTree ).PorFForward = TRUE;
68: # endif
69: return (p);
70: }
71: }
72: /*
73: * Declare the prog/proc/func
74: */
75: switch (r[0]) {
76: case T_PROG:
77: if (opt('z'))
78: monflg++;
79: program = p = defnl(r[2], PROG, 0, 0);
80: p->value[3] = r[1];
81: break;
82: case T_PDEC:
83: if (r[4] != NIL)
84: error("Procedures do not have types, only functions do");
85: p = enter(defnl(r[2], PROC, 0, 0));
86: p->nl_flags |= NMOD;
87: break;
88: case T_FDEC:
89: il = r[4];
90: if (il == NIL)
91: error("Function type must be specified");
92: else if (il[0] != T_TYID) {
93: il = NIL;
94: error("Function type can be specified only by using a type identifier");
95: } else
96: il = gtype(il);
97: p = enter(defnl(r[2], FUNC, il, NIL));
98: p->nl_flags |= NMOD;
99: /*
100: * An arbitrary restriction
101: */
102: switch (o = classify(p->type)) {
103: case TFILE:
104: case TARY:
105: case TREC:
106: case TSET:
107: case TSTR:
108: warning();
109: if (opt('s'))
110: standard();
111: error("Functions should not return %ss", clnames[o]);
112: }
113: break;
114: default:
115: panic("funchdr");
116: }
117: if (r[0] != T_PROG) {
118: /*
119: * Mark this proc/func as
120: * being forward declared
121: */
122: p->nl_flags |= NFORWD;
123: /*
124: * Enter the parameters
125: * in the next block for
126: * the time being
127: */
128: if (++cbn >= DSPLYSZ) {
129: error("Procedure/function nesting too deep");
130: pexit(ERRS);
131: }
132: /*
133: * For functions, the function variable
134: */
135: if (p->class == FUNC) {
136: cp = defnl(r[2], FVAR, p->type, 0);
137: cp->chain = p;
138: p->ptr[NL_FVAR] = cp;
139: }
140: /*
141: * Enter the parameters
142: * and compute total size
143: */
144: cp = sp = p;
145: o = 0;
146: for (rl = r[3]; rl != NIL; rl = rl[2]) {
147: p = NIL;
148: if (rl[1] == NIL)
149: continue;
150: /*
151: * Parametric procedures
152: * don't have types !?!
153: */
154: if (rl[1][0] != T_PPROC) {
155: rll = rl[1][2];
156: if (rll[0] != T_TYID) {
157: error("Types for arguments can be specified only by using type identifiers");
158: p = NIL;
159: } else
160: p = gtype(rll);
161: }
162: for (il = rl[1][1]; il != NIL; il = il[2]) {
163: switch (rl[1][0]) {
164: default:
165: panic("funchdr2");
166: case T_PVAL:
167: if (p != NIL) {
168: if (p->class == FILET)
169: error("Files cannot be passed by value");
170: else if (p->nl_flags & NFILES)
171: error("Files cannot be a component of %ss passed by value",
172: nameof(p));
173: }
174: dp = defnl(il[1], VAR, p, o -= even(width(p)));
175: dp->nl_flags |= NMOD;
176: break;
177: case T_PVAR:
178: dp = defnl(il[1], REF, p, o -= sizeof ( int * ) );
179: break;
180: case T_PFUNC:
181: case T_PPROC:
182: error("Procedure/function parameters not implemented");
183: continue;
184: }
185: if (dp != NIL) {
186: cp->chain = dp;
187: cp = dp;
188: }
189: }
190: }
191: cbn--;
192: p = sp;
193: p->value[NL_OFFS] = -o+DPOFF2;
194: /*
195: * Correct the naievity
196: * of our above code to
197: * calculate offsets
198: */
199: for (il = p->chain; il != NIL; il = il->chain)
200: il->value[NL_OFFS] += p->value[NL_OFFS];
201: } else {
202: /*
203: * The wonderful
204: * program statement!
205: */
206: if (monflg) {
207: cntpatch = put2(O_PXPBUF, 0);
208: nfppatch = put3(NIL, 0, 0);
209: }
210: cp = p;
211: for (rl = r[3]; rl; rl = rl[2]) {
212: if (rl[1] == NIL)
213: continue;
214: dp = defnl(rl[1], VAR, 0, 0);
215: cp->chain = dp;
216: cp = dp;
217: }
218: }
219: /*
220: * Define a branch at
221: * the "entry point" of
222: * the prog/proc/func.
223: */
224: p->entloc = getlab();
225: if (monflg) {
226: put2(O_TRACNT, p->entloc);
227: putcnt();
228: } else
229: put2(O_TRA4, p->entloc);
230: # ifdef PTREE
231: {
232: pPointer PF = tCopy( r );
233:
234: pSeize( PorFHeader[ nesting ] );
235: if ( r[0] != T_PROG ) {
236: pPointer *PFs;
237:
238: PFs = &( pDEF( PorFHeader[ nesting ] ).PorFPFs );
239: *PFs = ListAppend( *PFs , PF );
240: } else {
241: pDEF( PorFHeader[ nesting ] ).GlobProg = PF;
242: }
243: pRelease( PorFHeader[ nesting ] );
244: }
245: # endif
246: return (p);
247: }
248:
249: funcfwd(fp)
250: struct nl *fp;
251: {
252:
253: return (fp);
254: }
255:
256: /*
257: * Funcbody is called
258: * when the actual (resolved)
259: * declaration of a procedure is
260: * encountered. It puts the names
261: * of the (function) and parameters
262: * into the symbol table.
263: */
264: funcbody(fp)
265: struct nl *fp;
266: {
267: register struct nl *q, *p;
268:
269: cbn++;
270: if (cbn >= DSPLYSZ) {
271: error("Too many levels of function/procedure nesting");
272: pexit(ERRS);
273: }
274: sizes[cbn].om_max = sizes[cbn].om_off = -DPOFF1;
275: gotos[cbn] = NIL;
276: errcnt[cbn] = syneflg;
277: parts = NIL;
278: if (fp == NIL)
279: return (NIL);
280: /*
281: * Save the virtual name
282: * list stack pointer so
283: * the space can be freed
284: * later (funcend).
285: */
286: fp->ptr[2] = nlp;
287: if (fp->class != PROG)
288: for (q = fp->chain; q != NIL; q = q->chain)
289: enter(q);
290: if (fp->class == FUNC) {
291: /*
292: * For functions, enter the fvar
293: */
294: enter(fp->ptr[NL_FVAR]);
295: }
296: # ifdef PTREE
297: /*
298: * pick up the pointer to porf declaration
299: */
300: PorFHeader[ ++nesting ] = fp -> inTree;
301: # endif
302: return (fp);
303: }
304:
305: struct nl *Fp;
306: int pnumcnt;
307: /*
308: * Funcend is called to
309: * finish a block by generating
310: * the code for the statements.
311: * It then looks for unresolved declarations
312: * of labels, procedures and functions,
313: * and cleans up the name list.
314: * For the program, it checks the
315: * semantics of the program
316: * statement (yuchh).
317: */
318: funcend(fp, bundle, endline)
319: struct nl *fp;
320: int *bundle;
321: int endline;
322: {
323: register struct nl *p;
324: register int i, b;
325: int var, inp, out, chkref, *blk;
326: struct nl *iop;
327: char *cp;
328: extern int cntstat;
329: # ifdef PPC
330: int toplabel = newlabel();
331: int botlabel = newlabel();
332: # endif
333:
334: cntstat = 0;
335: /*
336: * yyoutline();
337: */
338: if (program != NIL)
339: line = program->value[3];
340: blk = bundle[2];
341: if (fp == NIL) {
342: cbn--;
343: # ifdef PTREE
344: nesting--;
345: # endif
346: return;
347: }
348: #ifdef OBJ
349: /*
350: * Patch the branch to the
351: * entry point of the function
352: */
353: patch4(fp->entloc);
354: /*
355: * Put out the block entrance code and the block name.
356: * the CONG is overlaid by a patch later!
357: */
358: var = put1(cbn == 1 && opt('p') == 0 ? O_NODUMP: O_BEG);
359: put( 2 + (sizeof ( char * )/sizeof ( short )) , O_CONG, 8, fp->symbol);
360: put2(NIL, bundle[1]);
361: #endif
362: #ifdef PPC
363: /*
364: * put out the procedure entry code
365: */
366: if ( fp -> class == PROG ) {
367: puttext( " .data" );
368: puttext( " .align 1" );
369: putprintf( " .comm _display,%d"
370: , DSPLYSZ * sizeof( int * ) );
371: puttext( " .text" );
372: puttext( " .align 1" );
373: puttext( " .globl _main" );
374: puttext( "_main:" );
375: }
376: ftnno = newlabel();
377: puttext( " .text" );
378: puttext( " .align 1" );
379: putprintf( " .globl _%.7s" , fp -> symbol );
380: putprintf( "_%.7s:" , fp -> symbol );
381: /* register save mask for function */
382: putprintf( " .word 0" );
383: putprintf( " jbr B%d" , botlabel );
384: putprintf( "T%d:" , toplabel );
385: /* save old display */
386: putprintf( " movl _display+%o,(fp)" , cbn * sizeof( int * ) );
387: /* set up new display */
388: putprintf( " movl fp,_display+%o" , cbn * sizeof( int * ) );
389: /* 'allocate' local storage */
390: putlbracket();
391: #endif
392: if (fp->class == PROG) {
393: /*
394: * The glorious buffers option.
395: * 0 = don't buffer output
396: * 1 = line buffer output
397: * 2 = 512 byte buffer output
398: */
399: # ifdef OBJ
400: if (opt('b') != 1)
401: put1(O_BUFF | opt('b') << 8);
402: # endif
403: inp = 0;
404: out = 0;
405: for (p = fp->chain; p != NIL; p = p->chain) {
406: if (strcmp(p->symbol, "input") == 0) {
407: inp++;
408: continue;
409: }
410: if (strcmp(p->symbol, "output") == 0) {
411: out++;
412: continue;
413: }
414: iop = lookup1(p->symbol);
415: if (iop == NIL || bn != cbn) {
416: error("File %s listed in program statement but not declared", p->symbol);
417: continue;
418: }
419: if (iop->class != VAR) {
420: error("File %s listed in program statement but declared as a %s", p->symbol, classes[iop->class]);
421: continue;
422: }
423: if (iop->type == NIL)
424: continue;
425: if (iop->type->class != FILET) {
426: error("File %s listed in program statement but defined as %s",
427: p->symbol, nameof(iop->type));
428: continue;
429: }
430: # ifdef OBJ
431: put2(O_LV | bn << 9, iop->value[NL_OFFS]);
432: b = p->symbol;
433: while (b->pchar != '\0')
434: b++;
435: i = b - ( (int) p->symbol );
436: put( 2 + (sizeof ( char * )/sizeof ( short ))
437: , O_CONG, i, p->symbol);
438: put2(O_DEFNAME | i << 8
439: , text(iop->type) ? 0: width(iop->type->type));
440: # endif
441: }
442: if (out == 0 && fp->chain != NIL) {
443: recovered();
444: error("The file output must appear in the program statement file list");
445: }
446: }
447: /*
448: * Process the prog/proc/func body
449: */
450: noreach = 0;
451: line = bundle[1];
452: statlist(blk);
453: # ifdef PTREE
454: {
455: pPointer Body = tCopy( blk );
456:
457: pDEF( PorFHeader[ nesting -- ] ).PorFBody = Body;
458: }
459: # endif
460: # ifdef OBJ
461: if (cbn== 1 && monflg != 0) {
462: patchfil(cntpatch, cnts, 1);
463: patchfil(nfppatch, pfcnt, 1);
464: }
465: # endif
466: if (fp->class == PROG && inp == 0 && (input->nl_flags & (NUSED|NMOD)) != 0) {
467: recovered();
468: error("Input is used but not defined in the program statement");
469: }
470: /*
471: * Clean up the symbol table displays and check for unresolves
472: */
473: line = endline;
474: b = cbn;
475: Fp = fp;
476: chkref = syneflg == errcnt[cbn] && opt('w') == 0;
477: for (i = 0; i <= 077; i++) {
478: for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) {
479: /*
480: * Check for variables defined
481: * but not referenced
482: */
483: if (chkref && p->symbol != NIL)
484: switch (p->class) {
485: case FIELD:
486: /*
487: * If the corresponding record is
488: * unused, we shouldn't complain about
489: * the fields.
490: */
491: default:
492: if ((p->nl_flags & (NUSED|NMOD)) == 0) {
493: warning();
494: nerror("%s %s is neither used nor set", classes[p->class], p->symbol);
495: break;
496: }
497: /*
498: * If a var parameter is either
499: * modified or used that is enough.
500: */
501: if (p->class == REF)
502: continue;
503: if ((p->nl_flags & NUSED) == 0) {
504: warning();
505: nerror("%s %s is never used", classes[p->class], p->symbol);
506: break;
507: }
508: if ((p->nl_flags & NMOD) == 0) {
509: warning();
510: nerror("%s %s is used but never set", classes[p->class], p->symbol);
511: break;
512: }
513: case LABEL:
514: case FVAR:
515: case BADUSE:
516: break;
517: }
518: switch (p->class) {
519: case BADUSE:
520: cp = "s";
521: if (p->chain->ud_next == NIL)
522: cp++;
523: eholdnl();
524: if (p->value[NL_KINDS] & ISUNDEF)
525: nerror("%s undefined on line%s", p->symbol, cp);
526: else
527: nerror("%s improperly used on line%s", p->symbol, cp);
528: pnumcnt = 10;
529: pnums(p->chain);
530: pchr('\n');
531: break;
532:
533: case FUNC:
534: case PROC:
535: if (p->nl_flags & NFORWD)
536: nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol);
537: break;
538:
539: case LABEL:
540: if (p->nl_flags & NFORWD)
541: nerror("label %s was declared but not defined", p->symbol);
542: break;
543: case FVAR:
544: if ((p->nl_flags & NMOD) == 0)
545: nerror("No assignment to the function variable");
546: break;
547: }
548: }
549: /*
550: * Pop this symbol
551: * table slot
552: */
553: disptab[i] = p;
554: }
555:
556: # ifdef OBJ
557: put1(O_END);
558: # endif
559: # ifdef PPC
560: putprintf( " movl (fp),_display+%o"
561: , cbn * sizeof( int * ) );
562: puttext( " ret" );
563: putprintf( "B%d:" , botlabel );
564: putprintf( " subl2 $.F%d,sp" , ftnno );
565: putrbracket();
566: putprintf( " jbr T%d" , toplabel );
567: if ( fp -> class == PROG )
568: puteof();
569: # endif
570: #ifdef DEBUG
571: dumpnl(fp->ptr[2], fp->symbol);
572: #endif
573: /*
574: * Restore the
575: * (virtual) name list
576: * position
577: */
578: nlfree(fp->ptr[2]);
579: /*
580: * Proc/func has been
581: * resolved
582: */
583: fp->nl_flags &= ~NFORWD;
584: /*
585: * Patch the beg
586: * of the proc/func to
587: * the proper variable size
588: */
589: i = sizes[cbn].om_max;
590: # ifdef PDP11
591: # define TOOMUCH -50000.
592: # endif
593: # ifdef VAX
594: # define TOOMUCH -32767.
595: # endif
596: if (sizes[cbn].om_max < TOOMUCH)
597: nerror("Storage requirement of %ld bytes exceeds hardware capacity", -sizes[cbn].om_max);
598: if (Fp == NIL)
599: elineon();
600: # ifdef OBJ
601: patchfil(var, i, 1);
602: # endif
603: cbn--;
604: if (inpflist(fp->symbol)) {
605: opop('l');
606: }
607: }
608:
609: pnums(p)
610: struct udinfo *p;
611: {
612:
613: if (p->ud_next != NIL)
614: pnums(p->ud_next);
615: if (pnumcnt == 0) {
616: printf("\n\t");
617: pnumcnt = 20;
618: }
619: pnumcnt--;
620: printf(" %d", p->ud_line);
621: }
622:
623: nerror(a1, a2, a3)
624: {
625:
626: if (Fp != NIL) {
627: yySsync();
628: #ifndef PI1
629: if (opt('l'))
630: yyoutline();
631: #endif
632: yysetfile(filename);
633: printf("In %s %s:\n", classes[Fp->class], Fp->symbol);
634: Fp = NIL;
635: elineoff();
636: }
637: error(a1, a2, a3);
638: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.