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 syntax_only = FALSE;
    80  logical_4 trace = FALSE;
    81  logical_4 use_strcasecmp = FALSE;
    82  
    83  RECORD hdate;
    84  RECORD hmodule, hsection;
    85  RECORD libnam, modnam, procnam;
    86  RECORD object_name;
    87  RECORD oflags;
    88  RECORD prelex, curlex, retnam;
    89  RECORD program, block;
    90  RECORD stat_start;
    91  
    92  logical_4 reserved (char *lex)
    93  {
    94    static char *words[] = {
    95      "accept", "assign", "automatic", "backspace", "call", "character",
    96      "close", "common", "complex", "continue", "decode", "dimension", "data", 
    97      "do", "double", "else", "elseif", "encode", "end", "enddo", "endfile", 
    98      "endif", "entry", "external", "format", "function", "go", "goto",
    99      "if", "implicit", "integer", "intrinsic", "logical", "open",
   100      "pause", "precision", "print", "program", "punch", "read", "real",
   101      "repeat", "return", "rewind", "save", "subroutine", "stop", "then",
   102      "to", "until", "while", "write", NO_TEXT
   103    };
   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 (3401, "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 (3402, "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 (3403, "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 ("  -W     : Set default REAL length to 8 and default COMPLEX length to 16.\n");
   294    printf ("  -O0    : Do not optimize the object code.\n");
   295    printf ("  -O     : Optimize the object code.\n");
   296    printf ("  -O1    : Optimize the object code.\n");
   297    printf ("  -O2    : Optimize the object code.\n");
   298    printf ("  -O3    : Optimize the object code.\n");
   299    printf ("  -Of    : Optimize the object code.\n");
   300  }
   301  
   302  void version (void)
   303  {
   304    printf ("VIF %s - experimental VIntage Fortran compiler.\n", VERSION);
   305    printf ("Copyright 2020-2025 J.M. van der Veer.\n\n");
   306    printf ("Backend compiler : %s\n", BACKEND);
   307    printf ("Install directory: %s\n\n", LOCDIR);
   308    printf ("This is free software covered by the GNU General Public License.\n");
   309    printf ("There is ABSOLUTELY NO WARRANTY for VIF;\n");
   310    printf ("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
   311    printf ("See the GNU General Public License for more details.\n");
   312  }
   313  
   314  #define OPTION(s) EQUAL (opt, (s))
   315  
   316  void option (char *opt)
   317  {
   318    if (OPTION ("--frequency")) {
   319      frequency = TRUE;
   320    } else if (OPTION ("--go")) {
   321      load_go = TRUE;
   322    } else if (OPTION ("--keep")) {
   323      keep = TRUE;
   324    } else if (OPTION ("--lib")) {
   325      new_libnam = TRUE;
   326    } else if (OPTION ("--pdf")) {
   327      keep = TRUE;
   328      pretty = TRUE;
   329    } else if (OPTION ("--f4-do-loops")) {
   330      f4_do_loops = TRUE;
   331    } else if (OPTION ("--renumber")) {
   332      renum = TRUE;
   333    } else if (OPTION ("--hollerith")) {
   334      hollerith = TRUE;
   335    } else if (OPTION ("--license")) {
   336      version ();
   337      exit (EXIT_SUCCESS);
   338    } else if (OPTION ("--version")) {
   339      version ();
   340      exit (EXIT_SUCCESS);
   341    } else if (opt[1] == '-' && opt[2] == '\0') {
   342      return;
   343    } else for (int_4 k = 1; opt[k] != '\0'; k++) {
   344      if (opt[k] == 'O') {
   345        optimise = 0;
   346        if (opt[k + 1] == '0') {
   347          _srecordf(oflags, "%s", "-O0 -ggdb");
   348          k++;
   349        } else if (opt[k + 1] == '1') {
   350          _srecordf(oflags, "%s", "-O1");
   351          optimise = 1;
   352          k++;
   353        } else if (opt[k + 1] == '2') {
   354          _srecordf(oflags, "%s", "-O2");
   355          optimise = 2;
   356          k++;
   357        } else if (opt[k + 1] == '3') {
   358          _srecordf(oflags, "%s", "-funroll-all-loops -O3");
   359          optimise = 3;
   360          k++;
   361        } else if (opt[k + 1] == 'f') {
   362          _srecordf(oflags, "%s", "-Ofast");
   363          optimise = 4;
   364          k++;
   365        } else {
   366          _srecordf(oflags, "%s", "-O");
   367          optimise = 1;
   368        }
   369      } else if (opt[k] == 'c') {
   370        compile_only = TRUE;
   371      } else if (opt[k] == 'd') {
   372        f4_do_loops = TRUE;
   373      } else if (opt[k] == 'f') {
   374        frequency = TRUE;
   375      } else if (opt[k] == 'g') {
   376        load_go = TRUE;
   377      } else if (opt[k] == 'k') {
   378        gcc_ftn_lines = FALSE;
   379      } else if (opt[k] == 'l') {
   380        keep = TRUE;
   381      } else if (opt[k] == 'o') {
   382        new_object = TRUE;
   383      } else if (opt[k] == 'p') {
   384        keep = TRUE;
   385        pretty = TRUE;
   386      } else if (opt[k] == 'q') {
   387        quiet_mode = TRUE;
   388      } else if (opt[k] == 'r') {
   389        renum = TRUE;
   390      } else if (opt[k] == 's') {
   391        syntax_only = TRUE;
   392      } else if (opt[k] == 't') {
   393        trace = TRUE;
   394      } else if (opt[k] == 'u') {
   395        use_strcasecmp = TRUE;
   396      } else if (opt[k] == 'v') {
   397        version ();
   398        exit (EXIT_SUCCESS);
   399      } else if (opt[k] == 'w') {
   400        no_warnings = TRUE;
   401      } else if (opt[k] == 'W') {
   402        implicit_r8 = TRUE;
   403      } else if (opt[k] == 'x') {
   404        load_go = TRUE;
   405        load_go_erase = TRUE;
   406      } else {
   407        usage ();
   408        exit (EXIT_FAILURE);
   409      }
   410    }
   411  }
   412  
   413  #undef OPTION
   414  
   415  static void post_edit (char *c_file)
   416  {
   417    NEW_RECORD (cmd);
   418    NEW_RECORD (tmp);
   419    _srecordf (tmp, "%s~", c_file);
   420    _sys (cmd, "sed", NO_TEXT, "-i '/^\\/\\//d' %s", c_file);
   421    _sys (cmd, "sed", NO_TEXT, "-i 's/^\\f//' %s", c_file);
   422    // _sys (cmd, "sed", NO_TEXT, "-i '/^# line /d' %s", c_file);
   423    _sys (cmd, "sed", NO_TEXT, "-i '/^[[:space:]]*$/d' %s", c_file);
   424    if (nerrors == 0) {
   425      _sys (cmd, "indent", NO_TEXT, "%s -l500 -br -ce -cdw -nfca -npsl -nut -i2 -nbad -cs -pcs -sob", c_file);
   426      _sys (cmd, "sed", NO_TEXT, "-i 's/\\(\\.[0-9][0-9]*\\) q/\\1q/' %s", c_file);
   427      // _sys (cmd, "fold", NO_TEXT, "-w 100 -s %s > %s", c_file, tmp);
   428      _sys (cmd, "mv", NO_TEXT, "%s %s", tmp, c_file);
   429    }
   430    _sys (cmd, "rm", NO_TEXT, "-f %s", tmp);
   431  }
   432  
   433  int_4 main (int_4 argc, char **argv)
   434  {
   435    int_4 rc = EXIT_SUCCESS, start = 1;
   436    NEW_RECORD (c_file);
   437    NEW_RECORD (lst_file);
   438    NEW_RECORD (cmd);
   439  //
   440    MAX_FTN_LINES = INCREMENT;
   441    MAX_C_SRC = INCREMENT;
   442    source = (FTN_LINE *) f_malloc (MAX_FTN_LINES * sizeof (FTN_LINE));
   443    object = (C_SRC *) f_malloc (MAX_C_SRC * sizeof (C_SRC));
   444    files = (FTN_LINE *) f_malloc (MAX_SOURCE_FILES * sizeof (FTN_LINE));
   445    memset (_ffile, 0, sizeof (_ffile));
   446  // Options
   447    f4_do_loops = FALSE;
   448    new_libnam = FALSE;
   449    new_object = FALSE;
   450    oflags[0] = '\0';
   451    RECCLR (libnam);
   452    RECCLR (object_name);
   453    while (argv[start] != NO_TEXT && argv[start][0] == '-') {
   454      option (argv[start]);
   455      start++;
   456      if (new_libnam) {
   457        new_libnam = FALSE;
   458        if (strlen (libnam) == 0 && argv[start] != NO_TEXT) {
   459          RECCPY (libnam, argv[start]);
   460          start++;
   461        } else {
   462          usage ();
   463          exit (EXIT_FAILURE);
   464        }
   465      } else if (new_object) {
   466        new_object = FALSE;
   467        if (strlen (object_name) == 0 && argv[start] != NO_TEXT) {
   468          RECCPY (object_name, argv[start]);
   469          start++;
   470        } else {
   471          usage ();
   472          exit (EXIT_FAILURE);
   473        }
   474      }
   475    }
   476    if (argv[start] == NO_TEXT) {
   477      usage ();
   478      exit (EXIT_FAILURE);
   479    }
   480    RECCLR (program);
   481    RECCLR (block);
   482    RECCLR (curlex);
   483    RECCLR (prelex);
   484    for (int_4 k = 0; k < MAX_STRLENS; k++) {
   485      strlens[k] = FALSE;
   486    }
   487    date ();
   488    RECCPY (hmodule, "global-scope");
   489    RECCPY (hsection, "global-section");
   490  // Import all sources.
   491    NEW_RECORD (argv_start);
   492    _srecordf (argv_start, argv[start]);
   493    for (int k = start; k < argc; k++) {
   494      get_source (f_stralloc (argv[k]), 0);
   495    }
   496  // Name for project derives from first source file.
   497    if (strlen (libnam) == 0) {
   498      if (new_object) {
   499        RECCPY (libnam, object_name);
   500      } else {
   501        RECCPY (libnam, argv_start);
   502      }
   503      for (int k = (int_4) strlen (libnam); k >= 0; k--) {
   504        if (libnam[k] == '.') {
   505          libnam[k] = '\0';
   506          break;
   507        }
   508      }
   509    }
   510  // Fill in what we know at the start.
   511    prelude (argc, argv, libnam);
   512  // Compile all subprograms.
   513    nmodules = 0;
   514    curlin = 1; 
   515    curcol = START_OF_LINE;
   516    jcllin = 0;
   517    scan_modules ();
   518    curlin = 1; 
   519    curcol = START_OF_LINE;
   520    macro_nest = 0;
   521    lhs_factor = FALSE;
   522    subprograms ();
   523  // Fill in what we know afterwards, and write C source.
   524    postlude ();
   525  // Remove stale files.
   526    RECCLR (c_file);
   527    _srecordf (c_file, "%s.c", libnam);
   528    _srecordf (lst_file, "%s.l", libnam);
   529  //
   530    write_object (c_file);
   531  // Compile intermediate code.
   532    if (syntax_only) {
   533      NEW_RECORD (str);
   534      _srecordf (str, "** linker     ** no object file generated");
   535      diagnostic (0, str);
   536      if (nerrors == 0) {
   537        rc = EXIT_SUCCESS;
   538      } else {
   539        rc = EXIT_FAILURE;
   540      }
   541    } else if (renum) {
   542      NEW_RECORD (str);
   543      if (nerrors == 0) {
   544        int_4 Nf = 0;
   545        // Renumber source files.
   546        for (int k = start; k < argc; k++, Nf++) {
   547          relabel (f_stralloc (argv[k]));
   548        }
   549        if (Nf == 1) {
   550          _srecordf (str, "** statistics ** 1 fortran file renumbered");
   551        } else {
   552          _srecordf (str, "** statistics ** %d fortran files renumbered", Nf);
   553          rc = EXIT_SUCCESS;
   554        }
   555      } else {
   556        _srecordf (str, "** statistics ** no fortran files renumbered");
   557        rc = EXIT_FAILURE;
   558      }
   559      diagnostic (0, str);
   560    } else if (nerrors != 0) {
   561      NEW_RECORD (str);
   562      nerrors++;
   563      _srecordf (str, "** linker     ** no object file generated");
   564      diagnostic (0, str);
   565      rc = EXIT_FAILURE;
   566    } else {
   567      NEW_RECORD (str);
   568      if (compile_only) {
   569        if (optimise > 0) {
   570          rc = _sys (cmd, BACKEND, NO_TEXT, "%s %s -c %s.c -o %s.o", oflags, CFLAGS, libnam, libnam);
   571        } else {
   572          rc = _sys (cmd, BACKEND, NO_TEXT, "-O0 -ggdb %s -c %s.c -o %s.o", CFLAGS, libnam, libnam);
   573        }
   574      } else {
   575        if (optimise > 0) {
   576  #if defined (BOOTSTRAP)
   577          rc = _sys (cmd, BACKEND, NO_TEXT, "%s %s %s.c -o %s %s", oflags, CFLAGS, libnam, libnam, LD_FLAGS);
   578  #else
   579          rc = _sys (cmd, BACKEND, NO_TEXT, "%s %s %s.c -o %s -L%s %s", oflags, CFLAGS, libnam, libnam, LOCDIR, LD_FLAGS);
   580  #endif
   581        } else {
   582  #if defined (BOOTSTRAP)
   583          rc = _sys (cmd, BACKEND, NO_TEXT, "-O0 -ggdb %s %s.c -o %s %s", CFLAGS, libnam, libnam, LD_FLAGS);
   584  #else
   585          rc = _sys (cmd, BACKEND, NO_TEXT, "-O0 -ggdb %s %s.c -o %s -L%s %s", CFLAGS, libnam, libnam, LOCDIR, LD_FLAGS);
   586  #endif
   587        }
   588      }
   589      if (rc == EXIT_SUCCESS) {
   590        struct stat s;
   591        if (compile_only) {
   592          NEW_RECORD (obj);
   593          _srecordf (obj, "%s.o", libnam);
   594          stat (obj, &s);
   595        } else {
   596          stat (libnam, &s);
   597        }
   598        _srecordf (str, "** linker     ** object size %ld bytes", s.st_size);
   599        diagnostic (0, str);
   600      } else {
   601        nerrors++;
   602        _srecordf (str, "** linker     ** no object file generated");
   603        diagnostic (0, str);
   604        rc = EXIT_FAILURE;
   605      }
   606      _sys (cmd, "cp", NO_TEXT, "%s %s", c_file, lst_file);
   607    }
   608  // Wrap it up
   609    {
   610      NEW_RECORD (str);
   611      NEW_RECORD (sub);
   612      NEW_RECORD (err);
   613      NEW_RECORD (war);
   614      // if (nprocs > 0 && ! compile_only) {
   615      //   nprocs--; // discount 'main'
   616      // }
   617      if (nprocs == 0) {
   618        _srecordf (sub, "no subprograms");
   619      } else if (nprocs == 1) {
   620        _srecordf (sub, "1 subprogram");
   621      } else {
   622        _srecordf (sub, "%d subprograms", nprocs);
   623      }
   624      if (nerrors == 0) {
   625        _srecordf (err, "no errors");
   626      } else if (nerrors == 1) {
   627        _srecordf (err, "1 error");
   628      } else {
   629        _srecordf (err, "%d errors", nerrors);
   630      }
   631      if (nwarns == 0) {
   632        _srecordf (war, "no warnings");
   633      } else if (nwarns == 1) {
   634        _srecordf (war, "1 warning");
   635      } else {
   636        _srecordf (war, "%d warnings", nwarns);
   637      }
   638      _srecordf (str, "** statistics ** %s, %s, %s", sub, err, war);
   639      diagnostic (0, str);
   640    }
   641  // Execution.
   642    if (!renum && load_go && nerrors == 0 && ! syntax_only) {
   643      fprintf (stderr, "** execution  **\n");
   644      NEW_RECORD (exec);
   645      if (libnam[0] == '/') {
   646        _srecordf (exec, "%s", libnam);
   647      } else {
   648        _srecordf (exec, "./%s", libnam);
   649      }
   650      rc = _sys (cmd, exec, NO_TEXT, NO_TEXT);
   651      if (load_go_erase) {
   652        _sys (cmd, "rm", NO_TEXT, "-f ./%s", exec);
   653      }
   654    }
   655  // Write C source again with post-compile information.
   656    remove (c_file);
   657    write_object (c_file);
   658    _sys (cmd, "cp", NO_TEXT, "%s %s", c_file, lst_file);
   659    post_edit (c_file);
   660  // Pretty listing file as PDF.
   661    if (keep && pretty) {
   662      NEW_RECORD (tmp);
   663      _srecordf (tmp, "./.vif_pdf");
   664      _sys (cmd, "enscript", "ps2pdf", "--quiet --font=Courier-Bold@9 -l -H1 -r --margins=25:25:40:40 -p - %s > %s", c_file, tmp);
   665      _sys (cmd, "ps2pdf", "enscript", "%s %s.pdf", tmp, libnam);
   666      _sys (cmd, "rm", NO_TEXT, "-f %s", tmp);
   667    }
   668    if (!keep) {
   669      _sys (cmd, "rm", NO_TEXT, "-f %s.s", libnam);
   670    }
   671  // Exeunt.
   672    exit (rc);
   673  }


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