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)