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