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      express (&reh, NOTYPE, NOLEN);
   332      rc = scan (")");
   333      rc = scan ("THEN");
   334      if (reh.mode.type != LOGICAL) {
   335        EXPECT (3209, "logical expression");
   336      }
   337      tidy_statements (NO_LABEL, depth + 1);
   338    }
   339    if (TOKEN ("else")) {
   340      tidy_skip_card ();
   341      tidy_statements (NO_LABEL, depth + 1);
   342    }
   343    if (TOKEN ("endif")) {
   344      tidy_skip_card ();
   345    } else {
   346      EXPECT (3210, "endif");
   347    }
   348    (void) rc;
   349  }
   350  
   351  void tidy_arith_if (EXPR *reg)
   352  {
   353  // Arithmetic IF.
   354    int_4 rc;
   355    NEW_RECORD (str);
   356    NEW_RECORD (tmp);
   357    LBL *L;
   358  // Gather the labels
   359    L = find_relabel (curlex);
   360    replace_label (L->renum);
   361    rc = scan (",");
   362    rc = scan (EXPECT_NONE);
   363    if (rc != INT_NUMBER) {
   364      EXPECT (3211, "label");
   365      return;
   366    }
   367    L = find_relabel (curlex);
   368    replace_label (L->renum);
   369    rc = scan (",");
   370    if (rc == END_OF_LINE) {
   371    // CRAY FORTRAN two-branch arithmetic statement.
   372      ;
   373    } else {
   374    // ANSI FORTRAN three-branch arithmetic statement.
   375      rc = scan (EXPECT_NONE);
   376      if (rc != INT_NUMBER) {
   377        EXPECT (3212, "label");
   378        return;
   379      }
   380      L = find_relabel (curlex);
   381      replace_label (L->renum);
   382    }
   383    tidy_skip_card ();
   384  }
   385  
   386  void tidy_conditional (int_4 depth, logical_4 block_allowed)
   387  {
   388    int_4 rc = scan ("(");
   389    EXPR reg;
   390    rc = scan (EXPECT_NONE);
   391    express (&reg, NOTYPE, NOLEN);
   392    rc = scan (")");
   393    rc = scan (EXPECT_NONE);
   394    if (TOKEN ("then") && block_allowed) {
   395      tidy_to_upper ();
   396      tidy_block_if (&reg, depth);
   397    } else if (rc == INT_NUMBER) {
   398      tidy_arith_if (&reg);
   399    } else {
   400  // Logical IF.
   401      NEW_RECORD (str);
   402      if (reg.mode.type != LOGICAL) {
   403        EXPECT (3213, "logical expression");
   404      }
   405      _srecordf (str, "if (%s) {\n", reg.str);
   406      if (TOKEN ("if") && IS_NOT_ASSIGNMENT) {
   407        tidy_to_upper ();
   408        tidy_conditional (depth, FALSE);
   409      } else if (TOKEN ("do") && IS_NOT_ASSIGNMENT) {
   410        SYNTAX (3214, "invalid statement in logical IF");
   411      } else if (TOKEN ("end") && IS_NOT_ASSIGNMENT) {
   412        SYNTAX (3215, "invalid statement in logical IF");
   413      } else {
   414        tidy_executable ();
   415      }
   416    }
   417  }
   418  
   419  void tidy_do_loop (LBL * curlbl, int_4 depth)
   420  {
   421    LBL *L;
   422    NEW_RECORD (str);
   423    int_4 rc = scan (EXPECT_LABEL);
   424    if (rc != LABEL) {
   425      L = NO_LABEL;
   426    } else {
   427      L = find_relabel (curlex);
   428      replace_label (L->renum);
   429      if (curlbl != NO_LABEL && L->line > curlbl->line) {
   430        ERROR (3216, "incorrect loop nesting", NO_TEXT);
   431        return;
   432      }
   433      rc = scan (EXPECT_NONE);
   434    }
   435    if (TOKEN ("repeat")) {
   436      tidy_to_upper ();
   437      tidy_skip_card ();
   438      tidy_statements (L, depth + 1);
   439    } else if (TOKEN ("while")) {
   440      tidy_to_upper ();
   441      tidy_skip_card ();
   442    } else {
   443      tidy_skip_card ();
   444      tidy_statements (L, depth + 1);
   445    }
   446  }
   447  
   448  static void tidy_io_specs (char *proc)
   449  {
   450    int_4 rc, parm = 1;
   451  // We accept that only a unit specification follows.
   452    if (curret == INT_NUMBER) {
   453      if (EQUAL (proc, "print")) {
   454        LBL *L = find_relabel (curlex);
   455        replace_label (L->renum);
   456        return;
   457      }
   458      if (EQUAL (proc, "accept")) {
   459        LBL *L = find_relabel (curlex);
   460        replace_label (L->renum);
   461        return;
   462      }
   463    }
   464    if (curret == WORD) {
   465      return;
   466    }
   467    if (TOKEN ("(")) {
   468      rc = scan (EXPECT_NONE); 
   469    } else {
   470      EXPECT (3217, "(");
   471      return;
   472    }
   473  //
   474    while (!TOKEN (")") && rc != END_OF_MODULE) {
   475  // ([UNIT], [FMT] [, FMT=n | FILE=expr | FORM=str | action=str |  DISP=str |  END=n | ERR=n])
   476      if (TOKEN ("unit") && lookahead ("=")) {
   477        rc = scan ("=");
   478        rc = scan (EXPECT_NONE);
   479      } else if (TOKEN ("rec") && lookahead ("=")) {
   480        EXPR rec;
   481        rc = scan ("=");
   482        rc = scan (EXPECT_NONE);
   483        express (&rec, INTEGER, 4);
   484      } else if (TOKEN ("file") && lookahead ("=")) {
   485        EXPR reg;
   486        rc = scan ("=");
   487        rc = scan (EXPECT_NONE);
   488        if (express (&reg, CHARACTER, NOLEN)) {
   489          ;
   490        }
   491      } else if (TOKEN ("form") && lookahead ("=")) {
   492        rc = scan ("=");
   493        rc = scan (EXPECT_NONE);
   494        if (MATCH ("formatted")) {
   495          ;
   496        } else if (MATCH ("unformatted")) {
   497          ;
   498        } else {
   499          SYNTAX (3218, curlex);
   500        }
   501      } else if ((TOKEN ("action") || TOKEN ("access")) && lookahead ("=")) {
   502        rc = scan ("=");
   503        rc = scan (EXPECT_NONE);
   504        if (MATCH ("read")) {
   505          ;
   506        } else if (MATCH ("write")) {
   507          ;
   508        } else if (MATCH ("readwrite")) {
   509          ;
   510        } else if (MATCH ("direct")) {
   511          ;
   512        } else {
   513          SYNTAX (3219, curlex);
   514        }
   515      } else if ((TOKEN ("disp") || TOKEN ("status")) && lookahead ("=")) {
   516  // Straight from JCL :-)
   517        rc = scan ("=");
   518        rc = scan (EXPECT_NONE);
   519        if (MATCH ("old")) {
   520          ;
   521        } else if (MATCH ("new")) {
   522          ;
   523        } else if (MATCH ("keep")) {
   524          ;
   525        } else if (MATCH ("delete")) {
   526          ;
   527        } else if (MATCH ("unknown")) {
   528          ;
   529        } else {
   530          SYNTAX (3220, curlex);
   531        }
   532      } else if ((TOKEN ("lrecl") || TOKEN ("recl")) && lookahead ("=")) {
   533        EXPR rec;
   534        rc = scan ("=");
   535        rc = scan (EXPECT_NONE);
   536        express (&rec, INTEGER, 4);
   537      } else if (TOKEN ("fmt") && lookahead ("=")) {
   538        rc = scan ("=");
   539        rc = scan (EXPECT_NONE);
   540        if (TOKEN ("*")) {
   541          ;
   542        } else if (rc == INT_NUMBER) {
   543          ;
   544        } else if (rc == WORD) {
   545          EXPR fmt;
   546          express (&fmt, NOTYPE, NOLEN);
   547          ;
   548        } else if (rc == TEXT) {
   549          (void) format_str (curlex);
   550        } else {
   551          SYNTAX (3221, curlex);
   552        }
   553      } else if (TOKEN ("end") && lookahead ("=")) {
   554        rc = scan ("=");
   555        if ((rc = scan (EXPECT_LABEL)) == LABEL) {
   556          LBL *L = find_relabel (curlex);
   557          replace_label (L->renum);
   558        } else {
   559          EXPECT (3222, "label");
   560        }
   561      } else if (TOKEN ("err") && lookahead ("=")) {
   562        rc = scan ("=");
   563        if ((rc = scan (EXPECT_LABEL)) == LABEL) {
   564          LBL *L = find_relabel (curlex);
   565          replace_label (L->renum);
   566        } else {
   567          EXPECT (3223, "label");
   568        }
   569      } else if (TOKEN ("iostat") && lookahead ("=")) {
   570        rc = scan ("=");
   571        rc = scan (EXPECT_NONE);
   572      } else {
   573        if (EQUAL (proc, "encode") || EQUAL (proc, "decode")) {
   574          if (parm == 1 && rc == INT_NUMBER) {
   575            ;
   576          } else if (parm == 2 && TOKEN ("*")) {
   577            ;
   578          } else if (parm == 2 && rc == WORD) {
   579            EXPR fmt;
   580            express (&fmt, NOTYPE, NOLEN);
   581          } else if (parm == 2 && rc == TEXT) {
   582            (void) format_str (curlex);
   583          } else if (parm == 2 && rc == INT_NUMBER) {
   584            LBL *L = find_relabel (curlex);
   585            replace_label (L->renum);
   586          } else if (parm == 3) {
   587            ;
   588          } else {
   589            SYNTAX (3224, curlex);
   590          }
   591        } else {
   592          if (parm == 1) {
   593            ;
   594          } else if (parm == 2 && TOKEN ("*")) {
   595            ;
   596          } else if (parm == 2 && rc == WORD) {
   597            EXPR fmt;
   598            express (&fmt, NOTYPE, NOLEN);
   599          } else if (parm == 2 && rc == TEXT) {
   600            (void) format_str (curlex);
   601          } else if (parm == 2 && rc == INT_NUMBER) {
   602            LBL *L = find_relabel (curlex);
   603            replace_label (L->renum);
   604          } else {
   605            SYNTAX (3225, curlex);
   606          }
   607        }
   608      }
   609  // Next item.
   610      parm++;
   611      rc = scan (EXPECT_NONE); 
   612      if (TOKEN (",")) {
   613        rc = scan (EXPECT_NONE); 
   614      } else if (TOKEN (")")) {
   615        ;
   616      } else {
   617        SYNTAX (3226, curlex);
   618      }
   619    }
   620  }
   621  static LBL *relbl = NO_LABEL;
   622  
   623  void tidy_executable (void)
   624  {
   625    int_4 rc = curret;
   626    if (TOKEN ("call") && IS_NOT_ASSIGNMENT) {
   627      tidy_to_upper ();
   628      tidy_skip_card ();
   629    } else if (TOKEN ("continue") && IS_NOT_ASSIGNMENT) {
   630      tidy_to_upper ();
   631      tidy_skip_card ();
   632    } else if (TOKEN ("goto") && IS_NOT_ASSIGNMENT) {
   633      tidy_to_upper ();
   634      tidy_jump ();
   635    } else if (TOKEN ("pause") && IS_NOT_ASSIGNMENT) {
   636      tidy_to_upper ();
   637      tidy_skip_card ();
   638    } else if (TOKEN ("return") && IS_NOT_ASSIGNMENT) {
   639      tidy_to_upper ();
   640      tidy_skip_card ();
   641    } else if (TOKEN ("entry") && IS_NOT_ASSIGNMENT) {
   642      ERROR (3227, "obsolete feature", "entry");
   643      tidy_skip_card ();
   644    } else if (TOKEN ("stop") && IS_NOT_ASSIGNMENT) {
   645      tidy_to_upper ();
   646      tidy_skip_card ();
   647    } else if (TOKEN ("open") && IS_NOT_ASSIGNMENT) {
   648      tidy_io_specs ("open");
   649      tidy_skip_card ();
   650    } else if (TOKEN ("close") && IS_NOT_ASSIGNMENT) {
   651      tidy_io_specs ("close");
   652      tidy_skip_card ();
   653    } else if (TOKEN ("endfile") && IS_NOT_ASSIGNMENT) {
   654      tidy_io_specs ("endfile");
   655      tidy_skip_card ();
   656    } else if (TOKEN ("backspace") && IS_NOT_ASSIGNMENT) {
   657      tidy_io_specs ("backspace");
   658      tidy_skip_card ();
   659    } else if (TOKEN ("rewind") && IS_NOT_ASSIGNMENT) {
   660      tidy_io_specs ("rewind");
   661      tidy_skip_card ();
   662    } else if (TOKEN ("decode") && IS_NOT_ASSIGNMENT) {
   663      tidy_io_specs ("decode");
   664      tidy_skip_card ();
   665    } else if (TOKEN ("encode") && IS_NOT_ASSIGNMENT) {
   666      tidy_io_specs ("encode");
   667      tidy_skip_card ();
   668    } else if (TOKEN ("read") && IS_NOT_ASSIGNMENT) {
   669      tidy_io_specs ("read");
   670      tidy_skip_card ();
   671    } else if (TOKEN ("accept") && IS_NOT_ASSIGNMENT) {
   672      tidy_io_specs ("accept");
   673      tidy_skip_card ();
   674    } else if (TOKEN ("write") && IS_NOT_ASSIGNMENT) {
   675      tidy_io_specs ("write");
   676      tidy_skip_card ();
   677    } else if (TOKEN ("print") && IS_NOT_ASSIGNMENT) {
   678      tidy_io_specs ("print");
   679      tidy_skip_card ();
   680    } else if (TOKEN ("punch") && IS_NOT_ASSIGNMENT) {
   681      tidy_io_specs ("punch");
   682      tidy_skip_card ();
   683    } else if (rc == WORD) {
   684      SAVE_POS (1);
   685      rc = scan (EXPECT_NONE);
   686      if (rc == END_OF_LINE || rc == END_OF_MODULE) {
   687        RESTORE_POS (1);
   688        tidy_vif_extensions ();
   689      } else {
   690        UNSCAN;
   691        tidy_skip_card ();
   692      }
   693    }
   694  }
   695  
   696  void tidy_statements (LBL * dolbl, int_4 depth)
   697  {
   698    int_4 rc;
   699    while ((rc = scan (EXPECT_NONE)) != END_OF_MODULE) {
   700  // FORTRAN statements.
   701      if (rc == LABEL) {
   702        NEW_RECORD (str);
   703        relbl = find_relabel (curlex);
   704        if (relbl == NO_LABEL) {
   705          ERROR (3228, "no such label", curlex);
   706        }
   707        NEW_RECORD (rep);
   708        _srecordf (rep, "%5d", relbl->renum);
   709        for (int_4 k = 0; k < 5; k++) {
   710          CUR_LIN.text[k] = rep[k];
   711        }
   712        rc = scan (EXPECT_NONE);
   713        if (TOKEN ("continue")) {
   714          tidy_to_upper ();
   715          continue;               // Sic!
   716        }
   717      }
   718      if (rc == DECLAR) {
   719        tidy_to_upper ();
   720        tidy_skip_card ();
   721      } else if (TOKEN ("assign")) {
   722        tidy_to_upper ();
   723        rc = scan (EXPECT_LABEL);
   724        if (rc != LABEL) {
   725          SYNTAX (3229, "label expected");
   726        } else {
   727          LBL *L = find_relabel (curlex);
   728          replace_label (L->renum);
   729        }
   730        rc = scan (EXPECT_NONE);
   731        if (TOKEN ("to")) {
   732          tidy_to_upper ();
   733        }
   734        tidy_skip_card ();
   735      } else if (TOKEN ("end") && IS_NOT_ASSIGNMENT) {
   736        tidy_to_upper ();
   737        if (depth != 0) {
   738          SYNTAX (3230, "end must end a subprogram");
   739        }
   740        tidy_skip_card ();
   741        return;
   742      } else if (TOKEN ("elseif") && IS_NOT_ASSIGNMENT) {
   743        tidy_to_upper ();
   744        if (depth > 0) {
   745          return;
   746        } else {
   747          SYNTAX (3231, "stray symbol");
   748        }
   749      } else if (TOKEN ("else") && IS_NOT_ASSIGNMENT) {
   750        tidy_to_upper ();
   751        if (depth > 0) {
   752          return;
   753        } else {
   754          SYNTAX (3232, "stray symbol");
   755        }
   756      } else if (TOKEN ("endif") && IS_NOT_ASSIGNMENT) {
   757        tidy_to_upper ();
   758        if (depth > 0) {
   759          return;
   760        } else {
   761          SYNTAX (3233, "stray symbol");
   762        }
   763      } else if (TOKEN ("until") && IS_NOT_ASSIGNMENT) {
   764        tidy_to_upper ();
   765        tidy_skip_card ();
   766      } else if (TOKEN ("if") && IS_NOT_ASSIGNMENT) {
   767        tidy_to_upper ();
   768        tidy_conditional (depth, TRUE);
   769      } else if (TOKEN ("do") && IS_NOT_ASSIGNMENT) {
   770        tidy_to_upper ();
   771        tidy_do_loop (dolbl, depth);
   772        tidy_skip_card ();
   773      } else if (TOKEN ("enddo") && IS_NOT_ASSIGNMENT) {
   774        tidy_to_upper ();
   775        if (dolbl != NO_LABEL) {
   776          ERROR (3234, "misplaced end do", NO_TEXT);
   777        }
   778        if (depth > 0) {
   779          return;
   780        } else {
   781          SYNTAX (3235, "stray symbol");
   782        }
   783      } else if (TOKEN ("format") && IS_NOT_ASSIGNMENT) {
   784        tidy_to_upper ();
   785        tidy_skip_card ();
   786      } else {
   787        tidy_executable ();
   788      }
   789  // Return for DO loop (ending label reached).
   790      if (dolbl != NO_LABEL && relbl != NO_LABEL && dolbl->num == relbl->num) {
   791        if (depth == 0) {
   792          BUG ("nesting");
   793        }
   794        return;
   795      }
   796    }
   797  }
   798  
   799  void write_tidy (char *name)
   800  {
   801  // Object code to file.
   802    FILE *obj;
   803    if ((obj = fopen (name, "w")) == NULL) {
   804      FATAL (3236, "cannot open for writing", name);
   805      exit (EXIT_FAILURE);
   806    };
   807    for (int_4 k = 1; k < nftnlines; k++) {
   808      fprintf (obj, "%s\n", source[k].text);
   809    }
   810    fclose (obj);
   811  }
   812  
   813  void tidy_source (char *modname)
   814  {
   815    tidy_prescan ();
   816    tidy_subprogram ();
   817    tidy_decls ();
   818    tidy_statements (NO_LABEL, 0);
   819  }


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