transput.c

     
   1  //! @file transput.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-2024 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 Fortran IO.
  25  
  26  #include <vif.h>
  27  
  28  static char *unum (EXPR *unit)
  29  {
  30    if (unit->mode.type == INTEGER) {
  31      return unit->str;
  32    } else {
  33      return "0";
  34    }
  35  }
  36  
  37  void save_iostat (char *iostat)
  38  {
  39    if (iostat != NULL) {
  40      EXPR loc; RECORD ios, str;
  41      MODE mode = (MODE) {.type = INTEGER, .len = 4, .dim = 0};
  42      _srecordf (ios, "%s", iostat);
  43      RECCLR (loc.str);
  44      variable (&loc, NULL, &mode, ios);
  45      if (loc.mode.type == mode.type && loc.mode.len == mode.len) {
  46        _srecordf (str, "%s = errno;\n", loc.str);
  47        code (nprocs, BODY, str);
  48      } else {
  49        MODE_ERROR (2901, qtype (&(loc.mode)), qtype (&mode));
  50      }
  51    }
  52  }
  53  
  54  void io_event (char *proc, EXPR *unit, char *iorc, LBL *endlbl, LBL *errlbl)
  55  {
  56    if (EQUAL (proc, "write")) {
  57      RECORD str;
  58      if (errlbl == NULL) {
  59        _srecordf (str, "_write_err (%s, %s, _ioerr_%s (\"%s\", %s));\n", iorc, unum (unit), proc, stat_start, unum (unit));
  60      } else {
  61        _srecordf (str, "_write_err (%s, %s, goto _l%d);\n", iorc, unum (unit), errlbl->num);
  62      }
  63      code (nprocs, BODY, str);
  64    } else if (EQUAL (proc, "read")) {
  65      RECORD str1, str2, str;
  66      if (endlbl == NULL) {
  67        _srecordf (str1, "_ioend_%s (\"%s\", %s)", proc, stat_start, unum (unit));
  68      } else {
  69        _srecordf (str1, "goto _l%d", endlbl->num);
  70      }
  71      if (errlbl == NULL) {
  72        _srecordf (str2, "_ioerr_%s (\"%s\", %s)", proc, stat_start, unum (unit));
  73      } else {
  74        _srecordf (str2, "goto _l%d", errlbl->num);
  75      }
  76      _srecordf (str, "_read_err (%s, %s, %s, %s);\n", iorc, unum (unit), str1, str2);
  77      code (nprocs, BODY, str);
  78    } else {
  79      BUG ("io_event");
  80    }
  81  }
  82  
  83  void io_parm (EXPR *reg, char *elem)
  84  {
  85    if (reg->variant == EXPR_VAR) {
  86      if (reg->mode.dim > 0) {
  87        _srecordf (elem, "%s", reg->str);
  88      } else if (reg->str[0] == '*') {
  89        _srecordf (elem, "%s", &reg->str[1]);
  90      } else if (reg->mode.type == CHARACTER) {
  91        _srecordf (elem, "%s", reg->str);
  92      } else {
  93        (void) impl_decl (reg->str, NULL);
  94        _srecordf (elem, "&%s", reg->str);
  95      }
  96    } else if (reg->variant == EXPR_SLICE) {
  97      _srecordf (elem, "&%s", reg->str);
  98    } else {
  99      RECORD tmp;
 100      _srecordf (tmp, "%s", edit_tmp (nloctmps++));
 101      if (reg->mode.type == CHARACTER) {
 102        norm_mode (&reg->mode);
 103        if (reg->mode.len == 0) {
 104          add_local (tmp, reg->mode.type, MAX_STRLEN, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
 105          _srecordf (elem, "strcpy (%s, %s);\n", tmp, reg->str);
 106        } else {
 107          add_local (tmp, reg->mode.type, reg->mode.len, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
 108          _srecordf (elem, "bufcpy (%s, %s, %d);\n", tmp, reg->str, reg->mode.len);
 109        }
 110        code (nprocs, BODY, elem);
 111        _srecordf (elem, "%s", tmp);
 112      } else {
 113        add_local (tmp, reg->mode.type, reg->mode.len, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
 114        _srecordf (elem, "%s = %s;\n", tmp, reg->str);
 115        code (nprocs, BODY, elem);
 116        _srecordf (elem, "&%s", tmp);
 117      }
 118    }
 119  }
 120  
 121  void io_text_items (char *proc, EXPR *unit, char *fstr, char *fid, char *iorc, LBL *endlbl, LBL *errlbl)
 122  {
 123    RECORD str;
 124    if (EQUAL (proc, "write")) {
 125      _srecordf (str, "while (%s[%s] != NULL && %s[%s] == FMT_TEXT) {\n", fstr, fid, fstr, fid);
 126      code (nprocs, BODY, str);
 127      _srecordf (str, "%s = _vifprintf (%s, %s[%s + 2], NULL, NOTYPE, 0);\n", iorc, unum (unit), fstr, fid);
 128      code (nprocs, BODY, str);
 129      io_event (proc, unit, iorc, endlbl, errlbl);
 130      _srecordf (str, "%s += 3;\n", fid);
 131      code (nprocs, BODY, str);
 132      code (nprocs, BODY, "}\n");
 133    } else if (EQUAL (proc, "read")) {
 134      _srecordf (str, "while (%s[%s] != NULL && %s[%s] == FMT_TEXT) {\n", fstr, fid, fstr, fid);
 135      code (nprocs, BODY, str);
 136      _srecordf (str, "%s = _vifscanf (%s, %s[%s + 1], NULL, NOTYPE, 0);\n", iorc, unum (unit), fstr, fid);
 137      code (nprocs, BODY, str);
 138      io_event (proc, unit, iorc, endlbl, errlbl);
 139      _srecordf (str, "%s += 3;\n", fid);
 140      code (nprocs, BODY, str);
 141      code (nprocs, BODY, "}\n");
 142    }
 143  }
 144  
 145  void io_format (char *proc, EXPR *unit, char *fstr, char *fid, char *iorc, LBL *endlbl, LBL *errlbl, char *elem, char *type, int_4 len)
 146  {
 147    RECORD str;
 148    if (EQUAL (proc, "write")) {
 149      _srecordf (str, "if (%s[%s] == NULL) {\n", fstr, fid);
 150      code (nprocs, BODY, str);
 151      _srecordf (str, "%s = 0;\n", fid);
 152      code (nprocs, BODY, str);
 153      _srecordf (str, "%s = fprintf (_ffile[%s].unit, \"\\n\");\n", iorc, unum (unit));
 154      code (nprocs, BODY, str);
 155      io_text_items (proc, unit, fstr, fid, iorc, endlbl, errlbl);
 156      code (nprocs, BODY, "};\n");
 157      _srecordf (str, "%s = _vifprintf (%s, %s[%s + 2], %s, %s, %d);\n", iorc, unum (unit), fstr, fid, elem, type, len);
 158      code (nprocs, BODY, str);
 159      io_event (proc, unit, iorc, endlbl, errlbl);
 160      _srecordf (str, "%s += 3;\n", fid);
 161      code (nprocs, BODY, str);
 162      io_text_items (proc, unit, fstr, fid, iorc, endlbl, errlbl);
 163    } else if (EQUAL (proc, "read")) {
 164      _srecordf (str, "if (%s[%s] == NULL) {\n", fstr, fid);
 165      code (nprocs, BODY, str);
 166      _srecordf (str, "%s = 0;\n", fid);
 167      code (nprocs, BODY, str);
 168      _srecordf (str, "_vifscanf (%s, NULL, NULL, NOTYPE, 0);\n", unum (unit));
 169      code (nprocs, BODY, str);
 170      io_text_items (proc, unit, fstr, fid, iorc, endlbl, errlbl);
 171      code (nprocs, BODY, "};\n");
 172      _srecordf (str, "%s = _vifscanf (%s, %s[%s + 1], %s, %s, %d);\n", iorc, unum (unit), fstr, fid, elem, type, len);
 173      code (nprocs, BODY, str);
 174      io_event (proc, unit, iorc, endlbl, errlbl);
 175      _srecordf (str, "%s += 3;\n", fid);
 176      code (nprocs, BODY, str);
 177      io_text_items (proc, unit, fstr, fid, iorc, endlbl, errlbl);
 178    }
 179  }
 180  
 181  void io_elemuf (char *proc, EXPR *unit, EXPR *reg, char *iorc, LBL *endlbl, LBL *errlbl, int_4 *items)
 182  {
 183    RECORD str, elem;
 184    RECCLR (elem);
 185    io_parm (reg, elem);
 186    if (EQUAL (proc, "write")) {
 187      _srecordf (str, "%s = fwrite (%s", iorc, elem);
 188      code (nprocs, BODY, str);
 189    } else if (EQUAL (proc, "read")) {
 190      _srecordf (str, "%s = fread (%s", iorc, elem);
 191      code (nprocs, BODY, str);
 192    } else {
 193      BUG ("io_elemuf");
 194    }
 195    _srecordf (str, ", sizeof (%s), ", wtype (&reg->mode, NOARG, NOFUN));
 196    code (nprocs, BODY, str);
 197    if (reg->variant == EXPR_VAR && reg->mode.dim > 0) {
 198      code_arrlen (reg->idf);
 199    } else {
 200      code (nprocs, BODY, "1");
 201    }
 202    _srecordf (str, ", _ffile[%s].unit);\n", unum (unit));
 203    code (nprocs, BODY, str);
 204    io_event (proc, unit, iorc, endlbl, errlbl);
 205  }
 206  
 207  void io_elemstd (char *proc, EXPR *unit, EXPR *reg, char *fstr, char *fid, char *iorc, LBL *endlbl, LBL *errlbl, int_4 *items)
 208  {
 209    RECORD str, elem;
 210    RECCLR (elem);
 211    io_parm (reg, elem);
 212    if (reg->mode.type == INTEGER) {
 213      if (EQUAL (proc, "write")) {
 214        _srecordf (str, "%s = _vifprintf (%s, \"%%d\", %s, INTEGER, %d);\n", iorc, unum (unit), elem, reg->mode.len);
 215      } else if (EQUAL (proc, "read")) {
 216        _srecordf (str, "%s = _vifscanf (%s, \"%%d\", %s, INTEGER, %d);\n", iorc, unum (unit), elem, reg->mode.len);
 217      }
 218    } else if (reg->mode.type == LOGICAL) {
 219      if (EQUAL (proc, "write")) {
 220        _srecordf (str, "%s = _vifprintf (%s, \"%%c\", %s, LOGICAL, %d);\n", iorc, unum (unit), elem, reg->mode.len);
 221      } else if (EQUAL (proc, "read")) {
 222        _srecordf (str, "%s = _vifscanf (%s, \"%%c\", %s, LOGICAL, %d);\n", iorc, unum (unit), elem, reg->mode.len);
 223      }
 224    } else if (reg->mode.type == REAL) {
 225      if (EQUAL (proc, "write")) {
 226        RECORD fmt;
 227        if (reg->mode.len == 32) {
 228          _srecordf (fmt, "\"%%.%de\"", FLT256_DIG);
 229          _srecordf (str, "%s = _vifprintf (%s, %s, %s, REAL, %d);\n", iorc, unum (unit), fmt, elem, reg->mode.len);
 230        } else if (reg->mode.len == 16) {
 231          _srecordf (fmt, "\"%%.%de\"", FLT128_DIG);
 232          _srecordf (str, "%s = _vifprintf (%s, %s, %s, REAL, %d);\n", iorc, unum (unit), fmt, elem, reg->mode.len);
 233        } else if (reg->mode.len == 8) {
 234          _srecordf (fmt, "\"%%.%de\"", DBL_DIG);
 235          _srecordf (str, "%s = _vifprintf (%s, %s, %s, REAL, %d);\n", iorc, unum (unit), fmt, elem, reg->mode.len);
 236        } else if (reg->mode.len == 4) {
 237          _srecordf (fmt, "\"%%.%de\"", FLT_DIG);
 238          _srecordf (str, "%s = _vifprintf (%s, %s, %s, REAL, %d);\n", iorc, unum (unit), fmt, elem, reg->mode.len);
 239        }
 240      } else if (EQUAL (proc, "read")) {
 241        _srecordf (str, "%s = _vifscanf (%s, \"%%e\", %s, REAL, %d);\n", iorc, unum (unit), elem, reg->mode.len);
 242      }
 243    } else if (reg->mode.type == COMPLEX) {
 244      if (EQUAL (proc, "write")) {
 245        RECORD fmt;
 246        if (reg->mode.len == 8) {
 247          _srecordf (fmt, "\"%%.%de\"", FLT_DIG);
 248        } else if (reg->mode.len == 16) {
 249          _srecordf (fmt, "\"%%.%de\"", DBL_DIG);
 250        } else if (reg->mode.len == 32) {
 251          _srecordf (fmt, "\"%%.%de\"", FLT128_DIG);
 252        } else if (reg->mode.len == 64) {
 253          _srecordf (fmt, "\"%%.%de\"", FLT256_DIG);
 254        }
 255        _srecordf (str, "%s = _vifprintf (%s, %s, %s, COMPLEX, %d);\n", iorc, unum (unit), fmt, elem, reg->mode.len);
 256        code (nprocs, BODY, str);
 257        io_event (proc, unit, iorc, endlbl, errlbl);
 258        _srecordf (str, "%s = _vifprintf (%s, \" \", NULL, NOTYPE, 0);\n", iorc, unum (unit));
 259        code (nprocs, BODY, str);
 260        io_event (proc, unit, iorc, endlbl, errlbl);
 261        _srecordf (str, "%s = _vifprintf (%s, %s, %s, COMPLEX, -%d);\n", iorc, unum (unit), fmt, elem, reg->mode.len);
 262      } else if (EQUAL (proc, "read")) {
 263        _srecordf (str, "%s = _vifscanf (%s, \"%%e\", %s, COMPLEX, %d);\n", iorc, unum (unit), elem, reg->mode.len);
 264        code (nprocs, BODY, str);
 265        io_event (proc, unit, iorc, endlbl, errlbl);
 266        _srecordf (str, "%s = _vifscanf (%s, \"%%e\", %s, COMPLEX, -%d);\n", iorc, unum (unit), elem, reg->mode.len);
 267      }
 268    } else if (reg->mode.type == CHARACTER) {
 269      if (EQUAL (proc, "write")) {
 270  //    _srecordf (str, "%s = _vifprintf (%s, \"%%-%ds\", %s, CHARACTER, %d);\n", iorc, unum (unit), reg->mode.len, elem, reg->mode.len);
 271        _srecordf (str, "%s = _vifprintf (%s, \"%%s\", %s, CHARACTER, %d);\n", iorc, unum (unit), elem, reg->mode.len);
 272      } else if (EQUAL (proc, "read")) {
 273  //    _srecordf (str, "%s = _vifscanf (%s, \"%%%ds\", %s, CHARACTER, %d);\n", iorc, unum (unit), reg->mode.len, elem, reg->mode.len);
 274        _srecordf (str, "%s = _vifscanf (%s, \"%%s\", %s, CHARACTER, %d);\n", iorc, unum (unit), elem, reg->mode.len);
 275      }
 276    }
 277    code (nprocs, BODY, str);
 278    io_event (proc, unit, iorc, endlbl, errlbl);
 279    (*items) ++;
 280  }
 281  
 282  void io_elemf (char *proc, EXPR *unit, EXPR *reg, char *fstr, char *fid, char *iorc, LBL *endlbl, LBL *errlbl, int_4 *items)
 283  {
 284    RECORD elem;
 285    RECCLR (elem);
 286    io_parm (reg, elem);
 287    if (reg->mode.type == INTEGER) {
 288      io_format (proc, unit, fstr, fid, iorc, endlbl, errlbl, elem, "INTEGER", reg->mode.len);
 289      (*items) ++;
 290    } else if (reg->mode.type == LOGICAL) {
 291      io_format (proc, unit, fstr, fid, iorc, endlbl, errlbl, elem, "LOGICAL", reg->mode.len);
 292      (*items) ++;
 293    } else if (reg->mode.type == REAL) {
 294      io_format (proc, unit, fstr, fid, iorc, endlbl, errlbl, elem, "REAL", reg->mode.len);
 295      (*items) ++;
 296    } else if (reg->mode.type == COMPLEX) {
 297      io_format (proc, unit, fstr, fid, iorc, endlbl, errlbl, elem, "COMPLEX", reg->mode.len);
 298      io_format (proc, unit, fstr, fid, iorc, endlbl, errlbl, elem, "COMPLEX", -reg->mode.len);
 299      (*items) ++;
 300    } else if (reg->mode.type == CHARACTER) {
 301      io_format (proc, unit, fstr, fid, iorc, endlbl, errlbl, elem, "CHARACTER", reg->mode.len);
 302      (*items) ++;
 303    }
 304  }
 305  
 306  void io_array (char *proc, EXPR *unit, EXPR *reg, int_4 form, char *fstr, char *fid, char *iorc, LBL *endlbl, LBL *errlbl, int_4 *items)
 307  {
 308    RECORD str, tmpa, tmpk;
 309    EXPR elem;
 310    IDENT *ptr;
 311    _srecordf (tmpa, "_arr_%d", nloctmps++);
 312    ptr = add_local (tmpa, reg->mode.type, reg->mode.len, NOUNIQ, NOPATCH, NOARG, LOCAL, TEMP);
 313    ptr->alias = reg->idf;
 314    _srecordf (tmpk, "_k_%d", nloctmps++);
 315    add_local (tmpk, INTEGER, 4, NOUNIQ, NOPATCH, NOARG, LOCAL, TEMP);
 316    _srecordf (str, "for (%s = %s %s, %s = 0; %s < ", tmpa, ptr_to_array (ptr, NOCONST, CAST, ACTUAL), reg->str, tmpk, tmpk);
 317    code (nprocs, BODY, str);
 318    code_arrlen (reg->idf);
 319    _srecordf (str, "; %s++, %s++) {\n", tmpa, tmpk);
 320    code (nprocs, BODY, str);
 321    memcpy (&elem, reg, sizeof (EXPR));
 322    elem.mode.dim = 0;
 323    if (EQUAL (proc, "read")) {
 324      _srecordf (elem.str, "%s", tmpa);
 325    } else if (EQUAL (proc, "write")) {
 326      _srecordf (elem.str, "*%s", tmpa);
 327    } else {
 328      BUG ("io_array");
 329    }
 330    if (form == STDFORMAT) {
 331      io_elemstd (proc, unit, &elem, fstr, fid, iorc, endlbl, errlbl, items);
 332    } else if (form == FORMATTED) {
 333      io_elemf (proc, unit, &elem, fstr, fid, iorc, endlbl, errlbl, items);
 334    }
 335    code (nprocs, BODY, "}\n");
 336  }
 337  
 338  void io_elem (char *proc, EXPR *unit, int_4 form, char *fstr, char *fid, char *iorc, LBL *endlbl, LBL *errlbl, int_4 *items)
 339  {
 340    EXPR reg;
 341    express (&reg, NOTYPE, 0);
 342    if (form == UNFORMATTED) {
 343      io_elemuf (proc, unit, &reg, iorc, endlbl, errlbl, items);
 344    } else if (form == STDFORMAT) {
 345      if (reg.variant == EXPR_VAR && reg.mode.dim > 0) {
 346        io_array (proc, unit, &reg, form, fstr, fid, iorc, endlbl, errlbl, items);
 347      } else {
 348        io_elemstd (proc, unit, &reg, fstr, fid, iorc, endlbl, errlbl, items);
 349      }
 350    } else if (form == FORMATTED) {
 351      if (reg.variant == EXPR_VAR && reg.mode.dim > 0) {
 352        io_array (proc, unit, &reg, form, fstr, fid, iorc, endlbl, errlbl, items);
 353      } else {
 354        io_elemf (proc, unit, &reg, fstr, fid, iorc, endlbl, errlbl, items);
 355      }
 356    } else {
 357      BUG ("IO formatting unspecified");
 358    }
 359  }
 360  
 361  int_4 impl_do (void)
 362  {
 363  // Quick check whether (...) in a list is an implied DO loop.
 364    int_4 rc, nest = 1;
 365    while ((rc = scan (NULL)) != END_OF_LINE) {
 366      if (TOKEN ("(")) {
 367        nest++;
 368      } else if (TOKEN (")")) {
 369        nest--;
 370        if (nest == 0) {
 371          return FALSE;
 372        }
 373      } else if (nest == 1 && TOKEN (",")) {
 374  // Trigger is the sequence ", I =" in outer nest.
 375        rc = scan (NULL);
 376        if (rc == WORD) {
 377          RECORD name;
 378          strcpy (name, curlex);
 379          rc = scan (NULL);
 380          if (TOKEN ("=")) {
 381            (void) impl_decl (name, NULL);
 382            return TRUE;
 383          } else {
 384            UNSCAN;
 385          }
 386        }
 387      }
 388    }
 389    (void) rc;
 390    return FALSE;
 391  }
 392  
 393  void io_list (char *proc, EXPR *unit, int_4 form, char *fstr, char *fid, char *iorc, LBL *endlbl, LBL *errlbl, int_4 lpatch, int_4 *nest, int_4 *items)
 394  {
 395    while (WITHIN) {
 396      int_4 rc;
 397      if (TOKEN (",")) {
 398        rc = scan (NULL);
 399        if (! WITHIN) {
 400          SYNTAX (2902, prelex);
 401          break;
 402        }
 403        if (TOKEN (",")) {
 404          SYNTAX (2903, ",,");
 405          continue;
 406        }
 407      } else {
 408        rc = scan (NULL);
 409        if (TOKEN (",")) {
 410          continue;
 411        }
 412      }
 413      if (! WITHIN) {
 414        break;
 415      }
 416      if (TOKEN ("(")) {
 417        SAVE_PRE;
 418  // Quick lookahead.
 419        int_4 loop = impl_do ();
 420  // Restore.
 421        RESTORE_POS;
 422        rc = scan ("(");
 423  // Decide.
 424        if (loop) {
 425          (*nest)++;
 426          int_4 where = code (nprocs, BODY, NULL);
 427          io_list (proc, unit, form, fstr, fid, iorc, endlbl, errlbl, where, nest, items);
 428        } else {
 429          io_elem (proc, unit, form, fstr, fid, iorc, endlbl, errlbl, items);
 430          rc = scan (NULL);
 431        }
 432      } else if (TOKEN (")")) {
 433  // Expression closed by ')'
 434        (*nest)--;
 435        return;
 436      } else if (rc == WORD) {
 437        if (*nest == 0) {
 438          io_elem (proc, unit, form, fstr, fid, iorc, endlbl, errlbl, items);
 439          rc = scan (NULL);
 440        } else {
 441          SAVE_PRE;
 442          rc = scan (NULL);
 443          if (!TOKEN ("=")) {
 444            RESTORE_POS;
 445            rc = scan (NULL);
 446            io_elem (proc, unit, form, fstr, fid, iorc, endlbl, errlbl, items);
 447            rc = scan (NULL);
 448          } else {
 449            RECORD lid, loop;
 450            EXPR from, to, by;
 451            MODE mode;
 452            IDENT *idf = impl_decl (prelex, &mode);
 453            if (idf->arg || idf->alias != NULL) {
 454              _srecordf (lid, "*%s", CID (idf));
 455            } else if (idf->common == EXTERN) {
 456              _srecordf (lid, "%s->%s", commons[idf->common], CID (idf));
 457            } else if (idf->common > 0) {
 458              _srecordf (lid, "%s.%s", commons[idf->common], CID (idf));
 459            } else {
 460              _srecordf (lid, "%s", CID (idf));
 461            }
 462            rc = scan (NULL);
 463            express (&from, idf->mode.type, idf->mode.len);
 464            rc = scan (",");
 465            rc = scan (NULL);
 466            express (&to, idf->mode.type, idf->mode.len);
 467            rc = scan (NULL);
 468            if (TOKEN (",")) {
 469              rc = scan (NULL);
 470              express (&by, idf->mode.type, idf->mode.len);
 471              _srecordf (loop, "for (%s = %s; %s <= %s; %s += %s) {\n", 
 472                        lid, from.str, lid, to.str, lid, by.str);
 473              rc = scan (NULL);
 474            } else {
 475              _srecordf (loop, "for (%s = %s; %s <= %s; %s++) {\n", 
 476                        lid, from.str, lid, to.str, lid);
 477            }
 478            patch (lpatch, loop);
 479            if (TOKEN (")")) {
 480  // Implied DO loop closed by ')'.
 481              (*nest)--;
 482              code (nprocs, BODY, "}; // implied DO \n");
 483            } else {
 484              EXPECT (2904, ")");
 485            }
 486            return;
 487          }
 488        }
 489      } else {
 490        io_elem (proc, unit, form, fstr, fid, iorc, endlbl, errlbl, items);
 491        rc = scan (NULL);
 492      }
 493    }
 494  }
 495  
 496  void io_unit (EXPR *unit, int_4 defunit)
 497  {
 498  // Reasonable default.
 499    unit->mode.type = INTEGER;
 500    unit->mode.len = 4;
 501  //
 502    if (TOKEN ("*")) {
 503      _srecordf (unit->str, "%d", defunit);
 504    } else if (TOKEN ("stdin")) {
 505      _srecordf (unit->str, "STDF_IN");
 506    } else if (TOKEN ("stdout")) {
 507      _srecordf (unit->str, "STDF_OUT");
 508    } else if (TOKEN ("stderr")) {
 509      _srecordf (unit->str, "STDF_ERR");
 510    } else {
 511      EXPR reg;
 512      express (&reg, NOTYPE, NOLEN);
 513      if (reg.mode.type == INTEGER) {
 514        if (reg.variant == EXPR_CONST) {
 515          _srecordf (unit->str, "%s", reg.str);
 516          int_4 val;
 517          (void) isint_4 (unit->str, &val);
 518          if (val < 1 || val > MAX_FILES - 1) {
 519            ERROR (2905, "unit number out of range", unit->str);
 520          }
 521        } else {
 522          RECORD str;
 523          _srecordf (unit->str, "%s", edit_unit (nloctmps++));
 524          add_local (unit->str, INTEGER, 4, NOUNIQ, NOPATCH, NOARG, LOCAL, TEMP);
 525          _srecordf (str, "%s = %s;\n", unit, reg.str);
 526          code (nprocs, BODY, str);
 527        }   
 528      } else if (reg.mode.type == CHARACTER) {
 529        if (reg.variant == EXPR_CONST) {
 530          ERROR (2906, "unit cannot be a denotation", unit->str);
 531        } else {
 532          _srecordf (unit->str, "%s", reg.str);
 533          unit->mode = reg.mode;
 534        }
 535      } else {
 536        ERROR (2907, "unit must be INTEGER or CHARACTER", NULL);
 537      }
 538    }
 539  }
 540  
 541  void io_specs (EXPR *unit, int_4 defunit, char *fmt, char **fn, char **form, char **action, int_4 *lrecl, char **disp, LBL **end, LBL **err, char **iostat)
 542  {
 543    int_4 rc, parm = 1;
 544    unit->str[0] = '\0';
 545    fmt[0] = '\0';
 546    *form = form_formatted;
 547    *fn = NULL;
 548    *action = action_default;
 549    *disp = disp_old;
 550    *end = NULL;
 551    *err = NULL;
 552    *iostat = NULL;
 553  //
 554    rc = scan (NULL); 
 555    while (!TOKEN (")") && rc != END_OF_MODULE) {
 556  // ([UNIT], [FMT] [, FMT=n | FILE=expr | FORM=str | action=str |  DISP=str |  END=n | ERR=n])
 557      if (TOKEN ("*") && parm == 2) {
 558        *form = form_formatted;
 559      } else if (rc == TEXT && parm == 2) {
 560        int_4 k = format_str (curlex);
 561        _srecordf (fmt, "%d", k);
 562        *form = form_formatted;
 563      } else if (TOKEN ("unit")) {
 564        rc = scan ("=");
 565        rc = scan (NULL);
 566        io_unit (unit, defunit);
 567      } else if (TOKEN ("file")) {
 568        EXPR reg;
 569        rc = scan ("=");
 570        rc = scan (NULL);
 571        if (express (&reg, CHARACTER, NOLEN)) {
 572          *fn = stralloc (reg.str);
 573        }
 574      } else if (TOKEN ("form")) {
 575        rc = scan ("=");
 576        rc = scan (NULL);
 577        if (TOKEN ("formatted")) {
 578          *form = form_formatted;
 579        } else if (TOKEN ("unformatted")) {
 580          *form = form_unformatted;
 581        } else {
 582          SYNTAX (2908, "invalid FORM specification");
 583        }
 584      } else if (TOKEN ("action") || TOKEN ("access")) {
 585        rc = scan ("=");
 586        rc = scan (NULL);
 587        if (TOKEN ("read")) {
 588          *action = action_read;
 589        } else if (TOKEN ("write")) {
 590          *action = action_write;
 591        } else if (TOKEN ("readwrite")) {
 592          *action = action_readwrite;
 593        } else {
 594          SYNTAX (2909, "invalid ACCESS specification");
 595        }
 596      } else if (TOKEN ("disp") || TOKEN ("status")) {
 597  // Straight from JCL :-)
 598        rc = scan ("=");
 599        rc = scan (NULL);
 600        if (TOKEN ("\"old\"")) {
 601          *disp = disp_old;
 602        } else if (TOKEN ("\"new\"")) {
 603          *disp = disp_new;
 604        } else if (TOKEN ("\"keep\"")) {
 605          *disp = disp_keep;
 606        } else if (TOKEN ("\"delete\"")) {
 607          *disp = disp_delete;
 608        } else if (TOKEN ("\"unknown\"")) {
 609          *disp = disp_new;
 610        } else {
 611          SYNTAX (2910, "invalid DISP specification");
 612        }
 613      } else if (TOKEN ("lrecl")) {
 614        rc = scan ("=");
 615        if ((rc = scan (NULL)) == INT_NUMBER) {
 616          (void) isint_4 (curlex, lrecl);
 617        } else {
 618          EXPECT (2911, "record length");
 619        }
 620      } else if (TOKEN ("fmt")) {
 621        rc = scan ("=");
 622        rc = scan (NULL);
 623        if (TOKEN ("*")) {
 624          fmt[0] = '\0';
 625          *form = form_formatted;
 626        } else if (rc == WORD || rc == INT_NUMBER) {
 627          bufcpy (fmt, curlex, RECLN);
 628          *form = form_formatted;
 629        } else if (rc == TEXT) {
 630          int_4 k = format_str (curlex);
 631          _srecordf (fmt, "%d", k);
 632          *form = form_formatted;
 633        } else {
 634          EXPECT (2912, "label or format string");
 635        }
 636      } else if (TOKEN ("end")) {
 637        rc = scan ("=");
 638        if ((rc = scan (NULL)) == INT_NUMBER) {
 639          if (((*end) = find_label (curlex)) == NULL) {
 640            ERROR (2913, "no such label", curlex);
 641          }
 642          (*end)->jumped++;
 643        } else {
 644          EXPECT (2914, "label");
 645        }
 646      } else if (TOKEN ("err")) {
 647        rc = scan ("=");
 648        if ((rc = scan (NULL)) == INT_NUMBER) {
 649          if (((*err) = find_label (curlex)) == NULL) {
 650            ERROR (2915, "no such label", curlex);
 651          }
 652          (*err)->jumped++;
 653        } else {
 654          EXPECT (2916, "label");
 655        }
 656      } else if (TOKEN ("iostat")) {
 657        rc = scan ("=");
 658        rc = scan (NULL);
 659        if (rc != WORD) {
 660          EXPECT (2917, "variable")
 661        } else {
 662          *iostat = stralloc (curlex);
 663        }
 664      } else if ((rc == WORD || rc == INT_NUMBER) && parm == 2) {
 665        bufcpy (fmt, curlex, RECLN);
 666        *form = form_formatted;
 667      } else if (parm == 1) {
 668        io_unit (unit, defunit);
 669      } else {
 670        SYNTAX (2918, curlex);
 671      }
 672  // Next item.
 673      parm++;
 674      rc = scan (NULL); 
 675      if (TOKEN (",")) {
 676        rc = scan (NULL); 
 677      } else if (TOKEN (")")) {
 678        ;
 679      } else {
 680        SYNTAX (2919, curlex);
 681      }
 682    }
 683  }
 684  
 685  void vif_close (void)
 686  {
 687    int_4 rc, lrecl = 0;
 688    char *daction = NULL, *ddisp = NULL, *dfn = NULL, *dform = NULL, *iostat = NULL;
 689    RECORD str, fmt;
 690    EXPR unit;
 691    LBL *endlbl = NULL, *errlbl = NULL;
 692    RECCLR (fmt);
 693    rc = scan (NULL);
 694    io_specs (&unit, ERR, fmt, &dfn, &dform, &daction, &lrecl, &ddisp, &endlbl, &errlbl, &iostat);
 695    _srecordf (str, "_fcheck (\"%s\", %s, NULL, NULL);\n", stat_start, unum (&unit));
 696    code (nprocs, BODY, str);
 697    _srecordf (str, "if (_ffile[%s].unit != NULL) {\n", unum (&unit));
 698    code (nprocs, BODY, str);
 699    _srecordf (str, "_funregister (\"%s\", %s);\n", stat_start, unum (&unit));
 700    code (nprocs, BODY, str);
 701    if (iostat != NULL) {
 702      RECORD ios;
 703      _srecordf (ios, "%s = errno;\n", iostat);
 704      code (nprocs, BODY, ios);
 705    } else {
 706      code (nprocs, BODY, "if (errno != 0) {\n");
 707      if (errlbl == NULL) {
 708        _srecordf (str, "_ioerr (\"%s\", %s);\n", stat_start, unum (&unit));
 709      } else {
 710        _srecordf (str, "goto _l%d;\n", errlbl->num);
 711      }
 712      code (nprocs, BODY, str);
 713      code (nprocs, BODY, "}\n");
 714      code (nprocs, BODY, "}\n");
 715    }
 716    (void) rc;
 717  }
 718  
 719  void vif_rewind (void)
 720  {
 721    int_4 rc, lrecl = 0;
 722    char *daction = NULL, *ddisp = NULL, *dfn = NULL, *dform = NULL, *iostat = NULL;
 723    RECORD str, fmt;
 724    EXPR unit;
 725    LBL *endlbl = NULL, *errlbl = NULL;
 726    RECCLR (fmt);
 727    rc = scan (NULL);
 728    io_specs (&unit, ERR, fmt, &dfn, &dform, &daction, &lrecl, &ddisp, &endlbl, &errlbl, &iostat);
 729    _srecordf (str, "_fcheck (\"%s\", %s, NULL, NULL);\n", stat_start, unum (&unit));
 730    code (nprocs, BODY, str);
 731    _srecordf (str, "if (_ffile[%s].unit != NULL) {\n", unum (&unit));
 732    code (nprocs, BODY, str);
 733    _srecordf (str, "rewind (%s);\n", unum (&unit));
 734    code (nprocs, BODY, str);
 735    if (iostat != NULL) {
 736      RECORD ios;
 737      _srecordf (ios, "%s = errno;\n", iostat);
 738      code (nprocs, BODY, ios);
 739    } else {
 740      code (nprocs, BODY, "if (errno != 0) {\n");
 741      if (errlbl == NULL) {
 742        _srecordf (str, "_ioerr (\"%s\", %s);\n", stat_start, unum (&unit));
 743      } else {
 744        _srecordf (str, "goto _l%d;\n", errlbl->num);
 745      }
 746      code (nprocs, BODY, str);
 747      code (nprocs, BODY, "}\n");
 748      code (nprocs, BODY, "}\n");
 749    }
 750    (void) rc;
 751  }
 752  
 753  void vif_open (void)
 754  {
 755    int_4 rc, lrecl = 0;
 756    char *daction = NULL, *dfn = NULL, *dform = NULL, *ddisp = NULL, *iostat = NULL;
 757    LBL *endlbl = NULL, *errlbl = NULL;
 758    RECORD str, fmt;
 759    EXPR unit;
 760    RECCLR (fmt);
 761    rc = scan (NULL);
 762    io_specs (&unit, ERR, fmt, &dfn, &dform, &daction, &lrecl, &ddisp, &endlbl, &errlbl, &iostat);
 763    if (dfn != NULL) {
 764      _srecordf (str, "_fregister (\"%s\", %s, %d, %s, %s, %s, %s);\n", stat_start, unum (&unit), lrecl, dfn, dform, daction, ddisp);
 765    } else {
 766      _srecordf (str, "_fregister (\"%s\", %s, %d, NULL, %s, %s, %s);\n", stat_start, unum (&unit), lrecl, dform, daction, ddisp);
 767    }
 768    code (nprocs, BODY, str);
 769    if (iostat != NULL) {
 770      RECORD ios;
 771      _srecordf (ios, "%s = errno;\n", iostat);
 772      code (nprocs, BODY, ios);
 773    }
 774    (void) rc;
 775  }
 776  
 777  void do_io (char *proc, int_4 *nest)
 778  {
 779    int_4 form = UNFORMATTED, lrecl = 0;
 780    LBL *endlbl = NULL, *errlbl = NULL;
 781    RECORD fstr, fid, iorc, str, fmt;
 782    char *daction = NULL, *ddisp = NULL, *dfn = NULL, *dform = NULL, *iostat = NULL;
 783    EXPR unit;
 784    unit.mode.type = INTEGER;
 785    unit.mode.len = 4;
 786    fmt[0] = '\0';
 787    fstr[0] = '\0';
 788    fid[0] = '\0';
 789    iorc[0] = '\0';
 790    int_4 rc = scan (NULL);
 791    if (EQUAL (proc, "read") || EQUAL (proc, "accept")) {
 792      if (TOKEN ("*")) {
 793        _srecordf (unit.str, "STDF_IN");
 794        dform = form_formatted;
 795        rc = scan (NULL);
 796      } else if (rc == INT_NUMBER) { // FORTRAN II
 797        _srecordf (unit.str, "STDF_IN");
 798        bufcpy (fmt, curlex, RECLN);
 799        dform = form_formatted;
 800        rc = scan (NULL);
 801      } else if (rc == TEXT) {
 802        _srecordf (unit.str, "STDF_IN");
 803        int_4 k = format_str (curlex);
 804        _srecordf (fmt, "%d", k);
 805        dform = form_formatted;
 806        rc = scan (NULL);
 807      } else {
 808        io_specs (&unit, STDF_IN, fmt, &dfn, &dform, &daction, &lrecl, &ddisp, &endlbl, &errlbl, &iostat);
 809      }
 810    } else if (EQUAL (proc, "write") || EQUAL (proc, "print") || EQUAL (proc, "punch")) {
 811      if (TOKEN ("*")) {
 812        _srecordf (unit.str, "STDF_OUT");
 813        dform = form_formatted;
 814        rc = scan (NULL);
 815      } else if (rc == INT_NUMBER) { // FORTRAN II
 816        _srecordf (unit.str, "STDF_OUT");
 817        bufcpy (fmt, curlex, RECLN);
 818        dform = form_formatted;
 819        rc = scan (NULL);
 820      } else if (rc == TEXT) {
 821        _srecordf (unit.str, "STDF_OUT");
 822        int_4 k = format_str (curlex);
 823        _srecordf (fmt, "%d", k);
 824        dform = form_formatted;
 825        rc = scan (NULL);
 826      } else {
 827        io_specs (&unit, STDF_OUT, fmt, &dfn, &dform, &daction, &lrecl, &ddisp, &endlbl, &errlbl, &iostat);
 828      }
 829    }
 830    if (strlen (fmt) == 0 && dform != form_unformatted) {
 831      form = STDFORMAT;
 832    } else if (strlen (fmt) == 0 && dform == form_unformatted) {
 833      form = UNFORMATTED;
 834    } else {
 835      form = FORMATTED;
 836    }
 837  // IO to a string implies UNIT=0.
 838    if (unit.mode.type == CHARACTER) {
 839      if (EQUAL (proc, "read")) {
 840        _srecordf (str, "_ffile[0].unit = fmemopen (%s, %d, \"r\");\n", unit.str, unit.mode.len + 1);
 841      } else if (EQUAL (proc, "accept")) {
 842        _srecordf (str, "_ffile[0].unit = fmemopen (%s, %d, \"r\");\n", unit.str, unit.mode.len + 1);
 843      } else if (EQUAL (proc, "write")) {
 844        _srecordf (str, "_ffile[0].unit = fmemopen (%s, %d, \"w\");\n", unit.str, unit.mode.len + 1);
 845      } else if (EQUAL (proc, "print")) {
 846        _srecordf (str, "_ffile[0].unit = fmemopen (%s, %d, \"w\");\n", unit.str, unit.mode.len + 1);
 847      } else if (EQUAL (proc, "punch")) {
 848        _srecordf (str, "_ffile[0].unit = fmemopen (%s, %d, \"w\");\n", unit.str, unit.mode.len + 1);
 849      }
 850      code (nprocs, BODY, str);
 851    }
 852  // Runtime checks - can the file do this?
 853    if (EQUAL (proc, "read")) {
 854      _srecordf (str, "_fcheck (\"%s\", %s, action_read, %s);\n", stat_start, unum (&unit), dform);
 855    } else if (EQUAL (proc, "accept")) {
 856      _srecordf (str, "_fcheck (\"%s\", %s, action_read, %s);\n", stat_start, unum (&unit), dform);
 857    } else if (EQUAL (proc, "write")) {
 858      _srecordf (str, "_fcheck (\"%s\", %s, action_write, %s);\n", stat_start, unum (&unit), dform);
 859    } else if (EQUAL (proc, "print")) {
 860      _srecordf (str, "_fcheck (\"%s\", %s, action_write, %s);\n", stat_start, unum (&unit), dform);
 861    } else if (EQUAL (proc, "punch")) {
 862      _srecordf (str, "_fcheck (\"%s\", %s, action_write, %s);\n", stat_start, unum (&unit), dform);
 863    }
 864    code (nprocs, BODY, str);
 865    if (form == FORMATTED) {
 866      RECORD fcnt;
 867      int_4 val;
 868      _srecordf (fid, "__fcnt");
 869      add_local (fid, INTEGER, 4, NOUNIQ, NOPATCH, NOARG, LOCAL, TEMP);
 870      _srecordf (iorc, "__rc");
 871      add_local (iorc, INTEGER, 4, NOUNIQ, NOPATCH, NOARG, LOCAL, TEMP);
 872      _srecordf (fcnt, "%s = 0;\n", fid);
 873      code (nprocs, BODY, fcnt);
 874      if (isint_4 (fmt, &val)) {
 875        _srecordf (fstr, "%s", edit_fmt (val));
 876      } else {
 877        MODE mode;
 878        IDENT *idf = find_local (fmt, &mode);
 879        if (idf == NULL) {
 880          ERROR (2920, "undeclared format identifier", fmt);
 881        } else if (mode.type == INTEGER) {
 882  // Assigned FORMAT.
 883          _srecordf (str, "switch (%s) {\n", CID (idf));
 884          code (nprocs, BODY, str);
 885          code (nprocs, BODY, "default:\n");
 886          for (int_4 k = 0; k < nlabels; k++) {
 887            LBL *L = &labels[k];
 888            if (L->format) {
 889              L->jumped++;
 890              _srecordf (str, "case %d: __fmt_a = %s; break;\n", L->index, edit_fmt(L->num));
 891              code (nprocs, BODY, str);
 892            }
 893          }
 894          code (nprocs, BODY, "}\n");
 895          strcpy (fstr, "__fmt_a");
 896        } else if (mode.type == CHARACTER) {
 897          _srecordf (str, "__fmt_a = _vif_jit (\"%s\", %s);\n", stat_start, CID (idf));
 898          code (nprocs, BODY, str);
 899          strcpy (fstr, "__fmt_a");
 900        } else {
 901          ERROR (2921, "format identifier mode error", qtype (&mode));
 902        }
 903      }
 904    } else {
 905      _srecordf (iorc, "__rc_%d", nloctmps++);
 906      add_local (iorc, INTEGER, 4, NOUNIQ, NOPATCH, NOARG, LOCAL, TEMP);
 907    }
 908  // Start-of-record.
 909    if (form == FORMATTED) {
 910      if (EQUAL (proc, "read")) {
 911        io_text_items ("read", &unit, fstr, fid, iorc, endlbl, errlbl);
 912      } else if (EQUAL (proc, "accept")) {
 913        io_text_items ("read", &unit, fstr, fid, iorc, endlbl, errlbl);
 914      } else if (EQUAL (proc, "write")) {
 915        io_text_items ("write", &unit, fstr, fid, iorc, endlbl, errlbl);
 916      } else if (EQUAL (proc, "print")) {
 917        io_text_items ("write", &unit, fstr, fid, iorc, endlbl, errlbl);
 918      } else if (EQUAL (proc, "punch")) {
 919        io_text_items ("write", &unit, fstr, fid, iorc, endlbl, errlbl);
 920      }
 921    }
 922    int_4 items = 0;
 923    if (EQUAL (proc, "read")) {
 924      io_list ("read", &unit, form, fstr, fid, iorc, endlbl, errlbl, ERR, nest, &items);
 925    } else if (EQUAL (proc, "accept")) {
 926      io_list ("read", &unit, form, fstr, fid, iorc, endlbl, errlbl, ERR, nest, &items);
 927    } else if (EQUAL (proc, "write")) {
 928      io_list ("write", &unit, form, fstr, fid, iorc, endlbl, errlbl, ERR, nest, &items);
 929    } else if (EQUAL (proc, "print")) {
 930      io_list ("write", &unit, form, fstr, fid, iorc, endlbl, errlbl, ERR, nest, &items);
 931    } else if (EQUAL (proc, "punch")) {
 932      io_list ("write", &unit, form, fstr, fid, iorc, endlbl, errlbl, ERR, nest, &items);
 933    }
 934    if (unit.mode.type == CHARACTER) {
 935  // IO to a string implies UNIT=0.
 936      code (nprocs, BODY, "_fclose (0);\n");
 937    } else if (EQUAL (proc, "write") || EQUAL (proc, "print") || EQUAL (proc, "punch")) {
 938  // End-of-record.
 939      if (form != UNFORMATTED) {
 940        _srecordf (str, "_write_eol (%s);\n", unum (&unit));
 941        code (nprocs, BODY, str);
 942      }
 943    } else if (EQUAL (proc, "read") || EQUAL (proc, "accept")) {
 944  // End-of-record.
 945      if (form != UNFORMATTED) {
 946        _srecordf (str, "_read_eol (%s);\n", unum (&unit));
 947        code (nprocs, BODY, str);
 948      }
 949    }
 950  //
 951    save_iostat (iostat);
 952  //
 953    (void) rc;
 954  }
     


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