148116Sbostic /*-
2*62223Sbostic * Copyright (c) 1980, 1993
3*62223Sbostic * The Regents of the University of California. All rights reserved.
448116Sbostic *
548116Sbostic * %sccs.include.redist.c%
622206Sdist */
7786Speter
814748Sthien #ifndef lint
9*62223Sbostic static char sccsid[] = "@(#)yyid.c 8.1 (Berkeley) 06/06/93";
1048116Sbostic #endif /* not lint */
11786Speter
12786Speter #include "whoami.h"
1344619Sbostic #include <0.h>
1414748Sthien #include "tree_ty.h" /* must be included for yy.h */
15786Speter #include "yy.h"
16786Speter
17786Speter #ifdef PI
1814748Sthien extern union semstack *yypv;
19786Speter /*
20786Speter * Determine whether the identifier whose name
21786Speter * is "cp" can possibly be a kind, which is a
22786Speter * namelist class. We look through the symbol
23786Speter * table for the first instance of cp as a non-field,
24786Speter * and at all instances of cp as a field.
25786Speter * If any of these are ok, we return true, else false.
26786Speter * It would be much better to handle with's correctly,
27786Speter * even to just know whether we are in a with at all.
28786Speter *
29786Speter * Note that we don't disallow constants on the lhs of assignment.
30786Speter */
identis(cp,kind)31786Speter identis(cp, kind)
32786Speter register char *cp;
33786Speter int kind;
34786Speter {
35786Speter register struct nl *p;
36786Speter int i;
37786Speter
38786Speter /*
39786Speter * Cp is NIL when error recovery inserts it.
40786Speter */
41786Speter if (cp == NIL)
42786Speter return (1);
43786Speter
44786Speter /*
45786Speter * Record kind we want for possible later use by yyrecover
46786Speter */
47786Speter yyidwant = kind;
48786Speter yyidhave = NIL;
49786Speter i = ( (int) cp ) & 077;
50786Speter for (p = disptab[i]; p != NIL; p = p->nl_next)
51786Speter if (p->symbol == cp) {
52786Speter if (yyidok(p, kind))
53786Speter goto gotit;
54786Speter if (p->class != FIELD && p->class != BADUSE)
55786Speter break;
56786Speter }
57786Speter if (p != NIL)
58786Speter for (p = p->nl_next; p != NIL; p = p->nl_next)
59786Speter if (p->symbol == cp && p->class == FIELD && yyidok(p, kind))
60786Speter goto gotit;
61786Speter return (0);
62786Speter gotit:
63786Speter if (p->class == BADUSE && !Recovery) {
64786Speter yybadref(p, OY.Yyeline);
6514748Sthien yypv[0].i_entry = NIL;
66786Speter }
67786Speter return (1);
68786Speter }
69786Speter
70786Speter /*
71786Speter * A bad reference to the identifier cp on line
72786Speter * line and use implying the addition of kindmask
73786Speter * to the mask of kind information.
74786Speter */
7514748Sthien struct nl *
yybaduse(cp,line,kindmask)76786Speter yybaduse(cp, line, kindmask)
77786Speter register char *cp;
78786Speter int line, kindmask;
79786Speter {
80786Speter register struct nl *p, *oldp;
81786Speter int i;
82786Speter
83786Speter i = ( (int) cp ) & 077;
84786Speter for (p = disptab[i]; p != NIL; p = p->nl_next)
85786Speter if (p->symbol == cp)
86786Speter break;
87786Speter oldp = p;
88786Speter if (p == NIL || p->class != BADUSE)
8914748Sthien p = enter(defnl(cp, BADUSE, NLNIL, 0));
903085Smckusic p->value[NL_KINDS] |= kindmask;
91786Speter yybadref(p, line);
92786Speter return (oldp);
93786Speter }
94786Speter
95786Speter /*
96786Speter * ud is initialized so that esavestr will allocate
97786Speter * sizeof ( struct udinfo ) bytes for the 'real' struct udinfo
98786Speter */
9914748Sthien struct udinfo ud = { ~0 , (struct udinfo *) ~0 , 0};
100786Speter /*
101786Speter * Record a reference to an undefined identifier,
102786Speter * or one which is improperly used.
103786Speter */
yybadref(p,line)104786Speter yybadref(p, line)
105786Speter register struct nl *p;
106786Speter int line;
107786Speter {
108786Speter register struct udinfo *udp;
109786Speter
11014748Sthien if (p->chain != NIL && ((struct udinfo *) p->chain)->ud_line == line)
111786Speter return;
11214748Sthien udp = (struct udinfo *) esavestr((char *) &ud);
113786Speter udp->ud_line = line;
11414748Sthien udp->ud_next = (struct udinfo *) p->chain;
11514748Sthien p->chain = (struct nl *) udp;
116786Speter }
117786Speter
1181201Speter #define varkinds ((1<<CONST)|(1<<VAR)|(1<<REF)|(1<<ARRAY)|(1<<PTR) \
1191201Speter |(1<<RECORD)|(1<<FIELD)|(1<<FUNC)|(1<<FVAR) \
1201201Speter |(1<<FFUNC)|(1<<PROC)|(1<<FPROC))
121786Speter /*
122786Speter * Is the symbol in the p entry of the namelist
123786Speter * even possibly a kind kind? If not, update
124786Speter * what we have based on this encounter.
125786Speter */
yyidok(p,kind)126786Speter yyidok(p, kind)
127786Speter register struct nl *p;
128786Speter int kind;
129786Speter {
130786Speter
131786Speter if (p->class == BADUSE) {
132786Speter if (kind == VAR)
133786Speter return (p->value[0] & varkinds);
134786Speter return (p->value[0] & (1 << kind));
135786Speter }
136786Speter if (yyidok1(p, kind))
137786Speter return (1);
138786Speter if (yyidhave != NIL)
139786Speter yyidhave = IMPROPER;
140786Speter else
141786Speter yyidhave = p->class;
142786Speter return (0);
143786Speter }
144786Speter
yyidok1(p,kind)145786Speter yyidok1(p, kind)
146786Speter register struct nl *p;
147786Speter int kind;
148786Speter {
149786Speter
150786Speter switch (kind) {
15114748Sthien default:
152786Speter case FUNC:
1531201Speter return ( p -> class == FUNC
1541201Speter || p -> class == FVAR
1551201Speter || p -> class == FFUNC );
1561201Speter case PROC:
1571201Speter return ( p -> class == PROC || p -> class == FPROC );
158786Speter case CONST:
159786Speter case TYPE:
160786Speter case FIELD:
161786Speter return (p->class == kind);
162786Speter case VAR:
163786Speter return (p->class == CONST || yyisvar(p, NIL));
164786Speter case ARRAY:
165786Speter case RECORD:
166786Speter return (yyisvar(p, kind));
167786Speter case PTRFILE:
168786Speter return (yyisvar(p, PTR) || yyisvar(p, FILET));
169786Speter }
170786Speter }
171786Speter
yyisvar(p,varclass)1727922Smckusick yyisvar(p, varclass)
173786Speter register struct nl *p;
1747922Smckusick int varclass;
175786Speter {
176786Speter
177786Speter switch (p->class) {
178786Speter case FIELD:
179786Speter case VAR:
180786Speter case REF:
181786Speter case FVAR:
182786Speter /*
183786Speter * We would prefer to return
184786Speter * parameterless functions only.
185786Speter */
186786Speter case FUNC:
1871201Speter case FFUNC:
1887922Smckusick return (varclass == NIL || (p->type != NIL && p->type->class == varclass));
1891201Speter case PROC:
1901201Speter case FPROC:
1917922Smckusick return ( varclass == NIL );
192786Speter }
193786Speter return (0);
194786Speter }
195786Speter #endif
196786Speter #ifdef PXP
197786Speter #ifndef DEBUG
identis()198786Speter identis()
199786Speter {
200786Speter
201786Speter return (1);
202786Speter }
203786Speter #endif
204786Speter #ifdef DEBUG
205786Speter extern char *classes[];
206786Speter
207786Speter char kindchars[] "UCTVAQRDPF";
208786Speter /*
209786Speter * Fake routine "identis" for pxp when testing error recovery.
210786Speter * Looks at letters in variable names to answer questions
211786Speter * about attributes. Mapping is
212786Speter * C const_id
213786Speter * T type_id
214786Speter * V var_id also if any of AQRDF
215786Speter * A array_id
216786Speter * Q ptr_id
217786Speter * R record_id
218786Speter * D field_id D for "dot"
219786Speter * P proc_id
220786Speter * F func_id
221786Speter */
identis(cp,kind)222786Speter identis(cp, kind)
223786Speter register char *cp;
224786Speter int kind;
225786Speter {
226786Speter register char *dp;
227786Speter char kindch;
228786Speter
229786Speter /*
230786Speter * Don't do anything unless -T
231786Speter */
232786Speter if (!typetest)
233786Speter return (1);
234786Speter
235786Speter /*
236786Speter * Inserted symbols are always correct
237786Speter */
238786Speter if (cp == NIL)
239786Speter return (1);
240786Speter /*
241786Speter * Set up the names for error messages
242786Speter */
243786Speter yyidwant = classes[kind];
244786Speter for (dp = kindchars; *dp; dp++)
245786Speter if (any(cp, *dp)) {
246786Speter yyidhave = classes[dp - kindchars];
247786Speter break;
248786Speter }
249786Speter
250786Speter /*
251786Speter * U in the name means undefined
252786Speter */
253786Speter if (any(cp, 'U'))
254786Speter return (0);
255786Speter
256786Speter kindch = kindchars[kind];
257786Speter if (kindch == 'V')
258786Speter for (dp = "AQRDF"; *dp; dp++)
259786Speter if (any(cp, *dp))
260786Speter return (1);
261786Speter return (any(cp, kindch));
262786Speter }
263786Speter #endif
264786Speter #endif
265