tidy.c

     1  //! @file yidy.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  //! Vintage Fortran tidying tool.
    25  
    26  #include <vif.h>
    27  
    28  #define ALLOW_ANON (nprocs >= 0)
    29  
    30  void tidy_executable (void);
    31  void tidy_statements (LBL *, int_4);
    32  
    33  void tidy_to_upper (void)
    34  {
    35  // Make uppercase, backwards.
    36    if (tidy) {
    37      char *p = curlex, *q = &(CUR_LIN.text[curcol - 1]);
    38      while (*p != '\0') {
    39        if (isspace (*q)) {
    40          q--;
    41        } else {
    42          *q = toupper (*q);
    43          q--;
    44          p++;
    45        }
    46      }
    47    }
    48  }
    49  
    50  void tidy_to_lower (void)
    51  {
    52  // Make lowercase, backwards.
    53    if (tidy) {
    54      char *p = curlex, *q = &(CUR_LIN.text[curcol - 1]);
    55      while (*p != '\0') {
    56        if (isspace (*q)) {
    57     q--;
    58        } else {
    59     *q = tolower (*q);
    60     q--;
    61     p++;
    62        }
    63      }
    64    }
    65  }
    66  
    67  void tidy_skip_card (void)
    68  {
    69    if (prelin == curlin) {
    70      int_4 rc;
    71      do {
    72        rc = scan (EXPECT_NONE);
    73      }
    74      while (rc != END_OF_LINE && rc != END_OF_MODULE);
    75    } else if (CUR_LIN.text == NO_TEXT) {
    76      return;
    77    } else if (strlen (CUR_LIN.text) >= 6 && POS(5) != ' ') {
    78      int_4 rc;
    79      do {
    80        rc = scan (EXPECT_NONE);
    81      }
    82      while (rc != END_OF_LINE && rc != END_OF_MODULE);
    83    }
    84  }
    85  
    86  LBL *find_relabel (char *lab)
    87  {
    88    int_4 k, num;
    89    sscanf (lab, "%d", &num);
    90    for (k = 0; k < nlabels; k++) {
    91      LBL *L = &labels[k];
    92      if (num == L->num) {
    93        return L;
    94      }
    95    }
    96    FATAL (3201, "no such label", curlex);
    97  }
    98  
    99  void replace_label (int_4 label)
   100  {
   101    NEW_RECORD (repl);
   102    _srecordf (repl, "%d", label);
   103    int_4 len_orig = strlen (curlex), len_repl = strlen (repl);
   104    int_4 delta = len_repl - len_orig;
   105    char *p = CUR_LIN.text;
   106    if ((strlen (p) + delta) > RECLN) {
   107      FATAL (3202, "cannot replace label", NO_TEXT);
   108    }
   109    NEW_RECORD (sub);
   110    RECCPY (sub, p);
   111    int_4 k = 0;
   112  // Recalibrate current position.
   113    while (curcol >= 0 && !isdigit (CUR_COL)) {
   114      curcol--;
   115    }
   116    curcol++;
   117  //
   118    for (; k < curcol - len_orig; k++) {
   119      p[k] = sub[k];
   120    }
   121    for (int_4 n = 0; repl[n] != '\0'; n++, k++) {
   122      p[k] = repl[n];
   123    }
   124    for (int_4 n = curcol; sub[n] != '\0'; n++, k++) {
   125      p[k] = sub[n];
   126    }
   127    for (; sub[k] != '\0'; k++) {
   128      p[k] = '\0';
   129    }
   130    CUR_LIN.len += delta;
   131    curcol += delta;
   132  }
   133  
   134  void tidy_prescan (void)
   135  {
   136    SAVE_POS (1);
   137    int_4 rc, go_on = TRUE;
   138    while (go_on) {
   139      rc = scan (EXPECT_NONE);
   140      if (rc == END_OF_MODULE) {
   141        go_on = FALSE;
   142      }
   143      if (TOKEN ("end") && IS_NOT_ASSIGNMENT) {
   144        go_on = FALSE;
   145      } else if (rc != TEXT) {
   146        tidy_to_lower ();
   147      }
   148    }
   149    RESTORE_POS (1);
   150  }
   151  
   152  void tidy_subprogram (void)
   153  {
   154    SAVE_POS (1);
   155    int_4 rc = scan (EXPECT_NONE);
   156    if (rc == WORD) {
   157      if (TOKEN ("program")) {
   158        tidy_to_upper ();
   159        tidy_skip_card ();
   160        return;
   161      } else if (TOKEN ("subroutine")) {
   162        tidy_to_upper ();
   163        tidy_skip_card ();
   164        return;
   165      } else if (TOKEN ("block")) {
   166        tidy_to_upper ();
   167        rc = scan (EXPECT_NONE);
   168        if (TOKEN ("data")) {
   169          tidy_to_upper ();
   170        }
   171        tidy_skip_card ();
   172        return;
   173      } else if (TOKEN ("function")) {
   174        tidy_to_upper ();
   175        tidy_skip_card ();
   176        return;
   177      } else {
   178        if (ALLOW_ANON) {
   179          tidy_skip_card ();
   180        }
   181      }
   182    } else if (rc == DECLAR) {
   183      tidy_to_upper ();
   184      tidy_subprogram ();
   185    }
   186    RESTORE_POS (1);
   187  }
   188  
   189  static void tidy_decls (void)
   190  {
   191    int_4 go_on = TRUE;
   192    while (go_on) {
   193      SAVE_POS (1);
   194      int_4 rc = scan (EXPECT_NONE);
   195      if (rc == DECLAR) {
   196        tidy_to_upper ();
   197        tidy_skip_card ();
   198      } else if (TOKEN ("implicit") && IS_NOT_ASSIGNMENT) {
   199        tidy_to_upper ();
   200        rc = scan (EXPECT_NONE);
   201        if (rc == DECLAR) {
   202          tidy_to_upper ();
   203        }
   204        tidy_skip_card ();
   205      } else if (TOKEN ("save") && IS_NOT_ASSIGNMENT) {
   206        tidy_to_upper ();
   207        tidy_skip_card ();
   208      } else if (TOKEN ("automatic") && IS_NOT_ASSIGNMENT) {
   209        tidy_to_upper ();
   210        tidy_skip_card ();
   211      } else if (TOKEN ("parameter") && IS_NOT_ASSIGNMENT) {
   212        tidy_to_upper ();
   213        tidy_skip_card ();
   214      } else if (TOKEN ("common") && IS_NOT_ASSIGNMENT) {
   215        tidy_to_upper ();
   216        tidy_skip_card ();
   217      } else if (TOKEN ("dimension") && IS_NOT_ASSIGNMENT) {
   218        tidy_to_upper ();
   219        tidy_skip_card ();
   220      } else if (TOKEN ("equivalence") && IS_NOT_ASSIGNMENT) {
   221        tidy_to_upper ();
   222        tidy_skip_card ();
   223      } else if (TOKEN ("external") && IS_NOT_ASSIGNMENT) {
   224        tidy_to_upper ();
   225        tidy_skip_card ();
   226      } else if (TOKEN ("intrinsic") && IS_NOT_ASSIGNMENT) {
   227        tidy_to_upper ();
   228        tidy_skip_card ();
   229      } else if (TOKEN ("data") && IS_NOT_ASSIGNMENT) {
   230        tidy_to_upper ();
   231        tidy_skip_card ();
   232      } else if (rc == WORD && IS_MACRO_DECLARATION) {
   233        tidy_skip_card ();
   234      } else if (strlen (curlex) > 0) {
   235  // Backspace and done.
   236        RESTORE_POS (1);
   237        go_on = FALSE;
   238      }
   239    }
   240  }
   241  
   242  void tidy_vif_extensions(void)
   243  {
   244    if (TOKEN ("exit")) {
   245      tidy_to_upper ();
   246      tidy_skip_card ();
   247    } else if (TOKEN ("break")) {
   248      tidy_to_upper ();
   249      tidy_skip_card ();
   250    } else if (TOKEN ("cycle")) {
   251      tidy_to_upper ();
   252      tidy_skip_card ();
   253    } else {
   254      ERROR (3203, "syntax", curlex);
   255      tidy_skip_card ();
   256    }
   257  }
   258  
   259  void tidy_jump (void)
   260  {
   261    int_4 rc = scan (EXPECT_LABEL);
   262    if (rc == LABEL) {
   263  // GOTO label
   264      LBL *L = find_relabel (curlex);
   265      replace_label (L->renum);
   266      tidy_skip_card ();
   267    } else if (TOKEN ("(")) {
   268  // GOTO (...), expr
   269      rc = scan (EXPECT_LABEL);
   270      while (rc == LABEL) {
   271        LBL *L = find_relabel (curlex);
   272        replace_label (L->renum);
   273        rc = scan (EXPECT_NONE);
   274        if (TOKEN (",")) {
   275          rc = scan (EXPECT_LABEL);
   276        }
   277      };
   278      CHECKPOINT (3204, ")");
   279      tidy_skip_card ();
   280    } else if (rc == WORD) {
   281  // GOTO idf [, (...)]
   282      IDENT *idf = find_local (curlex, NO_MODE);
   283      if (idf == NO_IDENT ) {
   284        return;
   285      }
   286      if (idf->mode.type != INTEGER) {
   287        EXPECT (3205, "integer variable");
   288      }
   289      EXPR var; MODE mode;
   290      var.str[0] = '\0';
   291      factor_variable (&var, idf, &mode, curlex);
   292      rc = scan (EXPECT_NONE);
   293      if (TOKEN (",") || TOKEN ("(")) {
   294    // Emit indicated labels.
   295        if (TOKEN (",")) {
   296          rc = scan (EXPECT_NONE);
   297        }
   298        CHECKPOINT (3206, "(");
   299        rc = scan (EXPECT_LABEL);
   300        while (rc == LABEL) {
   301          LBL *L = find_relabel (curlex);
   302          replace_label (L->renum);
   303          rc = scan (EXPECT_LABEL);
   304          if (TOKEN (",")) {
   305            rc = scan (EXPECT_LABEL);
   306          }
   307        }
   308        CHECKPOINT (3207, ")");
   309        tidy_skip_card ();
   310      } else {
   311      // Default, emit all labels.
   312        tidy_skip_card ();
   313      }
   314    }
   315  }
   316  
   317  void tidy_block_if (EXPR *reg, int_4 depth)
   318  {
   319  // Block IF.
   320    int_4 rc;
   321    tidy_skip_card ();
   322    NEW_RECORD (str);
   323    if (reg->mode.type != LOGICAL) {
   324      EXPECT (3208, "logical expression");
   325    }
   326    tidy_statements (NO_LABEL, depth + 1);
   327    while (TOKEN ("elseif")) {
   328      EXPR reh;
   329      rc = scan ("(");
   330      rc = scan (EXPECT_NONE);
   331      macro_depth = 0;
   332      express (&reh, NOTYPE, NOLEN);
   333      rc = scan (")");
   334      rc = scan ("THEN");
   335      if (reh.mode.type != LOGICAL) {
   336        EXPECT (3209, "logical expression");
   337      }
   338      tidy_statements (NO_LABEL, depth + 1);
   339    }
   340    if (TOKEN ("else")) {
   341      tidy_skip_card ();
   342      tidy_statements (NO_LABEL, depth + 1);
   343    }
   344    if (TOKEN ("endif")) {
   345      tidy_skip_card ();
   346    } else {
   347      EXPECT (3210, "endif");
   348    }
   349    (void) rc;
   350  }
   351  
   352  void tidy_arith_if (EXPR *reg)
   353  {
   354  // Arithmetic IF.
   355    int_4 rc;
   356    NEW_RECORD (str);
   357    NEW_RECORD (tmp);
   358    LBL *L;
   359  // Gather the labels
   360    L = find_relabel (curlex);
   361    replace_label (L->renum);
   362    rc = scan (",");
   363    rc = scan (EXPECT_NONE);
   364    if (rc != INT_NUMBER) {
   365      EXPECT (3211, "label");
   366      return;
   367    }
   368    L = find_relabel (curlex);
   369    replace_label (L->renum);
   370    rc = scan (",");
   371    if (rc == END_OF_LINE) {
   372    // CRAY FORTRAN two-branch arithmetic statement.
   373      ;
   374    } else {
   375    // ANSI FORTRAN three-branch arithmetic statement.
   376      rc = scan (EXPECT_NONE);
   377      if (rc != INT_NUMBER) {
   378        EXPECT (3212, "label");
   379        return;
   380      }
   381      L = find_relabel (curlex);
   382      replace_label (L->renum);
   383    }
   384    tidy_skip_card ();
   385  }
   386  
   387  void tidy_conditional (int_4 depth, logical_4 block_allowed)
   388  {
   389    int_4 rc = scan ("(");
   390    EXPR reg;
   391    rc = scan (EXPECT_NONE);
   392    macro_depth = 0;
   393    express (&reg, NOTYPE, NOLEN);
   394    rc = scan (")");
   395    rc = scan (EXPECT_NONE);
   396    if (TOKEN ("then") && block_allowed) {
   397      tidy_to_upper ();
   398      tidy_block_if (&reg, depth);
   399    } else if (rc == INT_NUMBER) {
   400      tidy_arith_if (&reg);
   401    } else {
   402  // Logical IF.
   403      NEW_RECORD (str);
   404      if (reg.mode.type != LOGICAL) {
   405        EXPECT (3213, "logical expression");
   406      }
   407      _srecordf (str, "if (%s) {\n", reg.str);
   408      if (TOKEN ("if") && IS_NOT_ASSIGNMENT) {
   409        tidy_to_upper ();
   410        tidy_conditional (depth, FALSE);
   411      } else if (TOKEN ("do") && IS_NOT_ASSIGNMENT) {
   412        SYNTAX (3214, "invalid statement in logical IF");
   413      } else if (TOKEN ("end") && IS_NOT_ASSIGNMENT) {
   414        SYNTAX (3215, "invalid statement in logical IF");
   415      } else {
   416        tidy_executable ();
   417      }
   418    }
   419  }
   420  
   421  void tidy_do_loop (LBL * curlbl, int_4 depth)
   422  {
   423    LBL *L;
   424    NEW_RECORD (str);
   425    int_4 rc = scan (EXPECT_LABEL);
   426    if (rc != LABEL) {
   427      L = NO_LABEL;
   428    } else {
   429      L = find_relabel (curlex);
   430      replace_label (L->renum);
   431      if (curlbl != NO_LABEL && L->line > curlbl->line) {
   432        ERROR (3216, "incorrect loop nesting", NO_TEXT);
   433        return;
   434      }
   435      rc = scan (EXPECT_NONE);
   436    }
   437    if (TOKEN ("repeat")) {
   438      tidy_to_upper ();
   439      tidy_skip_card ();
   440      tidy_statements (L, depth + 1);
   441    } else if (TOKEN ("while")) {
   442      tidy_to_upper ();
   443      tidy_skip_card ();
   444    } else {
   445      tidy_skip_card ();
   446      tidy_statements (L, depth + 1);
   447    }
   448  }
   449  
   450  static void tidy_io_specs (char *proc)
   451  {
   452    int_4 rc, parm = 1;
   453  // We accept that only a unit specification follows.
   454    if (curret == INT_NUMBER) {
   455      if (EQUAL (proc, "print")) {
   456        LBL *L = find_relabel (curlex);
   457        replace_label (L->renum);
   458        return;
   459      }
   460      if (EQUAL (proc, "accept")) {
   461        LBL *L = find_relabel (curlex);
   462        replace_label (L->renum);
   463        return;
   464      }
   465    }
   466    if (curret == WORD) {
   467      return;
   468    }
   469    if (TOKEN ("(")) {
   470      rc = scan (EXPECT_NONE); 
   471    } else {
   472      EXPECT (3217, "(");
   473      return;
   474    }
   475  //
   476    while (!TOKEN (")") && rc != END_OF_MODULE) {
   477  // ([UNIT], [FMT] [, FMT=n | FILE=expr | FORM=str | action=str |  DISP=str |  END=n | ERR=n])
   478      if (TOKEN ("unit") && lookahead ("=")) {
   479        rc = scan ("=");
   480        rc = scan (EXPECT_NONE);
   481      } else if (TOKEN ("rec") && lookahead ("=")) {
   482        EXPR rec;
   483        rc = scan ("=");
   484        rc = scan (EXPECT_NONE);
   485        macro_depth = 0;
   486        express (&rec, INTEGER, 4);
   487      } else if (TOKEN ("file") && lookahead ("=")) {
   488        EXPR reg;
   489        rc = scan ("=");
   490        rc = scan (EXPECT_NONE);
   491        macro_depth = 0;
   492        if (express (&reg, CHARACTER, NOLEN)) {
   493          ;
   494        }
   495      } else if (TOKEN ("form") && lookahead ("=")) {
   496        rc = scan ("=");
   497        rc = scan (EXPECT_NONE);
   498        if (MATCH ("formatted")) {
   499          ;
   500        } else if (MATCH ("unformatted")) {
   501          ;
   502        } else {
   503          SYNTAX (3218, curlex);
   504        }
   505      } else if ((TOKEN ("action") || TOKEN ("access")) && lookahead ("=")) {
   506        rc = scan ("=");
   507        rc = scan (EXPECT_NONE);
   508        if (MATCH ("read")) {
   509          ;
   510        } else if (MATCH ("write")) {
   511          ;
   512        } else if (MATCH ("readwrite")) {
   513          ;
   514        } else if (MATCH ("direct")) {
   515          ;
   516        } else {
   517          SYNTAX (3219, curlex);
   518        }
   519      } else if ((TOKEN ("disp") || TOKEN ("status")) && lookahead ("=")) {
   520  // Straight from JCL :-)
   521        rc = scan ("=");
   522        rc = scan (EXPECT_NONE);
   523        if (MATCH ("old")) {
   524          ;
   525        } else if (MATCH ("new")) {
   526          ;
   527        } else if (MATCH ("keep")) {
   528          ;
   529        } else if (MATCH ("delete")) {
   530          ;
   531        } else if (MATCH ("unknown")) {
   532          ;
   533        } else {
   534          SYNTAX (3220, curlex);
   535        }
   536      } else if ((TOKEN ("lrecl") || TOKEN ("recl")) && lookahead ("=")) {
   537        EXPR rec;
   538        rc = scan ("=");
   539        rc = scan (EXPECT_NONE);
   540        macro_depth = 0;
   541        express (&rec, INTEGER, 4);
   542      } else if (TOKEN ("fmt") && lookahead ("=")) {
   543        rc = scan ("=");
   544        rc = scan (EXPECT_NONE);
   545        if (TOKEN ("*")) {
   546          ;
   547        } else if (rc == INT_NUMBER) {
   548          ;
   549        } else if (rc == WORD) {
   550          EXPR fmt;
   551          macro_depth = 0;
   552          express (&fmt, NOTYPE, NOLEN);
   553          ;
   554        } else if (rc == TEXT) {
   555          (void) format_str (curlex);
   556        } else {
   557          SYNTAX (3221, curlex);
   558        }
   559      } else if (TOKEN ("end") && lookahead ("=")) {
   560        rc = scan ("=");
   561        if ((rc = scan (EXPECT_LABEL)) == LABEL) {
   562          LBL *L = find_relabel (curlex);
   563          replace_label (L->renum);
   564        } else {
   565          EXPECT (3222, "label");
   566        }
   567      } else if (TOKEN ("err") && lookahead ("=")) {
   568        rc = scan ("=");
   569        if ((rc = scan (EXPECT_LABEL)) == LABEL) {
   570          LBL *L = find_relabel (curlex);
   571          replace_label (L->renum);
   572        } else {
   573          EXPECT (3223, "label");
   574        }
   575      } else if (TOKEN ("iostat") && lookahead ("=")) {
   576        rc = scan ("=");
   577        rc = scan (EXPECT_NONE);
   578      } else {
   579        if (EQUAL (proc, "encode") || EQUAL (proc, "decode")) {
   580          if (parm == 1 && rc == INT_NUMBER) {
   581            ;
   582          } else if (parm == 2 && TOKEN ("*")) {
   583            ;
   584          } else if (parm == 2 && rc == WORD) {
   585            EXPR fmt;
   586            macro_depth = 0;
   587            express (&fmt, NOTYPE, NOLEN);
   588          } else if (parm == 2 && rc == TEXT) {
   589            (void) format_str (curlex);
   590          } else if (parm == 2 && rc == INT_NUMBER) {
   591            LBL *L = find_relabel (curlex);
   592            replace_label (L->renum);
   593          } else if (parm == 3) {
   594            ;
   595          } else {
   596            SYNTAX (3224, curlex);
   597          }
   598        } else {
   599          if (parm == 1) {
   600            ;
   601          } else if (parm == 2 && TOKEN ("*")) {
   602            ;
   603          } else if (parm == 2 && rc == WORD) {
   604            EXPR fmt;
   605            macro_depth = 0;
   606            express (&fmt, NOTYPE, NOLEN);
   607          } else if (parm == 2 && rc == TEXT) {
   608            (void) format_str (curlex);
   609          } else if (parm == 2 && rc == INT_NUMBER) {
   610            LBL *L = find_relabel (curlex);
   611            replace_label (L->renum);
   612          } else {
   613            SYNTAX (3225, curlex);
   614          }
   615        }
   616      }
   617  // Next item.
   618      parm++;
   619      rc = scan (EXPECT_NONE); 
   620      if (TOKEN (",")) {
   621        rc = scan (EXPECT_NONE); 
   622      } else if (TOKEN (")")) {
   623        ;
   624      } else {
   625        SYNTAX (3226, curlex);
   626      }
   627    }
   628  }
   629  static LBL *relbl = NO_LABEL;
   630  
   631  void tidy_executable (void)
   632  {
   633    int_4 rc = curret;
   634    if (TOKEN ("call") && IS_NOT_ASSIGNMENT) {
   635      tidy_to_upper ();
   636      tidy_skip_card ();
   637    } else if (TOKEN ("continue") && IS_NOT_ASSIGNMENT) {
   638      tidy_to_upper ();
   639      tidy_skip_card ();
   640    } else if (TOKEN ("goto") && IS_NOT_ASSIGNMENT) {
   641      tidy_to_upper ();
   642      tidy_jump ();
   643    } else if (TOKEN ("pause") && IS_NOT_ASSIGNMENT) {
   644      tidy_to_upper ();
   645      tidy_skip_card ();
   646    } else if (TOKEN ("return") && IS_NOT_ASSIGNMENT) {
   647      tidy_to_upper ();
   648      tidy_skip_card ();
   649    } else if (TOKEN ("entry") && IS_NOT_ASSIGNMENT) {
   650      ERROR (3227, "obsolete feature", "entry");
   651      tidy_skip_card ();
   652    } else if (TOKEN ("stop") && IS_NOT_ASSIGNMENT) {
   653      tidy_to_upper ();
   654      tidy_skip_card ();
   655    } else if (TOKEN ("open") && IS_NOT_ASSIGNMENT) {
   656      tidy_io_specs ("open");
   657      tidy_skip_card ();
   658    } else if (TOKEN ("close") && IS_NOT_ASSIGNMENT) {
   659      tidy_io_specs ("close");
   660      tidy_skip_card ();
   661    } else if (TOKEN ("endfile") && IS_NOT_ASSIGNMENT) {
   662      tidy_io_specs ("endfile");
   663      tidy_skip_card ();
   664    } else if (TOKEN ("backspace") && IS_NOT_ASSIGNMENT) {
   665      tidy_io_specs ("backspace");
   666      tidy_skip_card ();
   667    } else if (TOKEN ("rewind") && IS_NOT_ASSIGNMENT) {
   668      tidy_io_specs ("rewind");
   669      tidy_skip_card ();
   670    } else if (TOKEN ("decode") && IS_NOT_ASSIGNMENT) {
   671      tidy_io_specs ("decode");
   672      tidy_skip_card ();
   673    } else if (TOKEN ("encode") && IS_NOT_ASSIGNMENT) {
   674      tidy_io_specs ("encode");
   675      tidy_skip_card ();
   676    } else if (TOKEN ("read") && IS_NOT_ASSIGNMENT) {
   677      tidy_io_specs ("read");
   678      tidy_skip_card ();
   679    } else if (TOKEN ("accept") && IS_NOT_ASSIGNMENT) {
   680      tidy_io_specs ("accept");
   681      tidy_skip_card ();
   682    } else if (TOKEN ("write") && IS_NOT_ASSIGNMENT) {
   683      tidy_io_specs ("write");
   684      tidy_skip_card ();
   685    } else if (TOKEN ("print") && IS_NOT_ASSIGNMENT) {
   686      tidy_io_specs ("print");
   687      tidy_skip_card ();
   688    } else if (TOKEN ("punch") && IS_NOT_ASSIGNMENT) {
   689      tidy_io_specs ("punch");
   690      tidy_skip_card ();
   691    } else if (rc == WORD) {
   692      SAVE_POS (1);
   693      rc = scan (EXPECT_NONE);
   694      if (rc == END_OF_LINE || rc == END_OF_MODULE) {
   695        RESTORE_POS (1);
   696        tidy_vif_extensions ();
   697      } else {
   698        UNSCAN;
   699        tidy_skip_card ();
   700      }
   701    }
   702  }
   703  
   704  void tidy_statements (LBL * dolbl, int_4 depth)
   705  {
   706    int_4 rc;
   707    while ((rc = scan (EXPECT_NONE)) != END_OF_MODULE) {
   708  // FORTRAN statements.
   709      if (rc == LABEL) {
   710        NEW_RECORD (str);
   711        relbl = find_relabel (curlex);
   712        if (relbl == NO_LABEL) {
   713          ERROR (3228, "no such label", curlex);
   714        }
   715        NEW_RECORD (rep);
   716        _srecordf (rep, "%5d", relbl->renum);
   717        for (int_4 k = 0; k < 5; k++) {
   718          CUR_LIN.text[k] = rep[k];
   719        }
   720        rc = scan (EXPECT_NONE);
   721        if (TOKEN ("continue")) {
   722          tidy_to_upper ();
   723          continue;               // Sic!
   724        }
   725      }
   726      if (rc == DECLAR) {
   727        tidy_to_upper ();
   728        tidy_skip_card ();
   729      } else if (TOKEN ("assign")) {
   730        tidy_to_upper ();
   731        rc = scan (EXPECT_LABEL);
   732        if (rc != LABEL) {
   733          SYNTAX (3229, "label expected");
   734        } else {
   735          LBL *L = find_relabel (curlex);
   736          replace_label (L->renum);
   737        }
   738        rc = scan (EXPECT_NONE);
   739        if (TOKEN ("to")) {
   740          tidy_to_upper ();
   741        }
   742        tidy_skip_card ();
   743      } else if (TOKEN ("end") && IS_NOT_ASSIGNMENT) {
   744        tidy_to_upper ();
   745        if (depth != 0) {
   746          SYNTAX (3230, "end must end a subprogram");
   747        }
   748        tidy_skip_card ();
   749        return;
   750      } else if (TOKEN ("elseif") && IS_NOT_ASSIGNMENT) {
   751        tidy_to_upper ();
   752        if (depth > 0) {
   753          return;
   754        } else {
   755          SYNTAX (3231, "stray symbol");
   756        }
   757      } else if (TOKEN ("else") && IS_NOT_ASSIGNMENT) {
   758        tidy_to_upper ();
   759        if (depth > 0) {
   760          return;
   761        } else {
   762          SYNTAX (3232, "stray symbol");
   763        }
   764      } else if (TOKEN ("endif") && IS_NOT_ASSIGNMENT) {
   765        tidy_to_upper ();
   766        if (depth > 0) {
   767          return;
   768        } else {
   769          SYNTAX (3233, "stray symbol");
   770        }
   771      } else if (TOKEN ("until") && IS_NOT_ASSIGNMENT) {
   772        tidy_to_upper ();
   773        tidy_skip_card ();
   774      } else if (TOKEN ("if") && IS_NOT_ASSIGNMENT) {
   775        tidy_to_upper ();
   776        tidy_conditional (depth, TRUE);
   777      } else if (TOKEN ("do") && IS_NOT_ASSIGNMENT) {
   778        tidy_to_upper ();
   779        tidy_do_loop (dolbl, depth);
   780        tidy_skip_card ();
   781      } else if (TOKEN ("enddo") && IS_NOT_ASSIGNMENT) {
   782        tidy_to_upper ();
   783        if (dolbl != NO_LABEL) {
   784          ERROR (3234, "misplaced end do", NO_TEXT);
   785        }
   786        if (depth > 0) {
   787          return;
   788        } else {
   789          SYNTAX (3235, "stray symbol");
   790        }
   791      } else if (TOKEN ("format") && IS_NOT_ASSIGNMENT) {
   792        tidy_to_upper ();
   793        tidy_skip_card ();
   794      } else {
   795        tidy_executable ();
   796      }
   797  // Return for DO loop (ending label reached).
   798      if (dolbl != NO_LABEL && relbl != NO_LABEL && dolbl->num == relbl->num) {
   799        if (depth == 0) {
   800          BUG ("nesting");
   801        }
   802        return;
   803      }
   804    }
   805  }
   806  
   807  void write_tidy (char *name)
   808  {
   809  // Object code to file.
   810    FILE *obj;
   811    if ((obj = fopen (name, "w")) == NULL) {
   812      FATAL (3236, "cannot open for writing", name);
   813      exit (EXIT_FAILURE);
   814    };
   815    for (int_4 k = 1; k < nftnlines; k++) {
   816      fprintf (obj, "%s\n", source[k].text);
   817    }
   818    fclose (obj);
   819  }
   820  
   821  void tidy_source (char *modname)
   822  {
   823    tidy_prescan ();
   824    tidy_subprogram ();
   825    tidy_decls ();
   826    tidy_statements (NO_LABEL, 0);
   827  }


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