type.c
1 //! @file type.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 //! Type routines.
25
26 #include <vif.h>
27
28 void compute_row_size (RECORD buf, IDENT *idf)
29 {
30 RECORD str;
31 RECCLR (str);
32 for (int_4 n = 0; n < idf->mode.dim; n++) {
33 if (EQUAL (idf->len[n], "VARY")) {
34 _srecordf (buf, "VARY");
35 return;
36 } else {
37 fold_int_4 (buf, idf->len[n]);
38 }
39 if (isint_4 (buf, NO_REF_INTEGER)) {
40 bufcat (str, buf, RECLN);
41 } else {
42 bufcat (str,"(", RECLN);
43 bufcat (str, buf, RECLN);
44 bufcat (str,")", RECLN);
45 }
46 if (n < idf->mode.dim - 1) {
47 bufcat (str, " * ", RECLN);
48 }
49 }
50 fold_int_4 (buf, str);
51 }
52
53 void norm_mode (MODE *mode)
54 {
55 if (mode != NO_MODE && mode->type == CHARACTER) {
56 if (mode->len == 0) {
57 // CHARACTER*(*)
58 return;
59 }
60 for (int k = 0, lim = 2; k < MAX_STRLENS; k++, lim *= 2) {
61 if (mode->len < lim) {
62 strlens[k] = TRUE;
63 mode->len = lim - 1;
64 return;
65 }
66 }
67 RECORD str;
68 _srecordf (str, "%d", mode->len);
69 ERROR (3101, "character length overflow", str);
70 mode->len = MAX_STRLEN;
71 }
72 }
73
74 void default_impl (void)
75 {
76 int_4 k;
77 for (k = ord ('a'); k <= ord ('h'); k++) {
78 if (implicit_r8) {
79 f2c_type ("real*8", &(implic[k].mode), NOARG, NOFUN);
80 } else {
81 f2c_type ("real*4", &(implic[k].mode), NOARG, NOFUN);
82 }
83 implic[k].mode.save = STATIC;
84 }
85 for (k = ord ('i'); k <= ord ('n'); k++) {
86 f2c_type ("integer*4", &(implic[k].mode), NOARG, NOFUN);
87 implic[k].mode.save = STATIC;
88 }
89 for (k = ord ('o'); k <= ord ('z'); k++) {
90 if (implicit_r8) {
91 f2c_type ("real*8", &(implic[k].mode), NOARG, NOFUN);
92 } else {
93 f2c_type ("real*4", &(implic[k].mode), NOARG, NOFUN);
94 }
95 implic[k].mode.save = STATIC;
96 }
97 implic[k].mode.save = STATIC;
98 }
99
100 char *qtype (MODE * mode)
101 {
102 RECORD t;
103 RECCLR (t);
104 if (mode->type == NOTYPE) {
105 _srecordf (t, "%s", "void");
106 } else if (mode->type == ETYPE) {
107 _srecordf (t, "%s", "type error");
108 } else if (mode->len > 0) {
109 switch (mode->type) {
110 case INTEGER:
111 _srecordf (t, "%s*%d", "integer", mode->len);
112 break;
113 case LOGICAL:
114 _srecordf (t, "%s*%d", "logical", mode->len);
115 break;
116 case REAL:
117 _srecordf (t, "%s*%d", "real", mode->len);
118 break;
119 case COMPLEX:
120 _srecordf (t, "%s*%d", "complex", mode->len);
121 break;
122 case CHARACTER:
123 _srecordf (t, "%s*%d", "character", mode->len);
124 break;
125 }
126 } else {
127 switch (mode->type) {
128 case INTEGER:
129 _srecordf (t, "%s", "integer");
130 break;
131 case LOGICAL:
132 _srecordf (t, "%s", "logical");
133 break;
134 case REAL:
135 _srecordf (t, "%s", "real");
136 break;
137 case COMPLEX:
138 _srecordf (t, "%s", "complex");
139 break;
140 case CHARACTER:
141 _srecordf (t, "%s", "character");
142 break;
143 }
144 }
145 return f_stralloc (t);
146 }
147
148 char *wtype (MODE * mode, int_4 arg, int_4 fun)
149 {
150 switch (mode->type) {
151 case INTEGER:{
152 if (mode->len == 2) {
153 return (arg ? "int_2 _p_ " : "int_2");
154 } else if (mode->len == 4) {
155 return (arg ? "int_4 _p_ " : "int_4");
156 } else if (mode->len == 8) {
157 return (arg ? "int_8 _p_ " : "int_8");
158 } else {
159 return "notype";
160 }
161 }
162 case LOGICAL:
163 if (arg) {
164 return "logical_4 _p_ ";
165 } else {
166 return "logical_4";
167 }
168 case REAL:
169 if (mode->len == 4) {
170 return (arg ? "real_4 _p_ " : "real_4");
171 } else if (mode->len == 8) {
172 return (arg ? "real_8 _p_ " : "real_8");
173 } else if (mode->len == 16) {
174 return (arg ? "real_16 _p_ " : "real_16");
175 } else if (mode->len == 32) {
176 return (arg ? "real_32 _p_ " : "real_32");
177 } else {
178 return "notype";
179 }
180 case COMPLEX:
181 if (mode->len == 8) {
182 return (arg ? "complex_8 _p_ " : "complex_8");
183 } else if (mode->len == 16) {
184 return (arg ? "complex_16 _p_ " : "complex_16");
185 } else if (mode->len == 32) {
186 return (arg ? "complex_32 _p_ " : "complex_32");
187 } else if (mode->len == 64) {
188 return (arg ? "complex_64 _p_ " : "complex_64");
189 } else {
190 return "notype";
191 }
192 case CHARACTER:{
193 if (fun || arg) {
194 return "char _p_ ";
195 } else {
196 RECORD str;
197 _srecordf (str, "char_%d", mode->len);
198 return f_stralloc (str);
199 }
200 }
201 case NOTYPE: { // C routine type
202 return "int_4";
203 }
204 default: {
205 return "notype";
206 }
207 }
208 }
209
210 char *f2c_type (char *ftype, MODE * mode, int_4 arg, int_4 fun)
211 {
212 MODE m = (MODE) {.type = NOTYPE,.len = NOLEN,.dim = 0 };
213 int_4 found = FALSE;
214 #define TEST(name, f_type, f_len, f_trunc)\
215 if (EQUAL (ftype, name)) {\
216 m = (MODE) {.type = f_type, .len = f_trunc, .dim = 0};\
217 found = TRUE;\
218 }
219 TEST ("none", NOTYPE, 0, 0);
220 TEST ("logical", LOGICAL, 4, 4);
221 TEST ("logical*1", LOGICAL, 1, 4);
222 TEST ("logical*2", LOGICAL, 2, 4);
223 TEST ("logical*4", LOGICAL, 4, 4);
224 TEST ("logical*8", LOGICAL, 8, 4);
225 TEST ("integer", INTEGER, 4, 4);
226 TEST ("integer*1", INTEGER, 2, 2);
227 TEST ("integer*2", INTEGER, 2, 2);
228 TEST ("integer*4", INTEGER, 4, 4);
229 TEST ("integer*8", INTEGER, 8, 8);
230 if (implicit_r8) {
231 TEST ("real", REAL, 8, 8);
232 } else {
233 TEST ("real", REAL, 4, 4);
234 }
235 TEST ("real*4", REAL, 4, 4);
236 TEST ("real*8", REAL, 8, 8);
237 TEST ("real*16", REAL, 16, 16);
238 TEST ("real*32", REAL, 32, 32);
239 if (implicit_r8) {
240 TEST ("complex", COMPLEX, 16, 16);
241 } else {
242 TEST ("complex", COMPLEX, 8, 8);
243 }
244 TEST ("complex*8", COMPLEX, 8, 8);
245 TEST ("complex*16", COMPLEX, 16, 16);
246 TEST ("complex*32", COMPLEX, 32, 32);
247 TEST ("complex*64", COMPLEX, 64, 64);
248 TEST ("character", CHARACTER, 1, 1);
249 if (LEQUAL ("character*", ftype)) {
250 int_4 len;
251 if (strcmp (ftype, "character*(*)") == 0) {
252 m = (MODE) {.type = CHARACTER, .len = 0, .dim = 0};
253 found = TRUE;
254 } else {
255 char *op = strchr (ftype, '('), *cl = strrchr(ftype, ')');
256 if (op != NO_TEXT && cl != NO_TEXT) {
257 RECORD fact;
258 _srecordf (fact, "%s", ++op);
259 if (strlen (fact) > 0 && fact[strlen (fact) - 1] == ')') {
260 fact[strlen (fact) - 1] = '\0';
261 }
262 if (!isint_4 (fact, &len)) {
263 MODE pm;
264 IDENT *idf = find_local (fact, &pm);
265 if (idf->parm != NO_TEXT && idf->mode.type == INTEGER) {
266 (void) isint_4 (idf->parm, &len);
267 } else {
268 ERROR (3102, "invalid length", fact);
269 len = MAX_STRLEN;
270 }
271 }
272 } else {
273 sscanf (ftype, "character*%d", &len);
274 }
275 m = (MODE) {.type = CHARACTER, .len = len, .dim = 0};
276 found = TRUE;
277 }
278 if (found && m.len > 1) {
279 norm_mode (&m);
280 }
281 }
282 if (mode != NO_MODE) {
283 *mode = m;
284 }
285 if (found) {
286 return (wtype (&m, arg, fun));
287 } else {
288 ERROR (3103, "unknown type", ftype);
289 return "notype";
290 }
291 }
292
293 char *ptr_to_array (IDENT * idf, int_4 constant, int_4 cast, int_4 formal)
294 {
295 RECORD str, name;
296 if (formal) {
297 _srecordf (name, "%s", edit_f (C_NAME (idf)));
298 } else {
299 _srecordf (name, "%s", C_NAME (idf));
300 }
301 if (idf->mode.dim <= 1) {
302 if (cast) {
303 _srecordf (str, "(%s _p_)", wtype (&idf->mode, NOARG, NOFUN));
304 } else if (constant) {
305 _srecordf (str, "_p_ const %s", name);
306 } else {
307 _srecordf (str, "_p_ %s", name);
308 }
309 } else {
310 if (cast) {
311 _srecordf (str, "(%s (_p_)", wtype (&idf->mode, NOARG, NOFUN));
312 } else if (constant) {
313 _srecordf (str, "(_p_ const %s)", name);
314 } else {
315 _srecordf (str, "(_p_ %s)", name);
316 }
317 if (cast) {
318 bufcat (str, ")", RECLN);
319 }
320 }
321 return f_stralloc (str);
322 }
323
324 int_4 accept_mode (int_4 Lt, int_4 Ll, int_4 Rt, int_4 Rl)
325 {
326 // Whether L is acceptable to R.
327 if (Rt == REAL && Lt == REAL) {
328 return Ll <= Rl;
329 }
330 if (Rt == INTEGER && Lt == INTEGER) {
331 return Ll <= Rl;
332 }
333 if (Rt == LOGICAL && Lt == LOGICAL) {
334 return Ll <= Rl;
335 }
336 if (Rt == REAL && Lt == INTEGER) {
337 return Ll <= Rl;
338 }
339 if (Rt == COMPLEX && Lt == REAL) {
340 return 2 * Ll <= Rl;
341 }
342 if (Rt == COMPLEX && Lt == INTEGER) {
343 return 2 * Ll <= Rl;
344 }
345 if (Rt == INTEGER && Lt == CHARACTER) {
346 return Rl == 4;
347 }
348 if (Rt == INTEGER && Lt == REAL) {
349 return FALSE;
350 }
351 // Generic cases.
352 if (Rt == NOTYPE) {
353 return TRUE;
354 } else if (Lt != Rt) {
355 return FALSE;
356 } else if (Rl == NOLEN) {
357 return TRUE;
358 }
359 return Ll <= Rl;
360 }
361
© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)
|