xref: /csrg-svn/usr.bin/pascal/src/yyid.c (revision 62223)
148116Sbostic /*-
2*62223Sbostic  * Copyright (c) 1980, 1993
3*62223Sbostic  *	The Regents of the University of California.  All rights reserved.
448116Sbostic  *
548116Sbostic  * %sccs.include.redist.c%
622206Sdist  */
7786Speter 
814748Sthien #ifndef lint
9*62223Sbostic static char sccsid[] = "@(#)yyid.c	8.1 (Berkeley) 06/06/93";
1048116Sbostic #endif /* not lint */
11786Speter 
12786Speter #include "whoami.h"
1344619Sbostic #include <0.h>
1414748Sthien #include "tree_ty.h"	/* must be included for yy.h */
15786Speter #include "yy.h"
16786Speter 
17786Speter #ifdef PI
1814748Sthien extern	union semstack *yypv;
19786Speter /*
20786Speter  * Determine whether the identifier whose name
21786Speter  * is "cp" can possibly be a kind, which is a
22786Speter  * namelist class.  We look through the symbol
23786Speter  * table for the first instance of cp as a non-field,
24786Speter  * and at all instances of cp as a field.
25786Speter  * If any of these are ok, we return true, else false.
26786Speter  * It would be much better to handle with's correctly,
27786Speter  * even to just know whether we are in a with at all.
28786Speter  *
29786Speter  * Note that we don't disallow constants on the lhs of assignment.
30786Speter  */
identis(cp,kind)31786Speter identis(cp, kind)
32786Speter 	register char *cp;
33786Speter 	int kind;
34786Speter {
35786Speter 	register struct nl *p;
36786Speter 	int i;
37786Speter 
38786Speter 	/*
39786Speter 	 * Cp is NIL when error recovery inserts it.
40786Speter 	 */
41786Speter 	if (cp == NIL)
42786Speter 		return (1);
43786Speter 
44786Speter 	/*
45786Speter 	 * Record kind we want for possible later use by yyrecover
46786Speter 	 */
47786Speter 	yyidwant = kind;
48786Speter 	yyidhave = NIL;
49786Speter 	i = ( (int) cp ) & 077;
50786Speter 	for (p = disptab[i]; p != NIL; p = p->nl_next)
51786Speter 		if (p->symbol == cp) {
52786Speter 			if (yyidok(p, kind))
53786Speter 				goto gotit;
54786Speter 			if (p->class != FIELD && p->class != BADUSE)
55786Speter 				break;
56786Speter 		}
57786Speter 	if (p != NIL)
58786Speter 		for (p = p->nl_next; p != NIL; p = p->nl_next)
59786Speter 			if (p->symbol == cp && p->class == FIELD && yyidok(p, kind))
60786Speter 				goto gotit;
61786Speter 	return (0);
62786Speter gotit:
63786Speter 	if (p->class == BADUSE && !Recovery) {
64786Speter 		yybadref(p, OY.Yyeline);
6514748Sthien 		yypv[0].i_entry = NIL;
66786Speter 	}
67786Speter 	return (1);
68786Speter }
69786Speter 
70786Speter /*
71786Speter  * A bad reference to the identifier cp on line
72786Speter  * line and use implying the addition of kindmask
73786Speter  * to the mask of kind information.
74786Speter  */
7514748Sthien struct nl *
yybaduse(cp,line,kindmask)76786Speter yybaduse(cp, line, kindmask)
77786Speter 	register char *cp;
78786Speter 	int line, kindmask;
79786Speter {
80786Speter 	register struct nl *p, *oldp;
81786Speter 	int i;
82786Speter 
83786Speter 	i = ( (int) cp ) & 077;
84786Speter 	for (p = disptab[i]; p != NIL; p = p->nl_next)
85786Speter 		if (p->symbol == cp)
86786Speter 			break;
87786Speter 	oldp = p;
88786Speter 	if (p == NIL || p->class != BADUSE)
8914748Sthien 		p = enter(defnl(cp, BADUSE, NLNIL, 0));
903085Smckusic 	p->value[NL_KINDS] |= kindmask;
91786Speter 	yybadref(p, line);
92786Speter 	return (oldp);
93786Speter }
94786Speter 
95786Speter     /*
96786Speter      *	ud is initialized so that esavestr will allocate
97786Speter      *	sizeof ( struct udinfo ) bytes for the 'real' struct udinfo
98786Speter      */
9914748Sthien struct	udinfo ud = { ~0 , (struct udinfo *) ~0 , 0};
100786Speter /*
101786Speter  * Record a reference to an undefined identifier,
102786Speter  * or one which is improperly used.
103786Speter  */
yybadref(p,line)104786Speter yybadref(p, line)
105786Speter 	register struct nl *p;
106786Speter 	int line;
107786Speter {
108786Speter 	register struct udinfo *udp;
109786Speter 
11014748Sthien 	if (p->chain != NIL && ((struct udinfo *) p->chain)->ud_line == line)
111786Speter 		return;
11214748Sthien 	udp = (struct udinfo *) esavestr((char *) &ud);
113786Speter 	udp->ud_line = line;
11414748Sthien 	udp->ud_next = (struct udinfo *) p->chain;
11514748Sthien 	p->chain = (struct nl *) udp;
116786Speter }
117786Speter 
1181201Speter #define	varkinds	((1<<CONST)|(1<<VAR)|(1<<REF)|(1<<ARRAY)|(1<<PTR) \
1191201Speter 			|(1<<RECORD)|(1<<FIELD)|(1<<FUNC)|(1<<FVAR) \
1201201Speter 			|(1<<FFUNC)|(1<<PROC)|(1<<FPROC))
121786Speter /*
122786Speter  * Is the symbol in the p entry of the namelist
123786Speter  * even possibly a kind kind?  If not, update
124786Speter  * what we have based on this encounter.
125786Speter  */
yyidok(p,kind)126786Speter yyidok(p, kind)
127786Speter 	register struct nl *p;
128786Speter 	int kind;
129786Speter {
130786Speter 
131786Speter 	if (p->class == BADUSE) {
132786Speter 		if (kind == VAR)
133786Speter 			return (p->value[0] & varkinds);
134786Speter 		return (p->value[0] & (1 << kind));
135786Speter 	}
136786Speter 	if (yyidok1(p, kind))
137786Speter 		return (1);
138786Speter 	if (yyidhave != NIL)
139786Speter 		yyidhave = IMPROPER;
140786Speter 	else
141786Speter 		yyidhave = p->class;
142786Speter 	return (0);
143786Speter }
144786Speter 
yyidok1(p,kind)145786Speter yyidok1(p, kind)
146786Speter 	register struct nl *p;
147786Speter 	int kind;
148786Speter {
149786Speter 
150786Speter 	switch (kind) {
15114748Sthien 		default:
152786Speter 		case FUNC:
1531201Speter 			return (   p -> class == FUNC
1541201Speter 				|| p -> class == FVAR
1551201Speter 				|| p -> class == FFUNC );
1561201Speter 		case PROC:
1571201Speter 			return ( p -> class == PROC || p -> class == FPROC );
158786Speter 		case CONST:
159786Speter 		case TYPE:
160786Speter 		case FIELD:
161786Speter 			return (p->class == kind);
162786Speter 		case VAR:
163786Speter 			return (p->class == CONST || yyisvar(p, NIL));
164786Speter 		case ARRAY:
165786Speter 		case RECORD:
166786Speter 			return (yyisvar(p, kind));
167786Speter 		case PTRFILE:
168786Speter 			return (yyisvar(p, PTR) || yyisvar(p, FILET));
169786Speter 	}
170786Speter }
171786Speter 
yyisvar(p,varclass)1727922Smckusick yyisvar(p, varclass)
173786Speter 	register struct nl *p;
1747922Smckusick 	int varclass;
175786Speter {
176786Speter 
177786Speter 	switch (p->class) {
178786Speter 		case FIELD:
179786Speter 		case VAR:
180786Speter 		case REF:
181786Speter 		case FVAR:
182786Speter 		/*
183786Speter 		 * We would prefer to return
184786Speter 		 * parameterless functions only.
185786Speter 		 */
186786Speter 		case FUNC:
1871201Speter 		case FFUNC:
1887922Smckusick 			return (varclass == NIL || (p->type != NIL && p->type->class == varclass));
1891201Speter 		case PROC:
1901201Speter 		case FPROC:
1917922Smckusick 			return ( varclass == NIL );
192786Speter 	}
193786Speter 	return (0);
194786Speter }
195786Speter #endif
196786Speter #ifdef PXP
197786Speter #ifndef DEBUG
identis()198786Speter identis()
199786Speter {
200786Speter 
201786Speter 	return (1);
202786Speter }
203786Speter #endif
204786Speter #ifdef DEBUG
205786Speter extern	char *classes[];
206786Speter 
207786Speter char	kindchars[]	"UCTVAQRDPF";
208786Speter /*
209786Speter  * Fake routine "identis" for pxp when testing error recovery.
210786Speter  * Looks at letters in variable names to answer questions
211786Speter  * about attributes.  Mapping is
212786Speter  *	C	const_id
213786Speter  *	T	type_id
214786Speter  *	V	var_id		also if any of AQRDF
215786Speter  *	A	array_id
216786Speter  *	Q	ptr_id
217786Speter  *	R	record_id
218786Speter  *	D	field_id	D for "dot"
219786Speter  *	P	proc_id
220786Speter  *	F	func_id
221786Speter  */
identis(cp,kind)222786Speter identis(cp, kind)
223786Speter 	register char *cp;
224786Speter 	int kind;
225786Speter {
226786Speter 	register char *dp;
227786Speter 	char kindch;
228786Speter 
229786Speter 	/*
230786Speter 	 * Don't do anything unless -T
231786Speter 	 */
232786Speter 	if (!typetest)
233786Speter 		return (1);
234786Speter 
235786Speter 	/*
236786Speter 	 * Inserted symbols are always correct
237786Speter 	 */
238786Speter 	if (cp == NIL)
239786Speter 		return (1);
240786Speter 	/*
241786Speter 	 * Set up the names for error messages
242786Speter 	 */
243786Speter 	yyidwant = classes[kind];
244786Speter 	for (dp = kindchars; *dp; dp++)
245786Speter 		if (any(cp, *dp)) {
246786Speter 			yyidhave = classes[dp - kindchars];
247786Speter 			break;
248786Speter 		}
249786Speter 
250786Speter 	/*
251786Speter 	 * U in the name means undefined
252786Speter 	 */
253786Speter 	if (any(cp, 'U'))
254786Speter 		return (0);
255786Speter 
256786Speter 	kindch = kindchars[kind];
257786Speter 	if (kindch == 'V')
258786Speter 		for (dp = "AQRDF"; *dp; dp++)
259786Speter 			if (any(cp, *dp))
260786Speter 				return (1);
261786Speter 	return (any(cp, kindch));
262786Speter }
263786Speter #endif
264786Speter #endif
265