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
179 code (0, CONSTANTS, "#include <vif.h>\n");
180 code (0, CONSTANTS, "\n");
181 code (0, CONSTANTS, "static int_4 _km1 = -1, _k0 = 0, _k1 = 1;\n");
182 code (0, CONSTANTS, "\n");
183 code (0, COMMON, "\n");
184 code (0, MESSAGES, newpage ("global-scope", "diagnostics"));
185 code (0, JCL, newpage ("global-scope", "job-control"));
186 code (0, TYPEDEF, newpage ("global-scope", "typedefs"));
187 code (0, TYPEDEF, "static FORMAT *__fmt_a = NULL;\n");
188 code (0, PROTOTYPE, newpage ("global-scope", "prototypes"));
189 code (0, FREQ, newpage ("global-scope", "frequency-table"));
190 code (0, FREQ, "#define __ncalls ");
191 pcalls = code (0, FREQ, NO_TEXT);
192 code (0, FREQ, "\n");
193 code (0, FREQ, "static CALLS __calls[__ncalls] = {\n");
194 }
195
196 void postlude (void)
197 {
198 NEW_RECORD (str);
199 code (0, PROTOTYPE, "\n");
200 code (0, FREQ, " {NULL , 0}\n");
201 _srecordf (str, "%d", nprocs + 1);
202 patch (pcalls, str);
203 code (0, FREQ, "};\n");
204 // Write the common blocks.
205 if (ncommons > EXTERN) {
206 code (0, COMMON, newpage ("global-scope", "common-blocks"));
207 code_common ();
208 }
209 // Define character array types encountered.
210 for (int k = 0, len = 2; k < MAX_STRLENS; k++, len *= 2) {
211 if (strlens[k]) {
212 _srecordf (str, "typedef char char_%d[%d];\n", len - 1, len);
213 code (0, TYPEDEF, str);
214 }
215 }
216 // Add an entry procedure.
217 if (! compile_only) {
218 nprocs++;
219 code (nprocs, BODY, newpage ("global-scope", "entry-point"));
220 code (nprocs, BODY, "// Global entry point.\n");
221 code (nprocs, BODY, "int_4 main (int_4 argc, char **argv)\n");
222 code (nprocs, BODY, "{\n");
223 code (nprocs, BODY, "_vif_init ();\n");
224 code (nprocs, BODY, "_ffile[0] = NEW_FTN_FILE (NULL, form_formatted, action_readwrite, 0);\n");
225 for (int k = 0; k < MAX_FILES; k++) {
226 if (_ffile[k].in_stream) {
227 _srecordf (str, "_ffile[%d].in_stream = TRUE;\n", k);
228 code (nprocs, BODY, str);
229 _srecordf (str, "_ffile[%d].action = action_read;\n", k);
230 code (nprocs, BODY, str);
231 _srecordf (str, "_ffile[%d].buff = _ffile[%d].rewind = f_stralloc (%s);\n", k, k, _ffile[k].name);
232 code (nprocs, BODY, str);
233 }
234 }
235 // SYSIN
236 if (! (_ffile[STDF_IN].in_stream || _ffile[STDF_IN].redirect)) {
237 _srecordf (str, "_ffile[%d] = NEW_FTN_FILE (stdin, form_formatted, action_read, MAX_LRECL);\n", STDF_IN);
238 code (nprocs, BODY, str);
239 _srecordf (str, "_ffile[%d].buff = (char *) f_malloc (MAX_LRECL + 1);\n", STDF_IN);
240 code (nprocs, BODY, str);
241 }
242 //SYSOUT
243 if (_ffile[STDF_OUT].in_stream) {
244 ERROR (3501, "standard output", "JCL in-stream is read only");
245 } else if (! _ffile[STDF_OUT].redirect) {
246 _srecordf (str, "_ffile[%d] = NEW_FTN_FILE (stdout, form_formatted, action_write, 0);\n", STDF_OUT);
247 code (nprocs, BODY, str);
248 }
249 //SYSPUNCH
250 #if STDF_OUT != STDF_PUN
251 if (_ffile[STDF_PUN].in_stream) {
252 ERROR (3502, "standard punch", "JCL in-stream is read only");
253 } else if (! _ffile[STDF_PUN].redirect) {
254 _srecordf (str, "_ffile[%d] = NEW_FTN_FILE (stdout, form_formatted, action_write, 0);\n", STDF_PUN);
255 code (nprocs, BODY, str);
256 }
257 #endif
258 // SYSERR
259 if (_ffile[STDF_ERR].in_stream) {
260 ERROR (3503, "standard error", "JCL in-stream is read only");
261 } else if (! _ffile[STDF_ERR].redirect) {
262 _srecordf (str, "_ffile[%d] = NEW_FTN_FILE (stdout, form_formatted, action_write, 0);\n", STDF_ERR);
263 code (nprocs, BODY, str);
264 }
265 //
266 if (strlen (block) > 0) {
267 NEW_RECORD (call);
268 _srecordf (call, "%s (); // Block data.\n", block);
269 code (nprocs, BODY, call);
270 }
271 if (strlen (program) > 0) {
272 NEW_RECORD (call);
273 _srecordf (call, "%s (); // Fortran entry point.\n", program);
274 code (nprocs, BODY, call);
275 }
276 if (frequency) {
277 code (nprocs, BODY, "_vif_freq (__calls);");
278 }
279 code (nprocs, BODY, "_vif_exit ();\n");
280 code (nprocs, BODY, "return EXIT_SUCCESS;\n");
281 code (nprocs, BODY, "}\n");
282 }
283 }
284
285 static void usage (void)
286 {
287 printf ("Usage: %s [-O][-f][-g][-k][-p][-v] file [, file, ...]\n", PACKAGE);
288 printf ("\n");
289 printf (" -c : Compile as a library.\n");
290 printf (" -d : FORTRAN IV style do loops.\n");
291 printf (" -f : Generate a call frequency table.\n");
292 printf (" -g : Execute upon successful compilation.\n");
293 printf (" -k : Backend compiler reports diagnostics at object code line.\n");
294 printf (" -l : Generate a verbose listing file.\n");
295 printf (" -o name: sets name for object file to `name.c' and for executable to `name'.\n");
296 printf (" -p : Keep the generated code upon successful compilation in pdf format.\n");
297 printf (" -q : Quiet mode.\n");
298 printf (" -r : Renumber FORTRAN source code.\n");
299 printf (" -s : Check syntax only.\n");
300 printf (" -t : Trace mode.\n");
301 printf (" -v : Print the version and exit.\n");
302 printf (" -w : Suppress warning diagnostics.\n");
303 printf (" -x : Execute upon successful compilation and erase executable.\n");
304 printf (" -y : Renumber FORTRAN source code and apply upper stropping.\n");
305 printf (" -z : Set default REAL length to 8 and default COMPLEX length to 16.\n");
306 printf (" -O0 : Do not optimize the object code.\n");
307 printf (" -O : Optimize the object code.\n");
308 printf (" -O1 : Optimize the object code.\n");
309 printf (" -O2 : Optimize the object code.\n");
310 printf (" -O3 : Optimize the object code.\n");
311 printf (" -Of : Optimize the object code.\n");
312 }
313
314 void version (void)
315 {
316 printf ("VIF %s - experimental VIntage Fortran compiler.\n", VERSION);
317 printf ("Copyright 2020-2025 J.M. van der Veer.\n\n");
318 printf ("Backend compiler : %s\n", BACKEND);
319 printf ("Install directory: %s\n\n", LOCDIR);
320 printf ("This is free software covered by the GNU General Public License.\n");
321 printf ("There is ABSOLUTELY NO WARRANTY for VIF;\n");
322 printf ("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
323 printf ("See the GNU General Public License for more details.\n");
324 }
325
326 #define OPTION(s) EQUAL (opt, (s))
327
328 void option (char *opt)
329 {
330 if (OPTION ("--frequency")) {
331 frequency = TRUE;
332 } else if (OPTION ("--go")) {
333 load_go = TRUE;
334 } else if (OPTION ("--keep")) {
335 keep = TRUE;
336 } else if (OPTION ("--lib")) {
337 new_libnam = TRUE;
338 } else if (OPTION ("--pdf")) {
339 keep = TRUE;
340 pretty = TRUE;
341 } else if (OPTION ("--f4-do-loops")) {
342 f4_do_loops = TRUE;
343 } else if (OPTION ("--renumber")) {
344 renum = TRUE;
345 } else if (OPTION ("--tidy")) {
346 renum = TRUE;
347 tidy = TRUE;
348 } else if (OPTION ("--hollerith")) {
349 hollerith = TRUE;
350 } else if (OPTION ("--license")) {
351 version ();
352 exit (EXIT_SUCCESS);
353 } else if (OPTION ("--version")) {
354 version ();
355 exit (EXIT_SUCCESS);
356 } else if (opt[1] == '-' && opt[2] == '\0') {
357 return;
358 } else for (int_4 k = 1; opt[k] != '\0'; k++) {
359 if (opt[k] == 'O') {
360 optimise = 0;
361 if (opt[k + 1] == '0') {
362 _srecordf(oflags, "%s", "-O0 -ggdb");
363 k++;
364 } else if (opt[k + 1] == '1') {
365 _srecordf(oflags, "%s", "-O1");
366 optimise = 1;
367 k++;
368 } else if (opt[k + 1] == '2') {
369 _srecordf(oflags, "%s", "-O2");
370 optimise = 2;
371 k++;
372 } else if (opt[k + 1] == '3') {
373 _srecordf(oflags, "%s", "-funroll-all-loops -O3");
374 optimise = 3;
375 k++;
376 } else if (opt[k + 1] == 'f') {
377 _srecordf(oflags, "%s", "-Ofast");
378 optimise = 4;
379 k++;
380 } else {
381 _srecordf(oflags, "%s", "-O");
382 optimise = 1;
383 }
384 } else if (opt[k] == 'c') {
385 compile_only = TRUE;
386 } else if (opt[k] == 'd') {
387 f4_do_loops = TRUE;
388 } else if (opt[k] == 'f') {
389 frequency = TRUE;
390 } else if (opt[k] == 'g') {
391 load_go = TRUE;
392 } else if (opt[k] == 'k') {
393 gcc_ftn_lines = FALSE;
394 } else if (opt[k] == 'l') {
395 keep = TRUE;
396 } else if (opt[k] == 'o') {
397 new_object = TRUE;
398 } else if (opt[k] == 'p') {
399 keep = TRUE;
400 pretty = TRUE;
401 } else if (opt[k] == 'q') {
402 quiet_mode = TRUE;
403 } else if (opt[k] == 'r') {
404 renum = TRUE;
405 } else if (opt[k] == 's') {
406 syntax_only = TRUE;
407 } else if (opt[k] == 't') {
408 trace = TRUE;
409 } else if (opt[k] == 'u') {
410 use_strcasecmp = TRUE;
411 } else if (opt[k] == 'v') {
412 version ();
413 exit (EXIT_SUCCESS);
414 } else if (opt[k] == 'w') {
415 no_warnings = TRUE;
416 } else if (opt[k] == 'x') {
417 load_go = TRUE;
418 load_go_erase = TRUE;
419 } else if (opt[k] == 'y') {
420 renum = TRUE;
421 tidy = TRUE;
422 } else if (opt[k] == 'z') {
423 implicit_r8 = TRUE;
424 } else {
425 usage ();
426 exit (EXIT_FAILURE);
427 }
428 }
429 }
430
431 #undef OPTION
432
433 static void post_edit (char *c_file)
434 {
435 NEW_RECORD (cmd);
436 NEW_RECORD (tmp);
437 _srecordf (tmp, "%s~", c_file);
438 _sys (cmd, "sed", NO_TEXT, "-i '/^\\/\\//d' %s", c_file);
439 _sys (cmd, "sed", NO_TEXT, "-i 's/^\\f//' %s", c_file);
440 // _sys (cmd, "sed", NO_TEXT, "-i '/^# line /d' %s", c_file);
441 _sys (cmd, "sed", NO_TEXT, "-i '/^[[:space:]]*$/d' %s", c_file);
442 if (nerrors == 0) {
443 _sys (cmd, "indent", NO_TEXT, "%s -l500 -br -ce -cdw -nfca -npsl -nut -i2 -nbad -cs -pcs -sob", c_file);
444 _sys (cmd, "sed", NO_TEXT, "-i 's/\\(\\.[0-9][0-9]*\\) q/\\1q/' %s", c_file);
445 // _sys (cmd, "fold", NO_TEXT, "-w 100 -s %s > %s", c_file, tmp);
446 _sys (cmd, "mv", NO_TEXT, "%s %s", tmp, c_file);
447 _sys (cmd, "sed", NO_TEXT, "-i 's/^}$/}\\n/' %s", c_file);
448 _sys (cmd, "sed", NO_TEXT, "-i 's/^};$/};\\n/' %s", c_file);
449 }
450 _sys (cmd, "rm", NO_TEXT, "-f %s", tmp);
451 }
452
453 int_4 main (int_4 argc, char **argv)
454 {
455 int_4 rc = EXIT_SUCCESS, start = 1;
456 NEW_RECORD (c_file);
457 NEW_RECORD (f_file);
458 NEW_RECORD (lst_file);
459 NEW_RECORD (cmd);
460 //
461 MAX_FTN_LINES = INCREMENT;
462 MAX_C_SRC = INCREMENT;
463 source = (FTN_LINE *) f_malloc (MAX_FTN_LINES * sizeof (FTN_LINE));
464 object = (C_SRC *) f_malloc (MAX_C_SRC * sizeof (C_SRC));
465 files = (FTN_LINE *) f_malloc (MAX_SOURCE_FILES * sizeof (FTN_LINE));
466 memset (_ffile, 0, sizeof (_ffile));
467 // Options
468 f4_do_loops = FALSE;
469 new_libnam = FALSE;
470 new_object = FALSE;
471 oflags[0] = '\0';
472 RECCLR (libnam);
473 RECCLR (object_name);
474 while (argv[start] != NO_TEXT && argv[start][0] == '-') {
475 option (argv[start]);
476 start++;
477 if (new_libnam) {
478 new_libnam = FALSE;
479 if (strlen (libnam) == 0 && argv[start] != NO_TEXT) {
480 RECCPY (libnam, argv[start]);
481 start++;
482 } else {
483 usage ();
484 exit (EXIT_FAILURE);
485 }
486 } else if (new_object) {
487 new_object = FALSE;
488 if (strlen (object_name) == 0 && argv[start] != NO_TEXT) {
489 RECCPY (object_name, argv[start]);
490 start++;
491 } else {
492 usage ();
493 exit (EXIT_FAILURE);
494 }
495 }
496 }
497 if (argv[start] == NO_TEXT) {
498 usage ();
499 exit (EXIT_FAILURE);
500 }
501 RECCLR (program);
502 RECCLR (block);
503 RECCLR (curlex);
504 RECCLR (prelex);
505 for (int_4 k = 0; k < MAX_STRLENS; k++) {
506 strlens[k] = FALSE;
507 }
508 date ();
509 RECCPY (hmodule, "global-scope");
510 RECCPY (hsection, "global-section");
511 // Import all sources.
512 NEW_RECORD (argv_start);
513 _srecordf (argv_start, argv[start]);
514 for (int k = start; k < argc; k++) {
515 get_source (f_stralloc (argv[k]), 0);
516 }
517 // Name for project derives from first source file.
518 if (strlen (libnam) == 0) {
519 if (new_object) {
520 RECCPY (libnam, object_name);
521 } else {
522 RECCPY (libnam, argv_start);
523 }
524 for (int k = (int_4) strlen (libnam); k >= 0; k--) {
525 if (libnam[k] == '.') {
526 libnam[k] = '\0';
527 break;
528 }
529 }
530 }
531 // Fill in what we know at the start.
532 prelude (argc, argv, libnam);
533 // Compile all subprograms.
534 nmodules = 0;
535 curlin = 1;
536 curcol = START_OF_LINE;
537 jcllin = 0;
538 scan_modules ();
539 curlin = 1;
540 curcol = START_OF_LINE;
541 macro_nest = 0;
542 lhs_factor = FALSE;
543 subprograms ();
544 // Fill in what we know afterwards, and write C source.
545 postlude ();
546 // Remove stale files.
547 RECCLR (c_file);
548 _srecordf (c_file, "%s.c", libnam);
549 _srecordf (f_file, "%s.f~", libnam);
550 _srecordf (lst_file, "%s.l", libnam);
551 //
552 write_object (c_file);
553 // Compile intermediate code.
554 if (syntax_only) {
555 NEW_RECORD (str);
556 _srecordf (str, "** linker ** no object file generated");
557 diagnostic (0, str);
558 if (nerrors == 0) {
559 rc = EXIT_SUCCESS;
560 } else {
561 rc = EXIT_FAILURE;
562 }
563 } else if (nerrors != 0) {
564 NEW_RECORD (str);
565 nerrors++;
566 _srecordf (str, "** linker ** no object file generated");
567 diagnostic (0, str);
568 rc = EXIT_FAILURE;
569 } else {
570 NEW_RECORD (str);
571 if (compile_only) {
572 if (optimise > 0) {
573 rc = _sys (cmd, BACKEND, NO_TEXT, "%s %s -c %s.c -o %s.o", oflags, CFLAGS, libnam, libnam);
574 } else {
575 rc = _sys (cmd, BACKEND, NO_TEXT, "-O0 -ggdb %s -c %s.c -o %s.o", CFLAGS, libnam, libnam);
576 }
577 } else {
578 if (optimise > 0) {
579 #if defined (BOOTSTRAP)
580 rc = _sys (cmd, BACKEND, NO_TEXT, "%s %s %s.c -o %s %s", oflags, CFLAGS, libnam, libnam, LD_FLAGS);
581 #else
582 rc = _sys (cmd, BACKEND, NO_TEXT, "%s %s %s.c -o %s -L%s %s", oflags, CFLAGS, libnam, libnam, LOCDIR, LD_FLAGS);
583 #endif
584 } else {
585 #if defined (BOOTSTRAP)
586 rc = _sys (cmd, BACKEND, NO_TEXT, "-O0 -ggdb %s %s.c -o %s %s", CFLAGS, libnam, libnam, LD_FLAGS);
587 #else
588 rc = _sys (cmd, BACKEND, NO_TEXT, "-O0 -ggdb %s %s.c -o %s -L%s %s", CFLAGS, libnam, libnam, LOCDIR, LD_FLAGS);
589 #endif
590 }
591 }
592 if (rc == EXIT_SUCCESS) {
593 struct stat s;
594 if (compile_only) {
595 NEW_RECORD (obj);
596 _srecordf (obj, "%s.o", libnam);
597 stat (obj, &s);
598 } else {
599 stat (libnam, &s);
600 }
601 _srecordf (str, "** linker ** object size %ld bytes", s.st_size);
602 diagnostic (0, str);
603 } else {
604 nerrors++;
605 _srecordf (str, "** linker ** no object file generated");
606 diagnostic (0, str);
607 rc = EXIT_FAILURE;
608 }
609 _sys (cmd, "cp", NO_TEXT, "%s %s", c_file, lst_file);
610 }
611 // Wrap it up
612 {
613 NEW_RECORD (str);
614 NEW_RECORD (sub);
615 NEW_RECORD (err);
616 NEW_RECORD (war);
617 // if (nprocs > 0 && ! compile_only) {
618 // nprocs--; // discount 'main'
619 // }
620 if (nprocs == 0) {
621 _srecordf (sub, "no subprograms");
622 } else if (nprocs == 1) {
623 _srecordf (sub, "1 subprogram");
624 } else {
625 _srecordf (sub, "%d subprograms", nprocs);
626 }
627 if (nerrors == 0) {
628 _srecordf (err, "no errors");
629 } else if (nerrors == 1) {
630 _srecordf (err, "1 error");
631 } else {
632 _srecordf (err, "%d errors", nerrors);
633 }
634 if (nwarns == 0) {
635 _srecordf (war, "no warnings");
636 } else if (nwarns == 1) {
637 _srecordf (war, "1 warning");
638 } else {
639 _srecordf (war, "%d warnings", nwarns);
640 }
641 _srecordf (str, "** statistics ** %s, %s, %s", sub, err, war);
642 diagnostic (0, str);
643 }
644 // Execution.
645 if (!renum && load_go && nerrors == 0 && ! syntax_only) {
646 fprintf (stderr, "** execution **\n");
647 NEW_RECORD (exec);
648 if (libnam[0] == '/') {
649 _srecordf (exec, "%s | tee %s.%s.%s", libnam, libnam, date_fn (), PACKAGE);
650 } else {
651 _srecordf (exec, "./%s | tee %s.%s.%s", libnam, libnam, date_fn (), PACKAGE);
652 }
653 rc = _sys (cmd, exec, NO_TEXT, NO_TEXT);
654 if (load_go_erase) {
655 _sys (cmd, "rm", NO_TEXT, "-f ./%s", exec);
656 }
657 }
658 // Write C source again with post-compile information.
659 remove (c_file);
660 write_object (c_file);
661 _sys (cmd, "cp", NO_TEXT, "%s %s", c_file, lst_file);
662 post_edit (c_file);
663 // Write tidied fortran file.
664 if (renum) {
665 write_tidy (f_file);
666 }
667 // Pretty listing file as PDF.
668 if (keep && pretty) {
669 NEW_RECORD (tmp);
670 _srecordf (tmp, "./.vif_pdf");
671 _sys (cmd, "enscript", "ps2pdf", "--quiet --font=Courier-Bold@9 -l -H1 -r --margins=25:25:40:40 -p - %s > %s", c_file, tmp);
672 _sys (cmd, "ps2pdf", "enscript", "%s %s.pdf", tmp, libnam);
673 _sys (cmd, "rm", NO_TEXT, "-f %s", tmp);
674 }
675 if (!keep) {
676 _sys (cmd, "rm", NO_TEXT, "-f %s.s", libnam);
677 }
678 // Exeunt.
679 exit (rc);
680 }
© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)
|