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