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