table.c
1 //! @file table.c
2 //! @author J. Marcel van der Veer
3 //
4 //! @section Copyright
5 //
6 // This file is part of VIF - vintage FORTRAN compiler.
7 // Copyright 2020-2024 J. Marcel van der Veer <algol68g@xs4all.nl>.
8 //
9 //! @section License
10 //
11 // This program is free software; you can redistribute it and/or modify it
12 // under the terms of the GNU General Public License as published by the
13 // Free Software Foundation; either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful, but
17 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 // more details. You should have received a copy of the GNU General Public
20 // License along with this program. If not, see <http://www.gnu.org/licenses/>.
21
22 //! @section Synopsis
23 //!
24 //! Symbol table routines.
25
26 #include <vif.h>
27
28 int_4 ord (char ch)
29 {
30 return (ch - 'a');
31 }
32
33 char *edit_name (char *name)
34 {
35 static RECORD idf, idf2;
36 char *buf = idf;
37 strcpy (buf, name);
38 int_4 len = strlen (buf);
39 while (len > 1 && buf[len - 1] == '_') {
40 buf[len - 1] = '\0';
41 len = strlen (buf);
42 }
43 while (len > 1 && buf[0] == '_') {
44 buf++;
45 len = strlen (buf);
46 }
47 strcpy (idf2, buf);
48 return idf2;
49 }
50
51 char *edit_f (char *name)
52 {
53 static RECORD buf;
54 _srecordf (buf, "_%s", edit_name (name));
55 return buf;
56 }
57
58 char *edit_v (char *name)
59 {
60 static RECORD buf;
61 _srecordf (buf, "%s_", edit_name (name));
62 return buf;
63 }
64
65 char *edit_vn (char *name, int_4 nest)
66 {
67 static RECORD buf;
68 _srecordf (buf, "%s_%d_", edit_name (name), nest);
69 return buf;
70 }
71
72 char *edit_tmp (int_4 nest)
73 {
74 static RECORD buf;
75 _srecordf (buf, "$%d_", nest);
76 return buf;
77 }
78
79 char *edit_fmt (int_4 nest)
80 {
81 static RECORD buf;
82 _srecordf (buf, "$f_%d_", nest);
83 return buf;
84 }
85
86 char *edit_unit (int_4 nest)
87 {
88 static RECORD buf;
89 _srecordf (buf, "$u_%d_", nest);
90 return buf;
91 }
92
93 char *encode (char *buf, char *name)
94 {
95 bufcpy (buf, name, RECLN);
96 int_4 len = (int_4) strlen (buf);
97 if (buf[0] == '_' || buf[len - 1] == '_') {
98 return buf;
99 }
100 bufcpy (buf, edit_v (name), RECLN);
101 return buf;
102 }
103
104 char *c_name (char *name)
105 {
106 RECORD safe;
107 RECCLR (safe);
108 (void) encode (safe, name);
109 return stralloc (safe);
110 }
111
112 int_4 same_name (char *name, char * id)
113 {
114 if (name == NULL || id == NULL) return FALSE;
115 RECORD u, v;
116 RECCLR (u);
117 RECCLR (v);
118 (void) encode (u, name);
119 (void) encode (v, id);
120 return EQUAL (u, v);
121 }
122
123 LBL *find_label (char *lab)
124 {
125 int_4 k, num;
126 sscanf (lab, "%d", &num);
127 for (k = 0; k < nlabels; k++) {
128 LBL *L = &labels[k];
129 if (num == L->num) {
130 return L;
131 }
132 }
133 return NULL;
134 }
135
136 void impl_type (char *name, MODE * mode)
137 {
138 int_4 k = ord (tolower (name[0]));
139 (*mode) = implic[k].mode;
140 }
141
142 int_4 add_block (char *name)
143 {
144 int_4 k;
145 for (k = 0; k < ncommons; k++) {
146 if (same_name (name, commons[k])) {
147 return k;
148 }
149 }
150 if (ncommons >= MAX_COMMONS) {
151 FATAL (2801, "too many common blocks", NULL);
152 }
153 k = ncommons++;
154 commons[k] = c_name (name);
155 return k;
156 }
157
158 IDENT *find_local (char *name, MODE * mode)
159 {
160 int_4 k;
161 if (!IS_VAR (name)) {
162 ERROR (2802, "not a variable name", curlex);
163 return NULL;
164 }
165 // Search backwards, do not change.
166 for (k = nlocals - 1; k >= 0; k--) {
167 IDENT *idf = &locals[k];
168 if (EQUAL (name, CID (idf)) || EQUAL (name, FID (idf))) {
169 if (macro_nest > 0 ? TRUE : idf->nest == 0) {
170 if (mode != NULL) {
171 (*mode) = idf->mode;
172 }
173 idf->used = TRUE;
174 return idf;
175 }
176 }
177 }
178 return NULL;
179 }
180
181 IDENT *void_decl (char *name, MODE * mode)
182 {
183 if (!IS_VAR (name)) {
184 ERROR (2803, "not a variable name", curlex);
185 return NULL;
186 }
187 // Apparently a normal local variable.
188 IDENT *idf = find_local (name, mode);
189 if (idf == NULL) {
190 if (nlocals >= MAX_IDENTS) {
191 FATAL (2804, "too many identifiers", NULL);
192 return NULL;
193 }
194 idf = &locals[nlocals++];
195 memset (idf, 0, sizeof (IDENT));
196 idf->line = curlin;
197 CID (idf) = c_name (name);
198 FID (idf) = stralloc (name);
199 idf->external = FALSE;
200 idf->mode.type = NOTYPE;
201 idf->mode.len = 0;
202 if (mode != NULL) {
203 *mode = idf->mode;
204 }
205 }
206 return idf;
207 }
208
209 IDENT *add_local (char *name, int_4 type, int_4 len, int_4 uniq, int_4 apatch, int_4 arg, int_4 blck, int_4 src)
210 {
211 MODE mode;
212 if (!IS_VAR (name)) {
213 ERROR (2805, "not a variable name", curlex);
214 return NULL;
215 }
216 IDENT *idf = find_local (name, &mode);
217 if (type == CHARACTER) {
218 MODE m = {.type = type, .len = len};
219 norm_mode (&m);
220 len = m.len;
221 if (idf == NULL) {
222 if (len == 0 && arg == FALSE) {
223 ERROR (2806, "variable length character must be argument", name);
224 }
225 } else {
226 if (len == 0 && idf->arg == FALSE) {
227 ERROR (2807, "variable length character must be argument", name);
228 }
229 }
230 }
231 if (idf != NULL) {
232 if (uniq) {
233 if (idf->mode.type == NOTYPE) {
234 if (type != NOTYPE) {
235 // Do not overwrite 'dim', respect previous dimension statement.
236 idf->mode.type = type;
237 idf->mode.len = len;
238 } else {
239 idf->patch2 = apatch;
240 }
241 } else if (idf->parm != NULL) {
242 if (accept_mode (idf->mode.type, idf->mode.len, type, len)) {
243 idf->mode = PLAIN_MODE (type, len);
244 } else {
245 MODE err = PLAIN_MODE (type, len);
246 MODE_ERROR (2808, qtype (&err), qtype (&(idf->mode)));
247 }
248 } else if (idf->common > 0) {
249 idf->mode = PLAIN_MODE (type, len);
250 } else if (idf->external) {
251 idf->mode = PLAIN_MODE (type, len);
252 } else if (idf->mode.type == type && idf->mode.len == len) {
253 /* Let it pass */
254 } else {
255 ERROR (2809, "multiple definition", name);
256 }
257 }
258 return idf;
259 }
260 if (nlocals >= MAX_IDENTS) {
261 FATAL (2810, "too many identifiers", NULL);
262 return NULL;
263 }
264 idf = &locals[nlocals++];
265 memset (idf, 0, sizeof (IDENT));
266 idf->line = curlin;
267 CID (idf) = c_name (name);
268 FID (idf) = stralloc (name);
269 idf->arg = arg;
270 idf->common = blck;
271 idf->external = FALSE;
272 idf->mode = PLAIN_MODE (type, len);
273 idf->patch1 = apatch;
274 idf->source = src;
275 return idf;
276 }
277
278 IDENT *add_nest (char *name, int_4 nest, MODE *mode)
279 {
280 if (!IS_VAR (name)) {
281 ERROR (2811, "not a variable name", curlex);
282 return NULL;
283 }
284 if (nlocals >= MAX_IDENTS) {
285 FATAL (2812, "too many identifiers", NULL);
286 return NULL;
287 }
288 // Already declared? Take this mode.
289 IDENT *pre = find_local (name, mode);
290 //
291 IDENT *idf = &locals[nlocals++];
292 memset (idf, 0, sizeof (IDENT));
293 idf->line = curlin;
294 CID (idf) = c_name (name);
295 FID (idf) = stralloc (name);
296 idf->arg = NOARG;
297 idf->external = FALSE;
298 idf->common = 0;
299 idf->patch1 = NOPATCH;
300 idf->source = TEMP;
301 idf->nest = nest;
302 if (pre == NULL) {
303 impl_type (name, &idf->mode);
304 *mode = idf->mode;
305 } else {
306 *mode = pre->mode;
307 idf->mode = *mode;
308 }
309 return idf;
310 }
© 2002-2024 J.M. van der Veer (jmvdveer@xs4all.nl)
|