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_POS (1);
   180  // Quick lookahead.
   181        int_4 loop = impl_do ();
   182  // Restore.
   183        RESTORE_POS (1);
   184        UNSCAN;
   185        rc = scan ("(");
   186  // Decide.
   187        if (loop) {
   188          (*nest)++;
   189          int_4 where = code (nprocs, BODY, NO_TEXT);
   190          data_list (data, datk, datn, mode, where, nest, items);
   191        } else {
   192          data_elem (data, datk, datn, mode, items);
   193        }
   194      } else if (TOKEN (")")) {
   195  // Expression closed by ')'
   196        (*nest)--;
   197        return;
   198      } else if (rc == WORD) {
   199        if (*nest == 0) {
   200          data_elem (data, datk, datn, mode, items);
   201        } else {
   202  // Implied do-loop?
   203          SAVE_POS (2);
   204          rc = scan (EXPECT_NONE);
   205          if (!TOKEN ("=")) {
   206  // Not an implied do-loop.
   207            RESTORE_POS (2);
   208            UNSCAN;
   209            rc = scan (EXPECT_NONE);
   210            data_elem (data, datk, datn, mode, items);
   211          } else {
   212  // Implied do-loop!
   213            NEW_RECORD (lid); NEW_RECORD (loop);
   214            EXPR from, to, by;
   215            MODE nmode;
   216            IDENT *idf = impl_decl (prelex, &nmode);
   217            if (idf->arg || idf->alias != NO_IDENT) {
   218              _srecordf (lid, "*%s", C_NAME (idf));
   219            } else {
   220              (void) idf_full_c_name (lid, idf);
   221            }
   222            rc = scan (EXPECT_NONE);
   223            express (&from, idf->mode.type, idf->mode.len);
   224            rc = scan (",");
   225            rc = scan (EXPECT_NONE);
   226            express (&to, idf->mode.type, idf->mode.len);
   227            rc = scan (EXPECT_NONE);
   228            if (TOKEN (",")) {
   229              rc = scan (EXPECT_NONE);
   230              express (&by, idf->mode.type, idf->mode.len);
   231              _srecordf (loop, "for (%s = %s; %s <= %s; %s += %s) {\n", lid, from.str, lid, to.str, lid, by.str);
   232              rc = scan (EXPECT_NONE);
   233            } else {
   234              _srecordf (loop, "for (%s = %s; %s <= %s; %s++) {\n", lid, from.str, lid, to.str, lid);
   235            }
   236            patch (lpatch, loop);
   237            if (TOKEN (")")) {
   238  // Implied DO loop closed by ')'.
   239              (*nest)--;
   240              code (nprocs, BODY, "}; // implied DO \n");
   241            } else {
   242              EXPECT (805, ")");
   243            }
   244            return;
   245          }
   246        }
   247      } else {
   248        data_elem (data, datk, datn, mode, items);
   249      }
   250    }
   251  }
   252  
   253  void do_data (int_4 *nest)
   254  {
   255    int_4 rc, go_on = TRUE;
   256    NEW_RECORD (str);
   257    _srecordf (str, "if (__calls[%d].calls == 0) {\n", nprocs - 1);
   258    code (nprocs, BODY, str);
   259    while (go_on) {
   260      int_4 items = 0, dpatch;
   261      NEW_RECORD (data); NEW_RECORD (datk); NEW_RECORD (datn);
   262      MODE mode;
   263      _srecordf (data, "_data_l_%d", nglobtmps);
   264      _srecordf (datk, "_data_k_%d", nglobtmps);
   265      _srecordf (datn, "_data_n_%d", nglobtmps++);
   266      add_local (datk, INTEGER, 4, NOUNIQ, NOPATCH, NOARG, LOCAL, TEMP);
   267      _srecordf (str, "%s = 0;\n", datk);
   268      code (nprocs, BODY, str);
   269      data_list (data, datk, datn, &mode, ERR, nest, &items);
   270      if (!TOKEN ("/")) {
   271        EXPECT (806, "/");
   272      }
   273      mode.dim = 0;
   274      code (nprocs, DATA, "\n");
   275      cpp_direct (nprocs, curlin, DATA);
   276      _srecordf (str, "#define %s ", datn);
   277      code (nprocs, DATA, str);
   278      dpatch = code (nprocs, DATA, NO_TEXT);
   279      code (nprocs, DATA, "\n");
   280      _srecordf (str, "static %s %s[%s] = {\n", wtype (&mode, NOARG, NOFUN), data, datn);
   281      code (nprocs, DATA, str);
   282      items = 0;
   283      const_list (&mode, &items);
   284      _srecordf (str, "%d", items);
   285      patch (dpatch, str);
   286      code (nprocs, DATA, "\n");
   287      code (nprocs, DATA, "};\n");
   288      if (!TOKEN ("/")) {
   289        EXPECT (807, "/");
   290      }
   291      rc = scan (EXPECT_NONE);
   292      go_on = TOKEN (",");
   293    }
   294    code (nprocs, BODY, "}\n");
   295    if (WITHIN) {
   296      SYNTAX (808, curlex);
   297    }
   298    (void) rc;
   299  }
   300  
   301  void decl_data (void)
   302  {
   303    int_4 go_on = TRUE;
   304    while (go_on) {
   305      SAVE_POS (1);
   306      int_4 rc = scan (EXPECT_NONE);
   307      if (rc == DECLAR) {
   308        skip_card (FALSE);
   309      } else if (TOKEN ("implicit") && IS_NOT_ASSIGNMENT) {
   310        skip_card (FALSE);
   311      } else if (TOKEN ("save") && IS_NOT_ASSIGNMENT) {
   312        skip_card (FALSE);
   313      } else if (TOKEN ("automatic") && IS_NOT_ASSIGNMENT) {
   314        skip_card (FALSE);
   315      } else if (TOKEN ("parameter") && IS_NOT_ASSIGNMENT) {
   316        skip_card (FALSE);
   317      } else if (TOKEN ("common") && IS_NOT_ASSIGNMENT) {
   318        skip_card (FALSE);
   319      } else if (TOKEN ("dimension") && IS_NOT_ASSIGNMENT) {
   320        skip_card (FALSE);
   321      } else if (TOKEN ("equivalence") && IS_NOT_ASSIGNMENT) {
   322        skip_card (FALSE);
   323      } else if (TOKEN ("external") && IS_NOT_ASSIGNMENT) {
   324        skip_card (FALSE);
   325      } else if (TOKEN ("intrinsic") && IS_NOT_ASSIGNMENT) {
   326        skip_card (FALSE);
   327      } else if (TOKEN ("data") && IS_NOT_ASSIGNMENT) {
   328        int_4 nest = 0;
   329        do_data (&nest);
   330        skip_card (FALSE);
   331      } else if (rc == WORD && IS_MACRO_DECLARATION) {
   332        skip_card (FALSE);
   333      } else if (strlen (curlex) > 0) {
   334  // Backspace and done.
   335        RESTORE_POS (1);
   336        go_on = FALSE;
   337      }
   338    }
   339  }
   340  


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