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