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-2025 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 RECCPY (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_i (char *name)
59 {
60 static RECORD buf;
61 _srecordf (buf, "__%s", edit_name (name));
62 return buf;
63 }
64
65 char *edit_v (char *name)
66 {
67 static RECORD buf;
68 _srecordf (buf, "%s_", edit_name (name));
69 return buf;
70 }
71
72 char *edit_vn (char *name, int_4 num)
73 {
74 static RECORD buf;
75 _srecordf (buf, "%s_%d_", edit_name (name), num);
76 return buf;
77 }
78
79 char *edit_tmp (int_4 num)
80 {
81 static RECORD buf;
82 _srecordf (buf, "$%d_", num);
83 return buf;
84 }
85
86 char *edit_fmt (int_4 num)
87 {
88 static RECORD buf;
89 if (num >= 100000) { // Anonymous text formats
90 _srecordf (buf, "$f_%d_", num);
91 return buf;
92 }
93 LBL *L = NO_LABEL;
94 for (int_4 k = 0; k < nlabels; k++) {
95 if (num == labels[k].num) {
96 L = &labels[k];
97 break;
98 }
99 }
100 if (L == NO_LABEL) {
101 _srecordf (buf, "%d", num);
102 ERROR (3101, "undefined label", buf);
103 return NO_TEXT;
104 } else if (!L->format) {
105 _srecordf (buf, "%d", num);
106 ERROR (3102, "not a format label", buf);
107 return NO_TEXT;
108 } else {
109 L->jumped++;
110 _srecordf (buf, "$f_%d_", num);
111 return buf;
112 }
113 }
114
115 char *edit_unit (int_4 num)
116 {
117 static RECORD buf;
118 _srecordf (buf, "$u_%d_", num);
119 return buf;
120 }
121
122 char *encode (char *buf, char *name)
123 {
124 bufcpy (buf, name, RECLN);
125 int_4 len = (int_4) strlen (buf);
126 if (buf[0] == '_' || buf[len - 1] == '_') {
127 return buf;
128 }
129 bufcpy (buf, edit_v (name), RECLN);
130 return buf;
131 }
132
133 char *c_name (char *name)
134 {
135 NEW_RECORD (safe);
136 (void) encode (safe, name);
137 return f_stralloc (safe);
138 }
139
140 logical_4 same_name (char *name, char * id)
141 {
142 if (name == NO_TEXT || id == NO_TEXT) return FALSE;
143 NEW_RECORD (u);
144 NEW_RECORD (v);
145 (void) encode (u, name);
146 (void) encode (v, id);
147 return EQUAL (u, v);
148 }
149
150 LBL *find_label (char *lab)
151 {
152 int_4 k, num;
153 sscanf (lab, "%d", &num);
154 for (k = 0; k < nlabels; k++) {
155 LBL *L = &labels[k];
156 if (num == L->num) {
157 return L;
158 }
159 }
160 return NO_LABEL;
161 }
162
163 void impl_type (char *name, MODE * mode)
164 {
165 int_4 k = ord (tolower (name[0]));
166 (*mode) = implic[k].mode;
167 }
168
169 int_4 add_block (char *name)
170 {
171 int_4 k;
172 for (k = 0; k < ncommons; k++) {
173 if (same_name (name, commons[k])) {
174 return k;
175 }
176 }
177 if (ncommons >= MAX_COMMONS) {
178 FATAL (3103, "too many common blocks", NO_TEXT);
179 }
180 k = ncommons++;
181 commons[k] = c_name (name);
182 return k;
183 }
184
185 IDENT *find_local (char *name, MODE * mode)
186 {
187 int_4 k;
188 if (!IS_VAR (name)) {
189 ERROR (3104, "not a variable name", curlex);
190 return NO_IDENT;
191 }
192 // Search backwards, do not change.
193 for (k = nlocals - 1; k >= 0; k--) {
194 IDENT *idf = &locals[k];
195 if (idf->nest >= 0 && (EQUAL (name, C_NAME (idf)) || EQUAL (name, FTN_NAME (idf)))) {
196 if (macro_nest > 0 ? TRUE : idf->nest == 0) {
197 if (mode != NO_MODE) {
198 (*mode) = idf->mode;
199 }
200 idf->used = TRUE;
201 return idf;
202 }
203 }
204 }
205 return NO_IDENT;
206 }
207
208 IDENT *void_decl (char *name, MODE * mode)
209 {
210 if (!IS_VAR (name)) {
211 ERROR (3105, "not a variable name", curlex);
212 return NO_IDENT;
213 }
214 // Apparently a normal local variable.
215 IDENT *idf = find_local (name, mode);
216 if (idf == NO_IDENT) {
217 if (nlocals >= MAX_IDENTS) {
218 FATAL (3106, "too many identifiers", NO_TEXT);
219 return NO_IDENT;
220 }
221 idf = &locals[nlocals++];
222 memset (idf, 0, sizeof (IDENT));
223 idf->line = curlin;
224 C_NAME (idf) = c_name (name);
225 FTN_NAME (idf) = f_stralloc (name);
226 idf->external = FALSE;
227 idf->mode.type = NOTYPE;
228 idf->mode.len = 0;
229 if (mode != NO_MODE) {
230 *mode = idf->mode;
231 }
232 }
233 return idf;
234 }
235
236 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)
237 {
238 MODE mode;
239 if (!IS_VAR (name)) {
240 ERROR (3107, "not a variable name", curlex);
241 return NO_IDENT;
242 }
243 IDENT *idf = find_local (name, &mode);
244 if (type == CHARACTER) {
245 MODE m = {.type = type, .len = len};
246 norm_mode (&m);
247 len = m.len;
248 if (idf == NO_IDENT) {
249 if (len == 0 && arg == FALSE) {
250 ERROR (3108, "variable length character must be argument", name);
251 }
252 } else {
253 if (len == 0 && idf->arg == FALSE) {
254 ERROR (3109, "variable length character must be argument", name);
255 }
256 }
257 }
258 if (idf != NO_IDENT) {
259 if (uniq) {
260 if (idf->mode.type == NOTYPE) {
261 if (type != NOTYPE) {
262 // Do not overwrite 'dim', respect previous dimension statement.
263 idf->mode.type = type;
264 idf->mode.len = len;
265 } else {
266 idf->patch2 = apatch;
267 }
268 } else if (idf->parm != NO_TEXT) {
269 if (accept_mode (idf->mode.type, idf->mode.len, type, len)) {
270 idf->mode = PLAIN_MODE (type, len);
271 } else {
272 MODE err = PLAIN_MODE (type, len);
273 MODE_ERROR (3110, qtype (&err), qtype (&(idf->mode)));
274 }
275 } else if (NOT_LOCAL (idf)) {
276 idf->mode = PLAIN_MODE (type, len);
277 } else if (idf->external) {
278 idf->mode = PLAIN_MODE (type, len);
279 } else if (idf->mode.type == type && idf->mode.len == len) {
280 /* Let it pass */
281 } else {
282 ERROR (3111, "multiple definition", name);
283 }
284 }
285 return idf;
286 }
287 if (nlocals >= MAX_IDENTS) {
288 FATAL (3112, "too many identifiers", NO_TEXT);
289 return NO_IDENT;
290 }
291 idf = &locals[nlocals++];
292 memset (idf, 0, sizeof (IDENT));
293 idf->line = curlin;
294 C_NAME (idf) = c_name (name);
295 FTN_NAME (idf) = f_stralloc (name);
296 idf->arg = arg;
297 idf->common = blck;
298 idf->external = FALSE;
299 idf->mode = PLAIN_MODE (type, len);
300 idf->patch1 = apatch;
301 idf->source = src;
302 return idf;
303 }
304
305 IDENT *add_nest (char *name, int_4 nest, MODE *mode)
306 {
307 if (!IS_VAR (name)) {
308 ERROR (3113, "not a variable name", curlex);
309 return NO_IDENT;
310 }
311 if (nlocals >= MAX_IDENTS) {
312 FATAL (3114, "too many identifiers", NO_TEXT);
313 return NO_IDENT;
314 }
315 // Already declared? Take this mode.
316 IDENT *pre = find_local (name, mode);
317 //
318 IDENT *idf = &locals[nlocals++];
319 memset (idf, 0, sizeof (IDENT));
320 idf->line = curlin;
321 C_NAME (idf) = c_name (name);
322 FTN_NAME (idf) = f_stralloc (name);
323 idf->arg = NOARG;
324 idf->external = FALSE;
325 idf->common = 0;
326 idf->patch1 = NOPATCH;
327 idf->source = TEMP;
328 idf->nest = nest;
329 if (pre == NO_IDENT) {
330 impl_type (name, &idf->mode);
331 *mode = idf->mode;
332 } else {
333 *mode = pre->mode;
334 idf->mode = *mode;
335 }
336 return idf;
337 }
© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)
|