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


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