xref: /original-bsd/usr.bin/pascal/src/yyid.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[] = "@(#)yyid.c	8.1 (Berkeley) 06/06/93";
10 #endif /* not lint */
11 
12 #include "whoami.h"
13 #include <0.h>
14 #include "tree_ty.h"	/* must be included for yy.h */
15 #include "yy.h"
16 
17 #ifdef PI
18 extern	union semstack *yypv;
19 /*
20  * Determine whether the identifier whose name
21  * is "cp" can possibly be a kind, which is a
22  * namelist class.  We look through the symbol
23  * table for the first instance of cp as a non-field,
24  * and at all instances of cp as a field.
25  * If any of these are ok, we return true, else false.
26  * It would be much better to handle with's correctly,
27  * even to just know whether we are in a with at all.
28  *
29  * Note that we don't disallow constants on the lhs of assignment.
30  */
31 identis(cp, kind)
32 	register char *cp;
33 	int kind;
34 {
35 	register struct nl *p;
36 	int i;
37 
38 	/*
39 	 * Cp is NIL when error recovery inserts it.
40 	 */
41 	if (cp == NIL)
42 		return (1);
43 
44 	/*
45 	 * Record kind we want for possible later use by yyrecover
46 	 */
47 	yyidwant = kind;
48 	yyidhave = NIL;
49 	i = ( (int) cp ) & 077;
50 	for (p = disptab[i]; p != NIL; p = p->nl_next)
51 		if (p->symbol == cp) {
52 			if (yyidok(p, kind))
53 				goto gotit;
54 			if (p->class != FIELD && p->class != BADUSE)
55 				break;
56 		}
57 	if (p != NIL)
58 		for (p = p->nl_next; p != NIL; p = p->nl_next)
59 			if (p->symbol == cp && p->class == FIELD && yyidok(p, kind))
60 				goto gotit;
61 	return (0);
62 gotit:
63 	if (p->class == BADUSE && !Recovery) {
64 		yybadref(p, OY.Yyeline);
65 		yypv[0].i_entry = NIL;
66 	}
67 	return (1);
68 }
69 
70 /*
71  * A bad reference to the identifier cp on line
72  * line and use implying the addition of kindmask
73  * to the mask of kind information.
74  */
75 struct nl *
76 yybaduse(cp, line, kindmask)
77 	register char *cp;
78 	int line, kindmask;
79 {
80 	register struct nl *p, *oldp;
81 	int i;
82 
83 	i = ( (int) cp ) & 077;
84 	for (p = disptab[i]; p != NIL; p = p->nl_next)
85 		if (p->symbol == cp)
86 			break;
87 	oldp = p;
88 	if (p == NIL || p->class != BADUSE)
89 		p = enter(defnl(cp, BADUSE, NLNIL, 0));
90 	p->value[NL_KINDS] |= kindmask;
91 	yybadref(p, line);
92 	return (oldp);
93 }
94 
95     /*
96      *	ud is initialized so that esavestr will allocate
97      *	sizeof ( struct udinfo ) bytes for the 'real' struct udinfo
98      */
99 struct	udinfo ud = { ~0 , (struct udinfo *) ~0 , 0};
100 /*
101  * Record a reference to an undefined identifier,
102  * or one which is improperly used.
103  */
104 yybadref(p, line)
105 	register struct nl *p;
106 	int line;
107 {
108 	register struct udinfo *udp;
109 
110 	if (p->chain != NIL && ((struct udinfo *) p->chain)->ud_line == line)
111 		return;
112 	udp = (struct udinfo *) esavestr((char *) &ud);
113 	udp->ud_line = line;
114 	udp->ud_next = (struct udinfo *) p->chain;
115 	p->chain = (struct nl *) udp;
116 }
117 
118 #define	varkinds	((1<<CONST)|(1<<VAR)|(1<<REF)|(1<<ARRAY)|(1<<PTR) \
119 			|(1<<RECORD)|(1<<FIELD)|(1<<FUNC)|(1<<FVAR) \
120 			|(1<<FFUNC)|(1<<PROC)|(1<<FPROC))
121 /*
122  * Is the symbol in the p entry of the namelist
123  * even possibly a kind kind?  If not, update
124  * what we have based on this encounter.
125  */
126 yyidok(p, kind)
127 	register struct nl *p;
128 	int kind;
129 {
130 
131 	if (p->class == BADUSE) {
132 		if (kind == VAR)
133 			return (p->value[0] & varkinds);
134 		return (p->value[0] & (1 << kind));
135 	}
136 	if (yyidok1(p, kind))
137 		return (1);
138 	if (yyidhave != NIL)
139 		yyidhave = IMPROPER;
140 	else
141 		yyidhave = p->class;
142 	return (0);
143 }
144 
145 yyidok1(p, kind)
146 	register struct nl *p;
147 	int kind;
148 {
149 
150 	switch (kind) {
151 		default:
152 		case FUNC:
153 			return (   p -> class == FUNC
154 				|| p -> class == FVAR
155 				|| p -> class == FFUNC );
156 		case PROC:
157 			return ( p -> class == PROC || p -> class == FPROC );
158 		case CONST:
159 		case TYPE:
160 		case FIELD:
161 			return (p->class == kind);
162 		case VAR:
163 			return (p->class == CONST || yyisvar(p, NIL));
164 		case ARRAY:
165 		case RECORD:
166 			return (yyisvar(p, kind));
167 		case PTRFILE:
168 			return (yyisvar(p, PTR) || yyisvar(p, FILET));
169 	}
170 }
171 
172 yyisvar(p, varclass)
173 	register struct nl *p;
174 	int varclass;
175 {
176 
177 	switch (p->class) {
178 		case FIELD:
179 		case VAR:
180 		case REF:
181 		case FVAR:
182 		/*
183 		 * We would prefer to return
184 		 * parameterless functions only.
185 		 */
186 		case FUNC:
187 		case FFUNC:
188 			return (varclass == NIL || (p->type != NIL && p->type->class == varclass));
189 		case PROC:
190 		case FPROC:
191 			return ( varclass == NIL );
192 	}
193 	return (0);
194 }
195 #endif
196 #ifdef PXP
197 #ifndef DEBUG
198 identis()
199 {
200 
201 	return (1);
202 }
203 #endif
204 #ifdef DEBUG
205 extern	char *classes[];
206 
207 char	kindchars[]	"UCTVAQRDPF";
208 /*
209  * Fake routine "identis" for pxp when testing error recovery.
210  * Looks at letters in variable names to answer questions
211  * about attributes.  Mapping is
212  *	C	const_id
213  *	T	type_id
214  *	V	var_id		also if any of AQRDF
215  *	A	array_id
216  *	Q	ptr_id
217  *	R	record_id
218  *	D	field_id	D for "dot"
219  *	P	proc_id
220  *	F	func_id
221  */
222 identis(cp, kind)
223 	register char *cp;
224 	int kind;
225 {
226 	register char *dp;
227 	char kindch;
228 
229 	/*
230 	 * Don't do anything unless -T
231 	 */
232 	if (!typetest)
233 		return (1);
234 
235 	/*
236 	 * Inserted symbols are always correct
237 	 */
238 	if (cp == NIL)
239 		return (1);
240 	/*
241 	 * Set up the names for error messages
242 	 */
243 	yyidwant = classes[kind];
244 	for (dp = kindchars; *dp; dp++)
245 		if (any(cp, *dp)) {
246 			yyidhave = classes[dp - kindchars];
247 			break;
248 		}
249 
250 	/*
251 	 * U in the name means undefined
252 	 */
253 	if (any(cp, 'U'))
254 		return (0);
255 
256 	kindch = kindchars[kind];
257 	if (kindch == 'V')
258 		for (dp = "AQRDF"; *dp; dp++)
259 			if (any(cp, *dp))
260 				return (1);
261 	return (any(cp, kindch));
262 }
263 #endif
264 #endif
265