xref: /original-bsd/usr.bin/pascal/src/fdec.c (revision 18f6d767)
1 /* Copyright (c) 1979 Regents of the University of California */
2 
3 #ifndef lint
4 static char sccsid[] = "@(#)fdec.c 2.2 03/20/85";
5 #endif
6 
7 #include "whoami.h"
8 #include "0.h"
9 #include "tree.h"
10 #include "opcode.h"
11 #include "objfmt.h"
12 #include "align.h"
13 #include "tmps.h"
14 
15 /*
16  * this array keeps the pxp counters associated with
17  * functions and procedures, so that they can be output
18  * when their bodies are encountered
19  */
20 int	bodycnts[ DSPLYSZ ];
21 
22 #ifdef PC
23 #   include "pc.h"
24 #   include <pcc.h>
25 #endif PC
26 
27 #ifdef OBJ
28 int	cntpatch;
29 int	nfppatch;
30 #endif OBJ
31 
32 funcfwd(fp)
33 	struct nl *fp;
34 {
35 
36 	    /*
37 	     *	save the counter for this function
38 	     */
39 	if ( monflg ) {
40 	    fp -> value[ NL_CNTR ] = bodycnts[ cbn ];
41 	}
42 }
43 
44 /*
45  * Funcext marks the procedure or
46  * function external in the symbol
47  * table. Funcext should only be
48  * called if PC, and is an error
49  * otherwise.
50  */
51 
52 struct nl *
53 funcext(fp)
54 	struct nl *fp;
55 {
56 
57 #ifdef OBJ
58 	error("Procedures or functions cannot be declared external.");
59 #endif OBJ
60 
61 #ifdef PC
62 	    /*
63 	     *	save the counter for this function
64 	     */
65 	if ( monflg ) {
66 	    fp -> value[ NL_CNTR ] = bodycnts[ cbn ];
67 	}
68  	if (opt('s')) {
69 		standard();
70 		error("External procedures and functions are not standard");
71 	} else {
72 		if (cbn == 1) {
73 			fp->extra_flags |= NEXTERN;
74 			stabefunc( fp -> symbol , fp -> class , line );
75 		}
76 		else
77 			error("External procedures and functions can only be declared at the outermost level.");
78 	}
79 #endif PC
80 
81 	return(fp);
82 }
83 
84 /*
85  * Funcbody is called
86  * when the actual (resolved)
87  * declaration of a procedure is
88  * encountered. It puts the names
89  * of the (function) and parameters
90  * into the symbol table.
91  */
92 struct nl *
93 funcbody(fp)
94 	struct nl *fp;
95 {
96 	register struct nl *q;
97 
98 	cbn++;
99 	if (cbn >= DSPLYSZ) {
100 		error("Too many levels of function/procedure nesting");
101 		pexit(ERRS);
102 	}
103 	tmpinit(cbn);
104 	gotos[cbn] = NIL;
105 	errcnt[cbn] = syneflg;
106 	parts[ cbn ] = NIL;
107 	dfiles[ cbn ] = FALSE;
108 	if (fp == NIL)
109 		return (NIL);
110 	/*
111 	 * Save the virtual name
112 	 * list stack pointer so
113 	 * the space can be freed
114 	 * later (funcend).
115 	 */
116 	fp->ptr[2] = nlp;
117 	if (fp->class != PROG) {
118 		for (q = fp->chain; q != NIL; q = q->chain) {
119 			(void) enter(q);
120 #			ifdef PC
121 			    q -> extra_flags |= NPARAM;
122 #			endif PC
123 		}
124 	}
125 	if (fp->class == FUNC) {
126 		/*
127 		 * For functions, enter the fvar
128 		 */
129 		(void) enter(fp->ptr[NL_FVAR]);
130 #		ifdef PC
131 		    q = fp -> ptr[ NL_FVAR ];
132 		    if (q -> type != NIL ) {
133 			sizes[cbn].curtmps.om_off = q -> value[NL_OFFS];
134 			sizes[cbn].om_max = q -> value[NL_OFFS];
135 		    }
136 #		endif PC
137 	}
138 #	ifdef PTREE
139 		/*
140 		 *	pick up the pointer to porf declaration
141 		 */
142 	    PorFHeader[ ++nesting ] = fp -> inTree;
143 #	endif PTREE
144 	return (fp);
145 }
146 
147 /*
148  * Segend is called to check for
149  * unresolved variables, funcs and
150  * procs, and deliver unresolved and
151  * baduse error diagnostics at the
152  * end of a routine segment (a separately
153  * compiled segment that is not the
154  * main program) for PC. This
155  * routine should only be called
156  * by PC (not standard).
157  */
158  segend()
159  {
160 #ifdef PC
161 	register struct nl *p;
162 	register int i,b;
163 	char *cp;
164 
165 	if ( monflg ) {
166 	    error("Only the module containing the \"program\" statement");
167 	    cerror("can be profiled with ``pxp''.\n");
168 	}
169 	if (opt('s')) {
170 		standard();
171 		error("Separately compiled routine segments are not standard.");
172 	} else {
173 		b = cbn;
174 		for (i=0; i<077; i++) {
175 			for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) {
176 			switch (p->class) {
177 				case BADUSE:
178 					cp = "s";
179 					if (((struct udinfo *) (p->chain))->ud_next == NIL)
180 						cp++;
181 					eholdnl();
182 					if (p->value[NL_KINDS] & ISUNDEF)
183 						nerror("%s undefined on line%s", p->symbol, cp);
184 					else
185 						nerror("%s improperly used on line%s", p->symbol, cp);
186 					pnumcnt = 10;
187 					pnums((struct udinfo *) (p->chain));
188 					pchr('\n');
189 					break;
190 
191 				case FUNC:
192 				case PROC:
193 					if ((p->nl_flags & NFORWD) &&
194 					    ((p->extra_flags & NEXTERN) == 0))
195 						nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol);
196 					break;
197 
198 				case FVAR:
199 					if (((p->nl_flags & NMOD) == 0) &&
200 					    ((p->chain->extra_flags & NEXTERN) == 0))
201 						nerror("No assignment to the function variable");
202 					break;
203 			    }
204 			   }
205 			   disptab[i] = p;
206 		    }
207 	}
208 #endif PC
209 #ifdef OBJ
210 	error("Missing program statement and program body");
211 #endif OBJ
212 
213 }
214 
215 
216 /*
217  * Level1 does level one processing for
218  * separately compiled routine segments
219  */
220 level1()
221 {
222 
223 #	ifdef OBJ
224 	    error("Missing program statement");
225 #	endif OBJ
226 #	ifdef PC
227 	    if (opt('s')) {
228 		    standard();
229 		    error("Missing program statement");
230 	    }
231 #	endif PC
232 
233 	cbn++;
234 	tmpinit(cbn);
235 	gotos[cbn] = NIL;
236 	errcnt[cbn] = syneflg;
237 	parts[ cbn ] = NIL;
238 	dfiles[ cbn ] = FALSE;
239 	progseen = TRUE;
240 }
241 
242 
243 
244 pnums(p)
245 	struct udinfo *p;
246 {
247 
248 	if (p->ud_next != NIL)
249 		pnums(p->ud_next);
250 	if (pnumcnt == 0) {
251 		printf("\n\t");
252 		pnumcnt = 20;
253 	}
254 	pnumcnt--;
255 	printf(" %d", p->ud_line);
256 }
257 
258 /*VARARGS*/
259 nerror(a1, a2, a3)
260     char *a1,*a2,*a3;
261 {
262 
263 	if (Fp != NIL) {
264 		yySsync();
265 #ifndef PI1
266 		if (opt('l'))
267 			yyoutline();
268 #endif
269 		yysetfile(filename);
270 		printf("In %s %s:\n", classes[Fp->class], Fp->symbol);
271 		Fp = NIL;
272 		elineoff();
273 	}
274 	error(a1, a2, a3);
275 }
276