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