vif.c
1 //! @file vif.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 //! VIF driver.
25
26 #include <vif.h>
27
28 int_4 MAX_FTN_LINES;
29 FTN_LINE *source, *files;
30
31 int_4 MAX_C_SRC;
32 C_SRC *object;
33
34 IDENT globals[MAX_IDENTS];
35 IDENT locals[MAX_IDENTS];
36 char *commons[MAX_COMMONS];
37 IMPLICIT implic[26];
38 LBL labels[MAX_LABELS];
39
40 int_4 strlens[MAX_STRLENS];
41
42 int_4 curlin = 1, curcol = START_OF_LINE;
43 int_4 curret, preret;
44 int_4 end_statements;
45 int_4 func;
46 int_4 indent = 0;
47 int_4 line = 0;
48 int_4 ncommons = 2; // 0 means local, 1 external
49 int_4 n_c_src = 0;
50 int_4 nfiles = 0;
51 int_4 nftnlines = 1;
52 int_4 nglobals = 0;
53 int_4 nglobtmps = 0;
54 int_4 nlabels = 0;
55 int_4 nlocals = 0;
56 int_4 nloctmps = 0;
57 int_4 optimise = 0;
58 int_4 page = 0;
59 int_4 pcalls = 0;
60 int_4 pnprocs = -1, nprocs = 0;
61 int_4 prelin, precol;
62
63 logical_4 abend = FALSE;
64 logical_4 compile_only = FALSE;
65 logical_4 f4_do_loops = FALSE;
66 logical_4 frequency = FALSE;
67 logical_4 gcc_ftn_lines = TRUE;
68 logical_4 hollerith = FALSE;
69 logical_4 implicit_r8 = FALSE;
70 logical_4 keep = FALSE;
71 logical_4 load_go_erase = FALSE;
72 logical_4 load_go = FALSE;
73 logical_4 new_libnam = FALSE;
74 logical_4 new_object = FALSE;
75 logical_4 no_warnings = FALSE;
76 logical_4 pretty = FALSE;
77 logical_4 quiet_mode = FALSE;
78 logical_4 renum = FALSE;
79 logical_4 tidy = FALSE;
80 logical_4 syntax_only = FALSE;
81 logical_4 trace = FALSE;
82 logical_4 use_strcasecmp = FALSE;
83
84 RECORD hdate;
85 RECORD hmodule, hsection;
86 RECORD libnam, modnam, procnam;
87 RECORD object_name;
88 RECORD oflags;
89 RECORD prelex, curlex, retnam;
90 RECORD program, block;
91 RECORD stat_start;
92
93 logical_4 reserved (char *lex)
94 {
95 static char *words[] = {
96 "accept", "assign", "automatic", "backspace", "call", "character",
97 "close", "common", "complex", "continue", "decode", "dimension", "data",
98 "do", "double", "else", "elseif", "encode", "end", "enddo", "endfile",
99 "endif", "entry", "external", "format", "function", "go", "goto",
100 "if", "implicit", "integer", "intrinsic", "logical", "open",
101 "pause", "precision", "print", "program", "punch", "read", "real",
102 "repeat", "return", "rewind", "save", "subroutine", "stop", "then",
103 "to", "until", "while", "write", NO_TEXT
104 };
105 for (char **sym = words; *sym != NO_TEXT; sym++) {
106 if (EQUAL (*sym, lex)) {
107 return TRUE;
108 }
109 }
110 return FALSE;
111 }
112
113 logical_4 is_int4 (char *s, int_4 *val)
114 {
115 // Is 's' an integer denotation, and what is its value?
116 char *end;
117 int_4 k = strtol (s, &end, 10);
118 int_4 rc = (end != NO_TEXT && end[0] == '\0');
119 if (val != NO_REF_INTEGER && rc) {
120 *val = k;
121 }
122 return rc;
123 }
124
125 char *date (void)
126 {
127 time_t t;
128 struct tm *info;
129 t = time ((time_t *) NULL);
130 info = localtime (&t);
131 strftime (hdate, RECLN, "%a %d-%b-%Y %H:%M:%S", info);
132 return hdate;
133 }
134
135 char *date_fn (void)
136 {
137 time_t t;
138 struct tm *info;
139 t = time ((time_t *) NULL);
140 info = localtime (&t);
141 strftime (hdate, RECLN, "%Y-%m-%d-%H-%M-%S", info);
142 return hdate;
143 }
144
145 char *tod (void)
146 {
147 static RECORD str;
148 time_t t;
149 struct tm *info;
150 t = time ((time_t *) NULL);
151 info = localtime (&t);
152 strftime (str, RECLN, "%H:%M:%S", info);
153 return str;
154 }
155
156 void prelude (int_4 argc, char **argv, char *project)
157 {
158 {
159 NEW_RECORD (usr);
160 if (getlogin_r (usr, RECLN) == 0) {
161 code (0, HEADER, newpage (usr, basename (project)));
162 } else {
163 code (0, HEADER, newpage (VERSION, project));
164 }
165 code (0, HEADER, "\n");
166 if (getlogin_r (usr, RECLN) == 0) {
167 banner (0, BANNER, _strupper (usr));
168 code (0, BANNER, "\n");
169 }
170 banner (0, BANNER, _strupper (basename (project)));
171 code (0, BANNER, "\n");
172 }
173 code (0, CONSTANTS, newpage ("global-scope", "definitions"));
174 NEW_RECORD (str);
175 code (0, CONSTANTS, "/*\nGenerated by VIF - experimental VIntage Fortran compiler.\n");
176 _srecordf (str, "VIF release %s\n*/\n\n", VERSION);
177 code (0, CONSTANTS, str);
178 // Several pragmas to relax GCC for sloppy vintage FORTRAN type checking.
179 code (0, CONSTANTS, "#if defined (__GNUC__)\n");
180 code (0, CONSTANTS, " #pragma GCC diagnostic ignored \"-Wimplicit-function-declaration\"\n");
181 code (0, CONSTANTS, " #pragma GCC diagnostic ignored \"-Wincompatible-pointer-types\"\n");
182 code (0, CONSTANTS, " #if (__GNUC__ >= 14)\n");
183 code (0, CONSTANTS, " #pragma GCC diagnostic ignored \"-Wdeclaration-missing-parameter-type\"\n");
184 code (0, CONSTANTS, " #pragma GCC diagnostic ignored \"-Wimplicit-int\"\n");
185 code (0, CONSTANTS, " #pragma GCC diagnostic ignored \"-Wint-conversion\"\n");
186 code (0, CONSTANTS, " #pragma GCC diagnostic ignored \"-Wreturn-mismatch\"\n");
187 code (0, CONSTANTS, " #endif\n");
188 code (0, CONSTANTS, "#else\n");
189 code (0, CONSTANTS, " #error VIF requires GCC\n");
190 code (0, CONSTANTS, "#endif\n");
191 code (0, CONSTANTS, "\n");
192 code (0, CONSTANTS, "#include <vif.h>\n");
193 code (0, CONSTANTS, "\n");
194 code (0, CONSTANTS, "static int_4 _km1 = -1, _k0 = 0, _k1 = 1;\n");
195 code (0, CONSTANTS, "\n");
196 code (0, COMMON, "\n");
197 code (0, MESSAGES, newpage ("global-scope", "diagnostics"));
198 code (0, JCL, newpage ("global-scope", "job-control"));
199 code (0, TYPEDEF, newpage ("global-scope", "typedefs"));
200 code (0, TYPEDEF, "static FORMAT *__fmt_a = NULL;\n");
201 code (0, PROTOTYPE, newpage ("global-scope", "prototypes"));
202 code (0, FREQ, newpage ("global-scope", "frequency-table"));
203 code (0, FREQ, "#define __ncalls ");
204 pcalls = code (0, FREQ, NO_TEXT);
205 code (0, FREQ, "\n");
206 code (0, FREQ, "static CALLS __calls[__ncalls] = {\n");
207 }
208
209 void postlude (void)
210 {
211 NEW_RECORD (str);
212 code (0, PROTOTYPE, "\n");
213 code (0, FREQ, " {NULL , 0}\n");
214 _srecordf (str, "%d", nprocs + 1);
215 patch (pcalls, str);
216 code (0, FREQ, "};\n");
217 // Write the common blocks.
218 if (ncommons > EXTERN) {
219 code (0, COMMON, newpage ("global-scope", "common-blocks"));
220 code_common ();
221 }
222 // Define character array types encountered.
223 for (int k = 0, len = 2; k < MAX_STRLENS; k++, len *= 2) {
224 if (strlens[k]) {
225 _srecordf (str, "typedef char char_%d[%d];\n", len - 1, len);
226 code (0, TYPEDEF, str);
227 }
228 }
229 // Add an entry procedure.
230 if (! compile_only) {
231 nprocs++;
232 code (nprocs, BODY, newpage ("global-scope", "entry-point"));
233 code (nprocs, BODY, "// Global entry point.\n");
234 code (nprocs, BODY, "int_4 main (int_4 argc, char **argv)\n");
235 code (nprocs, BODY, "{\n");
236 code (nprocs, BODY, "_vif_init ();\n");
237 code (nprocs, BODY, "_ffile[0] = NEW_FTN_FILE (NULL, form_formatted, action_readwrite, 0);\n");
238 for (int k = 0; k < MAX_FILES; k++) {
239 if (_ffile[k].in_stream) {
240 _srecordf (str, "_ffile[%d].in_stream = TRUE;\n", k);
241 code (nprocs, BODY, str);
242 _srecordf (str, "_ffile[%d].action = action_read;\n", k);
243 code (nprocs, BODY, str);
244 _srecordf (str, "_ffile[%d].buff = _ffile[%d].rewind = f_stralloc (%s);\n", k, k, _ffile[k].name);
245 code (nprocs, BODY, str);
246 }
247 }
248 // SYSIN
249 if (! (_ffile[STDF_IN].in_stream || _ffile[STDF_IN].redirect)) {
250 _srecordf (str, "_ffile[%d] = NEW_FTN_FILE (stdin, form_formatted, action_read, MAX_LRECL);\n", STDF_IN);
251 code (nprocs, BODY, str);
252 _srecordf (str, "_ffile[%d].buff = (char *) f_malloc (MAX_LRECL + 1);\n", STDF_IN);
253 code (nprocs, BODY, str);
254 }
255 //SYSOUT
256 if (_ffile[STDF_OUT].in_stream) {
257 ERROR (3501, "standard output", "JCL in-stream is read only");
258 } else if (! _ffile[STDF_OUT].redirect) {
259 _srecordf (str, "_ffile[%d] = NEW_FTN_FILE (stdout, form_formatted, action_write, 0);\n", STDF_OUT);
260 code (nprocs, BODY, str);
261 }
262 //SYSPUNCH
263 #if STDF_OUT != STDF_PUN
264 if (_ffile[STDF_PUN].in_stream) {
265 ERROR (3502, "standard punch", "JCL in-stream is read only");
266 } else if (! _ffile[STDF_PUN].redirect) {
267 _srecordf (str, "_ffile[%d] = NEW_FTN_FILE (stdout, form_formatted, action_write, 0);\n", STDF_PUN);
268 code (nprocs, BODY, str);
269 }
270 #endif
271 // SYSERR
272 if (_ffile[STDF_ERR].in_stream) {
273 ERROR (3503, "standard error", "JCL in-stream is read only");
274 } else if (! _ffile[STDF_ERR].redirect) {
275 _srecordf (str, "_ffile[%d] = NEW_FTN_FILE (stdout, form_formatted, action_write, 0);\n", STDF_ERR);
276 code (nprocs, BODY, str);
277 }
278 //
279 if (strlen (block) > 0) {
280 NEW_RECORD (call);
281 _srecordf (call, "%s (); // Block data.\n", block);
282 code (nprocs, BODY, call);
283 }
284 if (strlen (program) > 0) {
285 NEW_RECORD (call);
286 _srecordf (call, "%s (); // Fortran entry point.\n", program);
287 code (nprocs, BODY, call);
288 }
289 if (frequency) {
290 code (nprocs, BODY, "_vif_freq (__calls);");
291 }
292 code (nprocs, BODY, "_vif_exit ();\n");
293 code (nprocs, BODY, "return EXIT_SUCCESS;\n");
294 code (nprocs, BODY, "}\n");
295 }
296 }
297
298 static void usage (void)
299 {
300 printf ("Usage: %s [-O][-f][-g][-k][-p][-v] file [, file, ...]\n", PACKAGE);
301 printf ("\n");
302 printf (" -c : Compile as a library.\n");
303 printf (" -d : FORTRAN IV style do loops.\n");
304 printf (" -f : Generate a call frequency table.\n");
305 printf (" -g : Execute upon successful compilation.\n");
306 printf (" -k : Backend compiler reports diagnostics at object code line.\n");
307 printf (" -l : Generate a verbose listing file.\n");
308 printf (" -o name: sets name for object file to `name.c' and for executable to `name'.\n");
309 printf (" -p : Keep the generated code upon successful compilation in pdf format.\n");
310 printf (" -q : Quiet mode.\n");
311 printf (" -r : Renumber FORTRAN source code.\n");
312 printf (" -s : Check syntax only.\n");
313 printf (" -t : Trace mode.\n");
314 printf (" -v : Print the version and exit.\n");
315 printf (" -w : Suppress warning diagnostics.\n");
316 printf (" -x : Execute upon successful compilation and erase executable.\n");
317 printf (" -y : Renumber FORTRAN source code and apply upper stropping.\n");
318 printf (" -z : Set default REAL length to 8 and default COMPLEX length to 16.\n");
319 printf (" -O0 : Do not optimize the object code.\n");
320 printf (" -O : Optimize the object code.\n");
321 printf (" -O1 : Optimize the object code.\n");
322 printf (" -O2 : Optimize the object code.\n");
323 printf (" -O3 : Optimize the object code.\n");
324 printf (" -Of : Optimize the object code.\n");
325 }
326
327 void version (void)
328 {
329 printf ("VIF %s - experimental VIntage Fortran compiler.\n", VERSION);
330 printf ("Copyright 2020-2025 J.M. van der Veer.\n\n");
331 printf ("Backend compiler : %s\n", BACKEND);
332 printf ("Install directory: %s\n\n", LOCDIR);
333 printf ("This is free software covered by the GNU General Public License.\n");
334 printf ("There is ABSOLUTELY NO WARRANTY for VIF;\n");
335 printf ("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
336 printf ("See the GNU General Public License for more details.\n");
337 }
338
339 #define OPTION(s) EQUAL (opt, (s))
340
341 void option (char *opt)
342 {
343 if (OPTION ("--frequency")) {
344 frequency = TRUE;
345 } else if (OPTION ("--go")) {
346 load_go = TRUE;
347 } else if (OPTION ("--keep")) {
348 keep = TRUE;
349 } else if (OPTION ("--lib")) {
350 new_libnam = TRUE;
351 } else if (OPTION ("--pdf")) {
352 keep = TRUE;
353 pretty = TRUE;
354 } else if (OPTION ("--f4-do-loops")) {
355 f4_do_loops = TRUE;
356 } else if (OPTION ("--renumber")) {
357 renum = TRUE;
358 } else if (OPTION ("--tidy")) {
359 renum = TRUE;
360 tidy = TRUE;
361 } else if (OPTION ("--hollerith")) {
362 hollerith = TRUE;
363 } else if (OPTION ("--license")) {
364 version ();
365 exit (EXIT_SUCCESS);
366 } else if (OPTION ("--version")) {
367 version ();
368 exit (EXIT_SUCCESS);
369 } else if (opt[1] == '-' && opt[2] == '\0') {
370 return;
371 } else for (int_4 k = 1; opt[k] != '\0'; k++) {
372 if (opt[k] == 'O') {
373 optimise = 0;
374 if (opt[k + 1] == '0') {
375 _srecordf(oflags, "%s", "-O0 -ggdb");
376 k++;
377 } else if (opt[k + 1] == '1') {
378 _srecordf(oflags, "%s", "-O1");
379 optimise = 1;
380 k++;
381 } else if (opt[k + 1] == '2') {
382 _srecordf(oflags, "%s", "-O2");
383 optimise = 2;
384 k++;
385 } else if (opt[k + 1] == '3') {
386 _srecordf(oflags, "%s", "-funroll-all-loops -O3");
387 optimise = 3;
388 k++;
389 } else if (opt[k + 1] == 'f') {
390 _srecordf(oflags, "%s", "-Ofast");
391 optimise = 4;
392 k++;
393 } else {
394 _srecordf(oflags, "%s", "-O");
395 optimise = 1;
396 }
397 } else if (opt[k] == 'c') {
398 compile_only = TRUE;
399 } else if (opt[k] == 'd') {
400 f4_do_loops = TRUE;
401 } else if (opt[k] == 'f') {
402 frequency = TRUE;
403 } else if (opt[k] == 'g') {
404 load_go = TRUE;
405 } else if (opt[k] == 'k') {
406 gcc_ftn_lines = FALSE;
407 } else if (opt[k] == 'l') {
408 keep = TRUE;
409 } else if (opt[k] == 'o') {
410 new_object = TRUE;
411 } else if (opt[k] == 'p') {
412 keep = TRUE;
413 pretty = TRUE;
414 } else if (opt[k] == 'q') {
415 quiet_mode = TRUE;
416 } else if (opt[k] == 'r') {
417 renum = TRUE;
418 } else if (opt[k] == 's') {
419 syntax_only = TRUE;
420 } else if (opt[k] == 't') {
421 trace = TRUE;
422 } else if (opt[k] == 'u') {
423 use_strcasecmp = TRUE;
424 } else if (opt[k] == 'v') {
425 version ();
426 exit (EXIT_SUCCESS);
427 } else if (opt[k] == 'w') {
428 no_warnings = TRUE;
429 } else if (opt[k] == 'x') {
430 load_go = TRUE;
431 load_go_erase = TRUE;
432 } else if (opt[k] == 'y') {
433 renum = TRUE;
434 tidy = TRUE;
435 } else if (opt[k] == 'z') {
436 implicit_r8 = TRUE;
437 } else {
438 usage ();
439 exit (EXIT_FAILURE);
440 }
441 }
442 }
443
444 #undef OPTION
445
446 static void post_edit (char *c_file)
447 {
448 NEW_RECORD (cmd);
449 NEW_RECORD (tmp);
450 _srecordf (tmp, "%s~", c_file);
451 _sys (cmd, "sed", NO_TEXT, "-i '/^\\/\\//d' %s", c_file);
452 _sys (cmd, "sed", NO_TEXT, "-i 's/^\\f//' %s", c_file);
453 // _sys (cmd, "sed", NO_TEXT, "-i '/^# line /d' %s", c_file);
454 _sys (cmd, "sed", NO_TEXT, "-i '/^[[:space:]]*$/d' %s", c_file);
455 if (nerrors == 0) {
456 _sys (cmd, "indent", NO_TEXT, "%s -l500 -br -ce -cdw -nfca -npsl -nut -i2 -nbad -cs -pcs -sob", c_file);
457 _sys (cmd, "sed", NO_TEXT, "-i 's/\\(\\.[0-9][0-9]*\\) q/\\1q/' %s", c_file);
458 // _sys (cmd, "fold", NO_TEXT, "-w 100 -s %s > %s", c_file, tmp);
459 _sys (cmd, "mv", NO_TEXT, "%s %s", tmp, c_file);
460 _sys (cmd, "sed", NO_TEXT, "-i 's/^}$/}\\n/' %s", c_file);
461 _sys (cmd, "sed", NO_TEXT, "-i 's/^};$/};\\n/' %s", c_file);
462 }
463 _sys (cmd, "rm", NO_TEXT, "-f %s", tmp);
464 }
465
466 int_4 main (int_4 argc, char **argv)
467 {
468 int_4 rc = EXIT_SUCCESS, start = 1;
469 NEW_RECORD (c_file);
470 NEW_RECORD (f_file);
471 NEW_RECORD (lst_file);
472 NEW_RECORD (cmd);
473 //
474 MAX_FTN_LINES = INCREMENT;
475 MAX_C_SRC = INCREMENT;
476 source = (FTN_LINE *) f_malloc (MAX_FTN_LINES * sizeof (FTN_LINE));
477 object = (C_SRC *) f_malloc (MAX_C_SRC * sizeof (C_SRC));
478 files = (FTN_LINE *) f_malloc (MAX_SOURCE_FILES * sizeof (FTN_LINE));
479 memset (_ffile, 0, sizeof (_ffile));
480 // Options
481 f4_do_loops = FALSE;
482 new_libnam = FALSE;
483 new_object = FALSE;
484 oflags[0] = '\0';
485 RECCLR (libnam);
486 RECCLR (object_name);
487 while (argv[start] != NO_TEXT && argv[start][0] == '-') {
488 option (argv[start]);
489 start++;
490 if (new_libnam) {
491 new_libnam = FALSE;
492 if (strlen (libnam) == 0 && argv[start] != NO_TEXT) {
493 RECCPY (libnam, argv[start]);
494 start++;
495 } else {
496 usage ();
497 exit (EXIT_FAILURE);
498 }
499 } else if (new_object) {
500 new_object = FALSE;
501 if (strlen (object_name) == 0 && argv[start] != NO_TEXT) {
502 RECCPY (object_name, argv[start]);
503 start++;
504 } else {
505 usage ();
506 exit (EXIT_FAILURE);
507 }
508 }
509 }
510 if (argv[start] == NO_TEXT) {
511 usage ();
512 exit (EXIT_FAILURE);
513 }
514 RECCLR (program);
515 RECCLR (block);
516 RECCLR (curlex);
517 RECCLR (prelex);
518 for (int_4 k = 0; k < MAX_STRLENS; k++) {
519 strlens[k] = FALSE;
520 }
521 date ();
522 RECCPY (hmodule, "global-scope");
523 RECCPY (hsection, "global-section");
524 // Import all sources.
525 NEW_RECORD (argv_start);
526 _srecordf (argv_start, argv[start]);
527 for (int k = start; k < argc; k++) {
528 get_source (f_stralloc (argv[k]), 0);
529 }
530 // Name for project derives from first source file.
531 if (strlen (libnam) == 0) {
532 if (new_object) {
533 RECCPY (libnam, object_name);
534 } else {
535 RECCPY (libnam, argv_start);
536 }
537 for (int k = (int_4) strlen (libnam); k >= 0; k--) {
538 if (libnam[k] == '.') {
539 libnam[k] = '\0';
540 break;
541 }
542 }
543 }
544 // Fill in what we know at the start.
545 prelude (argc, argv, libnam);
546 // Compile all subprograms.
547 nmodules = 0;
548 curlin = 1;
549 curcol = START_OF_LINE;
550 jcllin = 0;
551 scan_modules ();
552 curlin = 1;
553 curcol = START_OF_LINE;
554 macro_nest = 0;
555 lhs_factor = FALSE;
556 subprograms ();
557 // Fill in what we know afterwards, and write C source.
558 postlude ();
559 // Remove stale files.
560 RECCLR (c_file);
561 _srecordf (c_file, "%s.c", libnam);
562 _srecordf (f_file, "%s.f~", libnam);
563 _srecordf (lst_file, "%s.l", libnam);
564 //
565 write_object (c_file);
566 // Compile intermediate code.
567 if (syntax_only) {
568 NEW_RECORD (str);
569 _srecordf (str, "** linker ** no object file generated");
570 diagnostic (0, str);
571 if (nerrors == 0) {
572 rc = EXIT_SUCCESS;
573 } else {
574 rc = EXIT_FAILURE;
575 }
576 } else if (nerrors != 0) {
577 NEW_RECORD (str);
578 nerrors++;
579 _srecordf (str, "** linker ** no object file generated");
580 diagnostic (0, str);
581 rc = EXIT_FAILURE;
582 } else {
583 NEW_RECORD (str);
584 if (compile_only) {
585 if (optimise > 0) {
586 rc = _sys (cmd, BACKEND, NO_TEXT, "%s %s -c %s.c -o %s.o", oflags, CFLAGS, libnam, libnam);
587 } else {
588 rc = _sys (cmd, BACKEND, NO_TEXT, "-O0 -ggdb %s -c %s.c -o %s.o", CFLAGS, libnam, libnam);
589 }
590 } else {
591 if (optimise > 0) {
592 #if defined (BOOTSTRAP)
593 rc = _sys (cmd, BACKEND, NO_TEXT, "%s %s %s.c -o %s %s", oflags, CFLAGS, libnam, libnam, LD_FLAGS);
594 #else
595 rc = _sys (cmd, BACKEND, NO_TEXT, "%s %s %s.c -o %s -L%s %s", oflags, CFLAGS, libnam, libnam, LOCDIR, LD_FLAGS);
596 #endif
597 } else {
598 #if defined (BOOTSTRAP)
599 rc = _sys (cmd, BACKEND, NO_TEXT, "-O0 -ggdb %s %s.c -o %s %s", CFLAGS, libnam, libnam, LD_FLAGS);
600 #else
601 rc = _sys (cmd, BACKEND, NO_TEXT, "-O0 -ggdb %s %s.c -o %s -L%s %s", CFLAGS, libnam, libnam, LOCDIR, LD_FLAGS);
602 #endif
603 }
604 }
605 if (rc == EXIT_SUCCESS) {
606 struct stat s;
607 if (compile_only) {
608 NEW_RECORD (obj);
609 _srecordf (obj, "%s.o", libnam);
610 stat (obj, &s);
611 } else {
612 stat (libnam, &s);
613 }
614 _srecordf (str, "** linker ** object size %ld bytes", s.st_size);
615 diagnostic (0, str);
616 } else {
617 nerrors++;
618 _srecordf (str, "** linker ** no object file generated");
619 diagnostic (0, str);
620 rc = EXIT_FAILURE;
621 }
622 _sys (cmd, "cp", NO_TEXT, "%s %s", c_file, lst_file);
623 }
624 // Wrap it up
625 {
626 NEW_RECORD (str);
627 NEW_RECORD (sub);
628 NEW_RECORD (err);
629 NEW_RECORD (war);
630 // if (nprocs > 0 && ! compile_only) {
631 // nprocs--; // discount 'main'
632 // }
633 if (nprocs == 0) {
634 _srecordf (sub, "no subprograms");
635 } else if (nprocs == 1) {
636 _srecordf (sub, "1 subprogram");
637 } else {
638 _srecordf (sub, "%d subprograms", nprocs);
639 }
640 if (nerrors == 0) {
641 _srecordf (err, "no errors");
642 } else if (nerrors == 1) {
643 _srecordf (err, "1 error");
644 } else {
645 _srecordf (err, "%d errors", nerrors);
646 }
647 if (nwarns == 0) {
648 _srecordf (war, "no warnings");
649 } else if (nwarns == 1) {
650 _srecordf (war, "1 warning");
651 } else {
652 _srecordf (war, "%d warnings", nwarns);
653 }
654 _srecordf (str, "** statistics ** %s, %s, %s", sub, err, war);
655 diagnostic (0, str);
656 }
657 // Execution.
658 if (!renum && load_go && nerrors == 0 && ! syntax_only) {
659 fprintf (stderr, "** execution **\n");
660 NEW_RECORD (exec);
661 if (libnam[0] == '/') {
662 _srecordf (exec, "%s | tee %s.%s.%s", libnam, libnam, date_fn (), PACKAGE);
663 } else {
664 _srecordf (exec, "./%s | tee %s.%s.%s", libnam, libnam, date_fn (), PACKAGE);
665 }
666 rc = _sys (cmd, exec, NO_TEXT, NO_TEXT);
667 if (load_go_erase) {
668 _sys (cmd, "rm", NO_TEXT, "-f ./%s", exec);
669 }
670 }
671 // Write C source again with post-compile information.
672 remove (c_file);
673 write_object (c_file);
674 _sys (cmd, "cp", NO_TEXT, "%s %s", c_file, lst_file);
675 post_edit (c_file);
676 // Write tidied fortran file.
677 if (renum) {
678 write_tidy (f_file);
679 }
680 // Pretty listing file as PDF.
681 if (keep && pretty) {
682 NEW_RECORD (tmp);
683 _srecordf (tmp, "./.vif_pdf");
684 _sys (cmd, "enscript", "ps2pdf", "--quiet --font=Courier-Bold@9 -l -H1 -r --margins=25:25:40:40 -p - %s > %s", c_file, tmp);
685 _sys (cmd, "ps2pdf", "enscript", "%s %s.pdf", tmp, libnam);
686 _sys (cmd, "rm", NO_TEXT, "-f %s", tmp);
687 }
688 if (!keep) {
689 _sys (cmd, "rm", NO_TEXT, "-f %s.s", libnam);
690 }
691 // Exeunt.
692 exit (rc);
693 }
© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)
|