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 */
identis(cp,kind)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 *
yybaduse(cp,line,kindmask)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 */
yybadref(p,line)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 */
yyidok(p,kind)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
yyidok1(p,kind)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
yyisvar(p,varclass)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
identis()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 */
identis(cp,kind)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