xref: /csrg-svn/usr.bin/pascal/src/yyid.c (revision 14748)
1786Speter /* Copyright (c) 1979 Regents of the University of California */
2786Speter 
3*14748Sthien #ifndef lint
4*14748Sthien static char sccsid[] = "@(#)yyid.c 1.5 08/19/83";
5*14748Sthien #endif
6786Speter 
7786Speter #include "whoami.h"
8786Speter #include "0.h"
9*14748Sthien #include "tree_ty.h"	/* must be included for yy.h */
10786Speter #include "yy.h"
11786Speter 
12786Speter #ifdef PI
13*14748Sthien extern	union semstack *yypv;
14786Speter /*
15786Speter  * Determine whether the identifier whose name
16786Speter  * is "cp" can possibly be a kind, which is a
17786Speter  * namelist class.  We look through the symbol
18786Speter  * table for the first instance of cp as a non-field,
19786Speter  * and at all instances of cp as a field.
20786Speter  * If any of these are ok, we return true, else false.
21786Speter  * It would be much better to handle with's correctly,
22786Speter  * even to just know whether we are in a with at all.
23786Speter  *
24786Speter  * Note that we don't disallow constants on the lhs of assignment.
25786Speter  */
26786Speter identis(cp, kind)
27786Speter 	register char *cp;
28786Speter 	int kind;
29786Speter {
30786Speter 	register struct nl *p;
31786Speter 	int i;
32786Speter 
33786Speter 	/*
34786Speter 	 * Cp is NIL when error recovery inserts it.
35786Speter 	 */
36786Speter 	if (cp == NIL)
37786Speter 		return (1);
38786Speter 
39786Speter 	/*
40786Speter 	 * Record kind we want for possible later use by yyrecover
41786Speter 	 */
42786Speter 	yyidwant = kind;
43786Speter 	yyidhave = NIL;
44786Speter 	i = ( (int) cp ) & 077;
45786Speter 	for (p = disptab[i]; p != NIL; p = p->nl_next)
46786Speter 		if (p->symbol == cp) {
47786Speter 			if (yyidok(p, kind))
48786Speter 				goto gotit;
49786Speter 			if (p->class != FIELD && p->class != BADUSE)
50786Speter 				break;
51786Speter 		}
52786Speter 	if (p != NIL)
53786Speter 		for (p = p->nl_next; p != NIL; p = p->nl_next)
54786Speter 			if (p->symbol == cp && p->class == FIELD && yyidok(p, kind))
55786Speter 				goto gotit;
56786Speter 	return (0);
57786Speter gotit:
58786Speter 	if (p->class == BADUSE && !Recovery) {
59786Speter 		yybadref(p, OY.Yyeline);
60*14748Sthien 		yypv[0].i_entry = NIL;
61786Speter 	}
62786Speter 	return (1);
63786Speter }
64786Speter 
65786Speter /*
66786Speter  * A bad reference to the identifier cp on line
67786Speter  * line and use implying the addition of kindmask
68786Speter  * to the mask of kind information.
69786Speter  */
70*14748Sthien struct nl *
71786Speter yybaduse(cp, line, kindmask)
72786Speter 	register char *cp;
73786Speter 	int line, kindmask;
74786Speter {
75786Speter 	register struct nl *p, *oldp;
76786Speter 	int i;
77786Speter 
78786Speter 	i = ( (int) cp ) & 077;
79786Speter 	for (p = disptab[i]; p != NIL; p = p->nl_next)
80786Speter 		if (p->symbol == cp)
81786Speter 			break;
82786Speter 	oldp = p;
83786Speter 	if (p == NIL || p->class != BADUSE)
84*14748Sthien 		p = enter(defnl(cp, BADUSE, NLNIL, 0));
853085Smckusic 	p->value[NL_KINDS] |= kindmask;
86786Speter 	yybadref(p, line);
87786Speter 	return (oldp);
88786Speter }
89786Speter 
90786Speter     /*
91786Speter      *	ud is initialized so that esavestr will allocate
92786Speter      *	sizeof ( struct udinfo ) bytes for the 'real' struct udinfo
93786Speter      */
94*14748Sthien struct	udinfo ud = { ~0 , (struct udinfo *) ~0 , 0};
95786Speter /*
96786Speter  * Record a reference to an undefined identifier,
97786Speter  * or one which is improperly used.
98786Speter  */
99786Speter yybadref(p, line)
100786Speter 	register struct nl *p;
101786Speter 	int line;
102786Speter {
103786Speter 	register struct udinfo *udp;
104786Speter 
105*14748Sthien 	if (p->chain != NIL && ((struct udinfo *) p->chain)->ud_line == line)
106786Speter 		return;
107*14748Sthien 	udp = (struct udinfo *) esavestr((char *) &ud);
108786Speter 	udp->ud_line = line;
109*14748Sthien 	udp->ud_next = (struct udinfo *) p->chain;
110*14748Sthien 	p->chain = (struct nl *) udp;
111786Speter }
112786Speter 
1131201Speter #define	varkinds	((1<<CONST)|(1<<VAR)|(1<<REF)|(1<<ARRAY)|(1<<PTR) \
1141201Speter 			|(1<<RECORD)|(1<<FIELD)|(1<<FUNC)|(1<<FVAR) \
1151201Speter 			|(1<<FFUNC)|(1<<PROC)|(1<<FPROC))
116786Speter /*
117786Speter  * Is the symbol in the p entry of the namelist
118786Speter  * even possibly a kind kind?  If not, update
119786Speter  * what we have based on this encounter.
120786Speter  */
121786Speter yyidok(p, kind)
122786Speter 	register struct nl *p;
123786Speter 	int kind;
124786Speter {
125786Speter 
126786Speter 	if (p->class == BADUSE) {
127786Speter 		if (kind == VAR)
128786Speter 			return (p->value[0] & varkinds);
129786Speter 		return (p->value[0] & (1 << kind));
130786Speter 	}
131786Speter 	if (yyidok1(p, kind))
132786Speter 		return (1);
133786Speter 	if (yyidhave != NIL)
134786Speter 		yyidhave = IMPROPER;
135786Speter 	else
136786Speter 		yyidhave = p->class;
137786Speter 	return (0);
138786Speter }
139786Speter 
140786Speter yyidok1(p, kind)
141786Speter 	register struct nl *p;
142786Speter 	int kind;
143786Speter {
144786Speter 
145786Speter 	switch (kind) {
146*14748Sthien 		default:
147786Speter 		case FUNC:
1481201Speter 			return (   p -> class == FUNC
1491201Speter 				|| p -> class == FVAR
1501201Speter 				|| p -> class == FFUNC );
1511201Speter 		case PROC:
1521201Speter 			return ( p -> class == PROC || p -> class == FPROC );
153786Speter 		case CONST:
154786Speter 		case TYPE:
155786Speter 		case FIELD:
156786Speter 			return (p->class == kind);
157786Speter 		case VAR:
158786Speter 			return (p->class == CONST || yyisvar(p, NIL));
159786Speter 		case ARRAY:
160786Speter 		case RECORD:
161786Speter 			return (yyisvar(p, kind));
162786Speter 		case PTRFILE:
163786Speter 			return (yyisvar(p, PTR) || yyisvar(p, FILET));
164786Speter 	}
165786Speter }
166786Speter 
1677922Smckusick yyisvar(p, varclass)
168786Speter 	register struct nl *p;
1697922Smckusick 	int varclass;
170786Speter {
171786Speter 
172786Speter 	switch (p->class) {
173786Speter 		case FIELD:
174786Speter 		case VAR:
175786Speter 		case REF:
176786Speter 		case FVAR:
177786Speter 		/*
178786Speter 		 * We would prefer to return
179786Speter 		 * parameterless functions only.
180786Speter 		 */
181786Speter 		case FUNC:
1821201Speter 		case FFUNC:
1837922Smckusick 			return (varclass == NIL || (p->type != NIL && p->type->class == varclass));
1841201Speter 		case PROC:
1851201Speter 		case FPROC:
1867922Smckusick 			return ( varclass == NIL );
187786Speter 	}
188786Speter 	return (0);
189786Speter }
190786Speter #endif
191786Speter #ifdef PXP
192786Speter #ifndef DEBUG
193786Speter identis()
194786Speter {
195786Speter 
196786Speter 	return (1);
197786Speter }
198786Speter #endif
199786Speter #ifdef DEBUG
200786Speter extern	char *classes[];
201786Speter 
202786Speter char	kindchars[]	"UCTVAQRDPF";
203786Speter /*
204786Speter  * Fake routine "identis" for pxp when testing error recovery.
205786Speter  * Looks at letters in variable names to answer questions
206786Speter  * about attributes.  Mapping is
207786Speter  *	C	const_id
208786Speter  *	T	type_id
209786Speter  *	V	var_id		also if any of AQRDF
210786Speter  *	A	array_id
211786Speter  *	Q	ptr_id
212786Speter  *	R	record_id
213786Speter  *	D	field_id	D for "dot"
214786Speter  *	P	proc_id
215786Speter  *	F	func_id
216786Speter  */
217786Speter identis(cp, kind)
218786Speter 	register char *cp;
219786Speter 	int kind;
220786Speter {
221786Speter 	register char *dp;
222786Speter 	char kindch;
223786Speter 
224786Speter 	/*
225786Speter 	 * Don't do anything unless -T
226786Speter 	 */
227786Speter 	if (!typetest)
228786Speter 		return (1);
229786Speter 
230786Speter 	/*
231786Speter 	 * Inserted symbols are always correct
232786Speter 	 */
233786Speter 	if (cp == NIL)
234786Speter 		return (1);
235786Speter 	/*
236786Speter 	 * Set up the names for error messages
237786Speter 	 */
238786Speter 	yyidwant = classes[kind];
239786Speter 	for (dp = kindchars; *dp; dp++)
240786Speter 		if (any(cp, *dp)) {
241786Speter 			yyidhave = classes[dp - kindchars];
242786Speter 			break;
243786Speter 		}
244786Speter 
245786Speter 	/*
246786Speter 	 * U in the name means undefined
247786Speter 	 */
248786Speter 	if (any(cp, 'U'))
249786Speter 		return (0);
250786Speter 
251786Speter 	kindch = kindchars[kind];
252786Speter 	if (kindch == 'V')
253786Speter 		for (dp = "AQRDF"; *dp; dp++)
254786Speter 			if (any(cp, *dp))
255786Speter 				return (1);
256786Speter 	return (any(cp, kindch));
257786Speter }
258786Speter #endif
259786Speter #endif
260