Commit | Line | Data |
---|---|---|
e4fa3cd1 PK |
1 | /* Copyright (c) 1979 Regents of the University of California */ |
2 | ||
3 | static char sccsid[] = "@(#)yyid.c 1.1 %G%"; | |
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 | \f | |
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 |