data.c

     1  //! @file data.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  //! Compile DATA.
    25  
    26  #include <vif.h>
    27  
    28  //
    29  // DATA STATEMENT
    30  //
    31  
    32  void const_list (MODE * mode, int_4 *items)
    33  {
    34    while (WITHIN) {
    35      int_4 rc = scan (EXPECT_NONE);
    36      if (!WITHIN) {
    37        ;
    38      } else {
    39        int_8 repeat = 1;
    40        if (curret == INT_NUMBER) {
    41          repeat = strtoll (curlex, NO_REF_TEXT, 10);
    42          rc = scan (EXPECT_NONE);
    43          if (TOKEN ("*")) {
    44            rc = scan (EXPECT_NONE);
    45          } else {
    46            repeat = 1;
    47            UNSCAN;
    48          }
    49        }
    50        EXPR reg;
    51        factor (&reg);
    52        if (reg.variant != EXPR_CONST) {
    53          EXPECT (801, "constant");
    54        } else if (!accept_mode (reg.mode.type, reg.mode.len, mode->type, mode->len)) {
    55          MODE_ERROR (802, qtype (&(reg.mode)), qtype (mode));
    56        }
    57        for (int_4 k = 0; k < repeat; k++) {
    58          if (reg.mode.type == CHARACTER && mode->type == INTEGER && mode->len == 4) {
    59            NEW_RECORD (str); NEW_RECORD (buf);
    60            _srecordf (str, "%d", _str_to_int4 (get_uniq_str (reg.str, buf)));
    61            code (nprocs, DATA, str);
    62          } else if (reg.mode.type == CHARACTER && mode->type == REAL && mode->len == 8) {
    63            NEW_RECORD (str); NEW_RECORD (buf);
    64            _srecordf (str, "%g", _str_to_real8 (get_uniq_str (reg.str, buf)));
    65            code (nprocs, DATA, str);
    66          } else {
    67            code (nprocs, DATA, reg.str);
    68          }
    69          if (k < repeat - 1) {
    70            code (nprocs, DATA, ",\n");
    71          }
    72        }
    73        (*items) += (int_4) repeat;
    74        rc = scan (EXPECT_NONE);
    75        if (TOKEN ("/")) {
    76          return;
    77        } else if (TOKEN (",")) {
    78          code (nprocs, DATA, ",\n");
    79        }
    80      }
    81      (void) rc;
    82    }
    83  }
    84  
    85  void data_elem (char *data, char *datk, char *datn, MODE * mode, int_4 *items)
    86  {
    87  #define CIRCULAR\
    88    {\
    89      _srecordf (str, "if (%s >= %s) {\n", datk, datn);\
    90      code (nprocs, BODY, str);\
    91      _srecordf (str, "%s = 0;\n", datk);\
    92      code (nprocs, BODY, str);\
    93      code (nprocs, BODY, "}\n");\
    94    }
    95  //
    96    EXPR reg;
    97    factor (&reg);
    98    if ((reg.idf != NO_IDENT) && reg.idf->mode.save == AUTOMATIC) {
    99      ERROR (803, "variable is automatic", C_NAME (reg.idf));
   100    }
   101    if (reg.variant == EXPR_VAR && IS_SCALAR (reg.mode)) {
   102      NEW_RECORD (str);
   103      *mode = reg.idf->mode;
   104      CIRCULAR;
   105      if (mode->type == CHARACTER) {
   106        if (mode->len == 0) {
   107          _srecordf (str, "strcpy (%s, %s[%s++]);\n", reg.str, data, datk);
   108        } else {
   109          _srecordf (str, "bufcpy (%s, %s[%s++], %d);\n", reg.str, data, datk, mode->len);
   110        }
   111      } else {
   112        _srecordf (str, "%s = %s[%s++];\n", reg.str, data, datk);
   113      }
   114      code (nprocs, BODY, str);
   115      (*items)++;
   116    } else if (reg.variant == EXPR_SLICE) {
   117      NEW_RECORD (str);
   118      *mode = reg.idf->mode;
   119      CIRCULAR;
   120      if (mode->type == CHARACTER) {
   121        if (mode->len == 0) {
   122          _srecordf (str, "strcpy (%s, %s[%s++]);\n", reg.str, data, datk);
   123        } else {
   124          _srecordf (str, "bufcpy (%s, %s[%s++], %d);\n", reg.str, data, datk, mode->len);
   125        }
   126      } else {
   127        _srecordf (str, "%s = %s[%s++];\n", reg.str, data, datk);
   128      }
   129      code (nprocs, BODY, str);
   130      (*items)++;
   131    } else if (reg.variant == EXPR_VAR && IS_ROW (reg.mode)) {
   132      NEW_RECORD (str); NEW_RECORD (tmpa); NEW_RECORD (tmpk);
   133      IDENT *ptr;
   134      *mode = reg.idf->mode;
   135      mode->dim = 0;
   136      _srecordf (tmpa, "_arr_%d", nloctmps++);
   137      ptr = add_local (tmpa, mode->type, mode->len, NOUNIQ, NOPATCH, NOARG, LOCAL, TEMP);
   138      ptr->alias = reg.idf;
   139      _srecordf (tmpk, "_k_%d", nloctmps++);
   140      add_local (tmpk, INTEGER, 4, NOUNIQ, NOPATCH, NOARG, LOCAL, TEMP);
   141      _srecordf (str, "for (%s = (%s *) %s, %s = 0; %s < ", tmpa, wtype (mode, NOARG, NOFUN), reg.str, tmpk, tmpk);
   142      code (nprocs, BODY, str);
   143      code_row_len (reg.idf);
   144      _srecordf (str, "; %s++, %s++) {\n", tmpa, tmpk);
   145      code (nprocs, BODY, str);
   146      CIRCULAR;
   147      if (mode->type == CHARACTER) {
   148        if (mode->len == 0) {
   149          _srecordf (str, "strcpy (*(%s), %s[%s++]);\n", tmpa, data, datk);
   150        } else {
   151          _srecordf (str, "bufcpy (*(%s), %s[%s++], %d);\n", tmpa, data, datk, mode->len);
   152        }
   153      } else {
   154        _srecordf (str, "%s[%s] = %s[%s++];\n", reg.str, tmpk, data, datk);
   155      }
   156      code (nprocs, BODY, str);
   157      code (nprocs, BODY, "}\n");
   158      (*mode) = reg.idf->mode;
   159      (*items)++;
   160    } else {
   161      ERROR (804, "cannot initialise", reg.str);
   162    }
   163  #undef CIRCULAR
   164  }
   165  
   166  void data_list (char *data, char *datk, char *datn, MODE * mode, int_4 lpatch, int_4 *nest, int_4 *items)
   167  {
   168    while (WITHIN) {
   169      int_4 rc = scan (EXPECT_NONE);
   170      if (!WITHIN) {
   171        ;
   172      } else if (TOKEN ("/")) {
   173        return;
   174      } else if (TOKEN (",")) {
   175        if (*nest == 0) {
   176          code (nprocs, DATA, "\n");
   177        }
   178      } else if (TOKEN ("(")) {
   179        SAVE_PRE;
   180  // Quick lookahead.
   181        int_4 loop = impl_do ();
   182  // Restore.
   183        RESTORE_POS;
   184        rc = scan ("(");
   185  // Decide.
   186        if (loop) {
   187          (*nest)++;
   188          int_4 where = code (nprocs, BODY, NO_TEXT);
   189          data_list (data, datk, datn, mode, where, nest, items);
   190        } else {
   191          data_elem (data, datk, datn, mode, items);
   192        }
   193      } else if (TOKEN (")")) {
   194  // Expression closed by ')'
   195        (*nest)--;
   196        return;
   197      } else if (rc == WORD) {
   198        if (*nest == 0) {
   199          data_elem (data, datk, datn, mode, items);
   200        } else {
   201  // Implied do-loop?
   202          SAVE_PRE;
   203          rc = scan (EXPECT_NONE);
   204          if (!TOKEN ("=")) {
   205  // Not an implied do-loop.
   206            RESTORE_POS;
   207            rc = scan (EXPECT_NONE);
   208            data_elem (data, datk, datn, mode, items);
   209          } else {
   210  // Implied do-loop!
   211            NEW_RECORD (lid); NEW_RECORD (loop);
   212            EXPR from, to, by;
   213            MODE nmode;
   214            IDENT *idf = impl_decl (prelex, &nmode);
   215            if (idf->arg || idf->alias != NO_IDENT) {
   216              _srecordf (lid, "*%s", C_NAME (idf));
   217            } else {
   218              (void) idf_full_c_name (lid, idf);
   219            }
   220            rc = scan (EXPECT_NONE);
   221            express (&from, idf->mode.type, idf->mode.len);
   222            rc = scan (",");
   223            rc = scan (EXPECT_NONE);
   224            express (&to, idf->mode.type, idf->mode.len);
   225            rc = scan (EXPECT_NONE);
   226            if (TOKEN (",")) {
   227              rc = scan (EXPECT_NONE);
   228              express (&by, idf->mode.type, idf->mode.len);
   229              _srecordf (loop, "for (%s = %s; %s <= %s; %s += %s) {\n", lid, from.str, lid, to.str, lid, by.str);
   230              rc = scan (EXPECT_NONE);
   231            } else {
   232              _srecordf (loop, "for (%s = %s; %s <= %s; %s++) {\n", lid, from.str, lid, to.str, lid);
   233            }
   234            patch (lpatch, loop);
   235            if (TOKEN (")")) {
   236  // Implied DO loop closed by ')'.
   237              (*nest)--;
   238              code (nprocs, BODY, "}; // implied DO \n");
   239            } else {
   240              EXPECT (805, ")");
   241            }
   242            return;
   243          }
   244        }
   245      } else {
   246        data_elem (data, datk, datn, mode, items);
   247      }
   248    }
   249  }
   250  
   251  void do_data (int_4 *nest)
   252  {
   253    int_4 rc, go_on = TRUE;
   254    NEW_RECORD (str);
   255    _srecordf (str, "if (__calls[%d].calls == 0) {\n", nprocs - 1);
   256    code (nprocs, BODY, str);
   257    while (go_on) {
   258      int_4 items = 0, dpatch;
   259      NEW_RECORD (data); NEW_RECORD (datk); NEW_RECORD (datn);
   260      MODE mode;
   261      _srecordf (data, "_data_l_%d", nglobtmps);
   262      _srecordf (datk, "_data_k_%d", nglobtmps);
   263      _srecordf (datn, "_data_n_%d", nglobtmps++);
   264      add_local (datk, INTEGER, 4, NOUNIQ, NOPATCH, NOARG, LOCAL, TEMP);
   265      _srecordf (str, "%s = 0;\n", datk);
   266      code (nprocs, BODY, str);
   267      data_list (data, datk, datn, &mode, ERR, nest, &items);
   268      if (!TOKEN ("/")) {
   269        EXPECT (806, "/");
   270      }
   271      mode.dim = 0;
   272      code (nprocs, DATA, "\n");
   273      cpp_direct (nprocs, curlin, DATA);
   274      _srecordf (str, "#define %s ", datn);
   275      code (nprocs, DATA, str);
   276      dpatch = code (nprocs, DATA, NO_TEXT);
   277      code (nprocs, DATA, "\n");
   278      _srecordf (str, "static %s %s[%s] = {\n", wtype (&mode, NOARG, NOFUN), data, datn);
   279      code (nprocs, DATA, str);
   280      items = 0;
   281      const_list (&mode, &items);
   282      _srecordf (str, "%d", items);
   283      patch (dpatch, str);
   284      code (nprocs, DATA, "\n");
   285      code (nprocs, DATA, "};\n");
   286      if (!TOKEN ("/")) {
   287        EXPECT (807, "/");
   288      }
   289      rc = scan (EXPECT_NONE);
   290      go_on = TOKEN (",");
   291    }
   292    code (nprocs, BODY, "}\n");
   293    if (WITHIN) {
   294      SYNTAX (808, curlex);
   295    }
   296    (void) rc;
   297  }
   298  
   299  void decl_data (void)
   300  {
   301    int_4 go_on = TRUE;
   302    while (go_on) {
   303      SAVE_POS;
   304      int_4 rc = scan (EXPECT_NONE);
   305      if (rc == DECLAR) {
   306        skip_card (FALSE);
   307      } else if (TOKEN ("implicit")) {
   308        skip_card (FALSE);
   309      } else if (TOKEN ("save")) {
   310        skip_card (FALSE);
   311      } else if (TOKEN ("automatic")) {
   312        skip_card (FALSE);
   313      } else if (TOKEN ("parameter")) {
   314        skip_card (FALSE);
   315      } else if (TOKEN ("common")) {
   316        skip_card (FALSE);
   317      } else if (TOKEN ("dimension")) {
   318        skip_card (FALSE);
   319      } else if (TOKEN ("equivalence")) {
   320        skip_card (FALSE);
   321      } else if (TOKEN ("external")) {
   322        skip_card (FALSE);
   323      } else if (TOKEN ("intrinsic")) {
   324        skip_card (FALSE);
   325      } else if (TOKEN ("data")) {
   326        int_4 nest = 0;
   327        do_data (&nest);
   328        skip_card (FALSE);
   329      } else if (rc == WORD && is_macro_decl (curlex)) {
   330        skip_card (FALSE);
   331      } else if (strlen (curlex) > 0) {
   332  // Backspace and done.
   333        RESTORE_POS;
   334        go_on = FALSE;
   335      }
   336    }
   337  }
   338  


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