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_FTN_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 ("  -u     : Code case insensitive string comparisons.\n");
   319    printf ("  -v     : Print the version and exit.\n");
   320    printf ("  -w     : Suppress warning diagnostics.\n");
   321    printf ("  -x     : Execute upon successful compilation and erase executable.\n");
   322    printf ("  -y     : Renumber FORTRAN source code and apply upper stropping.\n");
   323    printf ("  -z     : Set default REAL length to 8 and default COMPLEX length to 16.\n");
   324    printf ("  -O0    : Do not optimize the object code.\n");
   325    printf ("  -O     : Optimize the object code.\n");
   326    printf ("  -O1    : Optimize the object code.\n");
   327    printf ("  -O2    : Optimize the object code.\n");
   328    printf ("  -O3    : Optimize the object code.\n");
   329    printf ("  -Of    : Optimize the object code.\n");
   330  }
   331  
   332  void version (void)
   333  {
   334    printf ("VIF %s - experimental VIntage Fortran compiler.\n", VERSION);
   335    printf ("Copyright 2020-2025 J.M. van der Veer.\n\n");
   336    printf ("Backend compiler : %s\n", BACKEND);
   337    printf ("Install directory: %s\n\n", LOCDIR);
   338    printf ("This is free software covered by the GNU General Public License.\n");
   339    printf ("There is ABSOLUTELY NO WARRANTY for VIF;\n");
   340    printf ("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
   341    printf ("See the GNU General Public License for more details.\n");
   342  }
   343  
   344  #define OPTION(s) EQUAL (opt, (s))
   345  
   346  void option (char *opt)
   347  {
   348    if (OPTION ("--frequency")) {
   349      frequency = TRUE;
   350    } else if (OPTION ("--go")) {
   351      load_go = TRUE;
   352    } else if (OPTION ("--keep")) {
   353      keep_object = TRUE;
   354    } else if (OPTION ("--keep-listing")) {
   355      keep_listing = TRUE;
   356    } else if (OPTION ("--lib")) {
   357      new_libnam = TRUE;
   358    } else if (OPTION ("--pdf")) {
   359      keep_listing = TRUE;
   360      pretty = TRUE;
   361    } else if (OPTION ("--f4-do-loops")) {
   362      f4_do_loops = TRUE;
   363    } else if (OPTION ("--renumber")) {
   364      renum = TRUE;
   365    } else if (OPTION ("--tidy")) {
   366      renum = TRUE;
   367      tidy = TRUE;
   368    } else if (OPTION ("--hollerith")) {
   369      hollerith = TRUE;
   370    } else if (OPTION ("--no-source")) {
   371      no_source = TRUE;
   372    } else if (OPTION ("--license")) {
   373      version ();
   374      exit (EXIT_SUCCESS);
   375    } else if (OPTION ("--version")) {
   376      version ();
   377      exit (EXIT_SUCCESS);
   378    } else if (opt[1] == '-' && opt[2] == '\0') {
   379      return;
   380    } else for (int_4 k = 1; opt[k] != '\0'; k++) {
   381      if (opt[k] == 'O') {
   382        optimise = 0;
   383        if (opt[k + 1] == '0') {
   384          _srecordf(oflags, "%s", "-O0 -ggdb");
   385          k++;
   386        } else if (opt[k + 1] == '1') {
   387          _srecordf(oflags, "%s", "-O1");
   388          optimise = 1;
   389          k++;
   390        } else if (opt[k + 1] == '2') {
   391          _srecordf(oflags, "%s", "-O2");
   392          optimise = 2;
   393          k++;
   394        } else if (opt[k + 1] == '3') {
   395          _srecordf(oflags, "%s", "-funroll-all-loops -O3");
   396          optimise = 3;
   397          k++;
   398        } else if (opt[k + 1] == 'f') {
   399          _srecordf(oflags, "%s", "-Ofast");
   400          optimise = 4;
   401          k++;
   402        } else {
   403          _srecordf(oflags, "%s", "-O");
   404          optimise = 1;
   405        }
   406      } else if (opt[k] == 'b') {
   407        no_source = TRUE;
   408      } else if (opt[k] == 'c') {
   409        compile_only = TRUE;
   410      } else if (opt[k] == 'd') {
   411        f4_do_loops = TRUE;
   412      } else if (opt[k] == 'e') {
   413        keep_object = TRUE;
   414      } else if (opt[k] == 'f') {
   415        frequency = TRUE;
   416      } else if (opt[k] == 'g') {
   417        load_go = TRUE;
   418      } else if (opt[k] == 'h') {
   419        hollerith = TRUE;
   420      } else if (opt[k] == 'k') {
   421        gcc_ftn_lines = FALSE;
   422      } else if (opt[k] == 'l') {
   423        keep_listing = TRUE;
   424      } else if (opt[k] == 'o') {
   425        new_object = TRUE;
   426      } else if (opt[k] == 'p') {
   427        keep_listing = TRUE;
   428        pretty = TRUE;
   429      } else if (opt[k] == 'q') {
   430        quiet_mode = TRUE;
   431      } else if (opt[k] == 'r') {
   432        renum = TRUE;
   433      } else if (opt[k] == 's') {
   434        syntax_only = TRUE;
   435      } else if (opt[k] == 't') {
   436        trace = TRUE;
   437      } else if (opt[k] == 'u') {
   438        use_strcasecmp = TRUE;
   439      } else if (opt[k] == 'v') {
   440        version ();
   441        exit (EXIT_SUCCESS);
   442      } else if (opt[k] == 'w') {
   443        no_warnings = TRUE;
   444      } else if (opt[k] == 'x') {
   445        load_go = TRUE;
   446        load_go_erase = TRUE;
   447      } else if (opt[k] == 'y') {
   448        renum = TRUE;
   449        tidy = TRUE;
   450      } else if (opt[k] == 'z') {
   451        implicit_r8 = TRUE;
   452      } else {
   453        usage ();
   454        exit (EXIT_FAILURE);
   455      }
   456    }
   457  }
   458  
   459  #undef OPTION
   460  
   461  int_4 main (int_4 argc, char **argv)
   462  {
   463    int_4 rc = EXIT_SUCCESS, start = 1;
   464    NEW_RECORD (c_file);
   465    NEW_RECORD (f_file);
   466    NEW_RECORD (lst_file);
   467    NEW_RECORD (cmd);
   468  //
   469    for (int k = 0; k < MAX_FTN_FILES; k++) {
   470      _reset_ftn_file (&_ffile[k]);
   471    }
   472  //
   473    MAX_FTN_LINES = INCREMENT;
   474    MAX_C_SRC = INCREMENT;
   475    source = (FTN_LINE *) f_malloc (MAX_FTN_LINES * sizeof (FTN_LINE));
   476    object = (C_SRC *) f_malloc (MAX_C_SRC * sizeof (C_SRC));
   477    files = (FTN_LINE *) f_malloc (MAX_SOURCE_FILES * sizeof (FTN_LINE));
   478    memset (_ffile, 0, sizeof (_ffile));
   479  // Options
   480    f4_do_loops = FALSE;
   481    new_libnam = FALSE;
   482    new_object = FALSE;
   483    oflags[0] = '\0';
   484    RECCLR (libnam);
   485    RECCLR (object_name);
   486    while (argv[start] != NO_TEXT && argv[start][0] == '-') {
   487      option (argv[start]);
   488      start++;
   489      if (new_libnam) {
   490        new_libnam = FALSE;
   491        if (strlen (libnam) == 0 && argv[start] != NO_TEXT) {
   492          RECCPY (libnam, argv[start]);
   493          start++;
   494        } else {
   495          usage ();
   496          exit (EXIT_FAILURE);
   497        }
   498      } else if (new_object) {
   499        new_object = FALSE;
   500        if (strlen (object_name) == 0 && argv[start] != NO_TEXT) {
   501          RECCPY (object_name, argv[start]);
   502          start++;
   503        } else {
   504          usage ();
   505          exit (EXIT_FAILURE);
   506        }
   507      }
   508    }
   509    if (argv[start] == NO_TEXT) {
   510      usage ();
   511      exit (EXIT_FAILURE);
   512    }
   513    RECCLR (program);
   514    RECCLR (block);
   515    RECCLR (curlex);
   516    RECCLR (prelex);
   517    for (int_4 k = 0; k < MAX_STRLENS; k++) {
   518      strlens[k] = FALSE;
   519    }
   520    date ();
   521    RECCPY (hmodule, "global-scope");
   522    RECCPY (hsection, "global-section");
   523  // Import all sources.
   524    NEW_RECORD (argv_start);
   525    _srecordf (argv_start, argv[start]);
   526    for (int k = start; k < argc; k++) {
   527      get_source (f_stralloc (argv[k]), 0);
   528    }
   529  // Name for project derives from first source file.
   530    if (strlen (libnam) == 0) {
   531      if (new_object) {
   532        RECCPY (libnam, object_name);
   533      } else {
   534        RECCPY (libnam, argv_start);
   535      }
   536      for (int k = (int_4) strlen (libnam); k >= 0; k--) {
   537        if (libnam[k] == '.') {
   538          libnam[k] = '\0';
   539          break;
   540        }
   541      }
   542    }
   543  // Fill in what we know at the start.
   544    prelude (argc, argv, libnam);
   545  // Compile all subprograms.
   546    nmodules = 0;
   547    curlin = 1; 
   548    curcol = START_OF_LINE;
   549    jcllin = 0;
   550    scan_modules ();
   551    curlin = 1; 
   552    curcol = START_OF_LINE;
   553    macro_nest = 0;
   554    lhs_factor = FALSE;
   555    subprograms ();
   556  // Fill in what we know afterwards, and write C source.
   557    postlude ();
   558  // Remove stale files.
   559    RECCLR (c_file);
   560    _srecordf (c_file, "%s.c", libnam);
   561    _srecordf (f_file, "%s.f~", libnam);
   562    _srecordf (lst_file, "%s.l", libnam);
   563  //
   564    write_object (c_file);
   565  // Compile intermediate code.
   566    if (syntax_only) {
   567      NEW_RECORD (str);
   568      _srecordf (str, "** linker     ** no object file generated");
   569      diagnostic (0, str);
   570      if (nerrors == 0) {
   571        rc = EXIT_SUCCESS;
   572      } else {
   573        rc = EXIT_FAILURE;
   574      }
   575    } else if (nerrors != 0) {
   576      NEW_RECORD (str);
   577      nerrors++;
   578      _srecordf (str, "** linker     ** no object file generated");
   579      diagnostic (0, str);
   580      rc = EXIT_FAILURE;
   581    } else {
   582      NEW_RECORD (str);
   583      if (compile_only) {
   584        if (optimise > 0) {
   585          rc = _sys (cmd, BACKEND, NO_TEXT, "%s %s -c %s.c -o %s.o", oflags, CFLAGS, libnam, libnam);
   586        } else {
   587          rc = _sys (cmd, BACKEND, NO_TEXT, "-O0 -ggdb %s -c %s.c -o %s.o", CFLAGS, libnam, libnam);
   588        }
   589      } else {
   590        if (optimise > 0) {
   591  #if defined (BOOTSTRAP)
   592          rc = _sys (cmd, BACKEND, NO_TEXT, "%s %s %s.c -o %s %s", oflags, CFLAGS, libnam, libnam, LD_FLAGS);
   593  #else
   594          rc = _sys (cmd, BACKEND, NO_TEXT, "%s %s %s.c -o %s -L%s %s", oflags, CFLAGS, libnam, libnam, LOCDIR, LD_FLAGS);
   595  #endif
   596        } else {
   597  #if defined (BOOTSTRAP)
   598          rc = _sys (cmd, BACKEND, NO_TEXT, "-O0 -ggdb %s %s.c -o %s %s", CFLAGS, libnam, libnam, LD_FLAGS);
   599  #else
   600          rc = _sys (cmd, BACKEND, NO_TEXT, "-O0 -ggdb %s %s.c -o %s -L%s %s", CFLAGS, libnam, libnam, LOCDIR, LD_FLAGS);
   601  #endif
   602        }
   603      }
   604      if (rc == EXIT_SUCCESS) {
   605        struct stat s;
   606        if (compile_only) {
   607          NEW_RECORD (obj);
   608          _srecordf (obj, "%s.o", libnam);
   609          stat (obj, &s);
   610        } else {
   611          stat (libnam, &s);
   612        }
   613        _srecordf (str, "** linker     ** object size %ld bytes", s.st_size);
   614        diagnostic (0, str);
   615      } else {
   616        nerrors++;
   617        _srecordf (str, "** linker     ** no object file generated");
   618        diagnostic (0, str);
   619        rc = EXIT_FAILURE;
   620      }
   621      if (keep_listing) {
   622        _sys (cmd, "cp", NO_TEXT, "%s %s", c_file, lst_file);
   623      }
   624    }
   625  // Wrap it up
   626    {
   627      NEW_RECORD (str);
   628      NEW_RECORD (sub);
   629      NEW_RECORD (err);
   630      NEW_RECORD (war);
   631      if (! compile_only) {
   632        nprocs--; // Discount entry point "main".
   633      }
   634      if (nprocs == 0) {
   635        _srecordf (sub, "no subprograms");
   636      } else if (nprocs == 1) {
   637        _srecordf (sub, "1 subprogram");
   638      } else {
   639        _srecordf (sub, "%d subprograms", nprocs);
   640      }
   641      if (nerrors == 0) {
   642        _srecordf (err, "no errors");
   643      } else if (nerrors == 1) {
   644        _srecordf (err, "1 error");
   645      } else {
   646        _srecordf (err, "%d errors", nerrors);
   647      }
   648      if (nwarns == 0) {
   649        _srecordf (war, "no warnings");
   650      } else if (nwarns == 1) {
   651        _srecordf (war, "1 warning");
   652      } else {
   653        _srecordf (war, "%d warnings", nwarns);
   654      }
   655      _srecordf (str, "** statistics ** %s, %s, %s", sub, err, war);
   656      diagnostic (0, str);
   657    }
   658  // Execution.
   659    if (!renum && load_go && nerrors == 0 && ! syntax_only) {
   660      fprintf (stderr, "** execution  **\n");
   661      NEW_RECORD (exec);
   662      if (libnam[0] == '/') {
   663        _srecordf (exec, "%s | tee %s.%s.%s", libnam, libnam, date_fn (), PACKAGE);
   664      } else {
   665        _srecordf (exec, "./%s | tee %s.%s.%s", libnam, libnam, date_fn (), PACKAGE);
   666      }
   667      rc = _sys (cmd, exec, NO_TEXT, NO_TEXT);
   668      if (load_go_erase) {
   669        _sys (cmd, "rm", NO_TEXT, "-f ./%s", exec);
   670      }
   671    }
   672  // Write C source again with post-compile information.
   673    remove (c_file);
   674    write_object (c_file);
   675    _sys (cmd, "cp", NO_TEXT, "%s %s", c_file, lst_file);
   676  // Write tidied fortran file.
   677    if (renum) {
   678      write_tidy (f_file);
   679    }
   680  // Pretty listing file as PDF.
   681    if (keep_listing && 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_object) {
   689      _sys (cmd, "rm", NO_TEXT, "-f %s.c", libnam);
   690      _sys (cmd, "rm", NO_TEXT, "-f %s.s", libnam);
   691    }
   692  // Exeunt.
   693    exit (rc);
   694  }


© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)