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


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