Implement formal functions and procedures
[unix-history] / usr / src / usr.bin / pascal / src / yyid.c
CommitLineData
e4fa3cd1
PK
1/* Copyright (c) 1979 Regents of the University of California */
2
c4e911b6 3static char sccsid[] = "@(#)yyid.c 1.2 %G%";
e4fa3cd1
PK
4
5#include "whoami.h"
6#include "0.h"
7#include "yy.h"
8
9#ifdef PI
10extern 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 */
23identis(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);
54gotit:
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 */
67yybaduse(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 */
90struct udinfo ud = { ~0 , ~0 , 0};
91/*
92 * Record a reference to an undefined identifier,
93 * or one which is improperly used.
94 */
95yybadref(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
c4e911b6
PK
109#define varkinds ((1<<CONST)|(1<<VAR)|(1<<REF)|(1<<ARRAY)|(1<<PTR) \
110 |(1<<RECORD)|(1<<FIELD)|(1<<FUNC)|(1<<FVAR) \
111 |(1<<FFUNC)|(1<<PROC)|(1<<FPROC))
e4fa3cd1
PK
112/*
113 * Is the symbol in the p entry of the namelist
114 * even possibly a kind kind? If not, update
115 * what we have based on this encounter.
116 */
117yyidok(p, kind)
118 register struct nl *p;
119 int kind;
120{
121
122 if (p->class == BADUSE) {
123 if (kind == VAR)
124 return (p->value[0] & varkinds);
125 return (p->value[0] & (1 << kind));
126 }
127 if (yyidok1(p, kind))
128 return (1);
129 if (yyidhave != NIL)
130 yyidhave = IMPROPER;
131 else
132 yyidhave = p->class;
133 return (0);
134}
135
136yyidok1(p, kind)
137 register struct nl *p;
138 int kind;
139{
140 int i;
141
142 switch (kind) {
143 case FUNC:
c4e911b6
PK
144 return ( p -> class == FUNC
145 || p -> class == FVAR
146 || p -> class == FFUNC );
147 case PROC:
148 return ( p -> class == PROC || p -> class == FPROC );
e4fa3cd1
PK
149 case CONST:
150 case TYPE:
e4fa3cd1
PK
151 case FIELD:
152 return (p->class == kind);
153 case VAR:
154 return (p->class == CONST || yyisvar(p, NIL));
155 case ARRAY:
156 case RECORD:
157 return (yyisvar(p, kind));
158 case PTRFILE:
159 return (yyisvar(p, PTR) || yyisvar(p, FILET));
160 }
161}
162
163yyisvar(p, class)
164 register struct nl *p;
165 int class;
166{
167
168 switch (p->class) {
169 case FIELD:
170 case VAR:
171 case REF:
172 case FVAR:
173 /*
174 * We would prefer to return
175 * parameterless functions only.
176 */
177 case FUNC:
c4e911b6 178 case FFUNC:
e4fa3cd1 179 return (class == NIL || (p->type != NIL && p->type->class == class));
c4e911b6
PK
180 case PROC:
181 case FPROC:
182 return ( class == NIL );
e4fa3cd1
PK
183 }
184 return (0);
185}
186#endif
187#ifdef PXP
188#ifndef DEBUG
189identis()
190{
191
192 return (1);
193}
194#endif
195#ifdef DEBUG
196extern char *classes[];
197
198char kindchars[] "UCTVAQRDPF";
199/*
200 * Fake routine "identis" for pxp when testing error recovery.
201 * Looks at letters in variable names to answer questions
202 * about attributes. Mapping is
203 * C const_id
204 * T type_id
205 * V var_id also if any of AQRDF
206 * A array_id
207 * Q ptr_id
208 * R record_id
209 * D field_id D for "dot"
210 * P proc_id
211 * F func_id
212 */
213identis(cp, kind)
214 register char *cp;
215 int kind;
216{
217 register char *dp;
218 char kindch;
219
220 /*
221 * Don't do anything unless -T
222 */
223 if (!typetest)
224 return (1);
225
226 /*
227 * Inserted symbols are always correct
228 */
229 if (cp == NIL)
230 return (1);
231 /*
232 * Set up the names for error messages
233 */
234 yyidwant = classes[kind];
235 for (dp = kindchars; *dp; dp++)
236 if (any(cp, *dp)) {
237 yyidhave = classes[dp - kindchars];
238 break;
239 }
240
241 /*
242 * U in the name means undefined
243 */
244 if (any(cp, 'U'))
245 return (0);
246
247 kindch = kindchars[kind];
248 if (kindch == 'V')
249 for (dp = "AQRDF"; *dp; dp++)
250 if (any(cp, *dp))
251 return (1);
252 return (any(cp, kindch));
253}
254#endif
255#endif