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