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