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


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