table.c

     1  //! @file table.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  //! Symbol table routines.
    25  
    26  #include <vif.h>
    27  
    28  int_4 ord (char ch)
    29  {
    30    return (ch - 'a');
    31  }
    32  
    33  char *edit_name (char *name)
    34  {
    35  // Strip leading and trailing underscores.
    36    static RECORD idf, idf2;
    37    char *buf = idf;
    38    strcpy (buf, name);
    39    int_4 len = strlen (buf);
    40    while (len > 1 && buf[len - 1] == '_') {
    41      buf[len - 1] = '\0';
    42      len = strlen (buf);
    43    }
    44    while (len > 1 && buf[0] == '_') {
    45      buf++;
    46      len = strlen (buf);
    47    }
    48    RECCPY (idf2, buf);
    49    return idf2;
    50  }
    51  
    52  char *edit_f (char *name)
    53  {
    54  // Function name
    55    static RECORD buf;
    56    _srecordf (buf, "_%s", edit_name (name));
    57    return buf;
    58  }
    59  
    60  char *edit_i (char *name)
    61  {
    62  // Intrinsic name
    63    static RECORD buf;
    64    _srecordf (buf, "__%s", edit_name (name));
    65    return buf;
    66  }
    67  
    68  char *edit_v (char *name)
    69  {
    70  // Variable
    71    static RECORD buf;
    72    _srecordf (buf, "%s_", edit_name (name));
    73    return buf;
    74  }
    75  
    76  char *edit_vn (char *name, int_4 num)
    77  {
    78  // Variable-Nest
    79    static RECORD buf;
    80    _srecordf (buf, "%s_%d_", edit_v (name), num);
    81    return buf;
    82  }
    83  
    84  char *edit_tmp (int_4 num)
    85  {
    86    static RECORD buf;
    87    _srecordf (buf, "$%d_", num);
    88    return buf;
    89  }
    90  
    91  char *edit_fmt (int_4 num)
    92  {
    93    static RECORD buf;
    94    if (num >= 100000) { // Anonymous text formats
    95      _srecordf (buf, "$f_%d_", num);
    96      return buf;
    97    }
    98    LBL *L = NO_LABEL;
    99    for (int_4 k = 0; k < nlabels; k++) {
   100      if (num == labels[k].num) {
   101        L = &labels[k];
   102        break;
   103      }
   104    }
   105    if (L == NO_LABEL) {
   106      _srecordf (buf, "%d", num);
   107      ERROR (3101, "undefined label", buf);
   108      return NO_TEXT;
   109    } else if (!L->format) {
   110      _srecordf (buf, "%d", num);
   111      ERROR (3102, "not a format label", buf);
   112      return NO_TEXT;
   113    } else {
   114      L->jumped++;
   115      _srecordf (buf, "$f_%d_", num);
   116      return buf;
   117    }
   118  }
   119  
   120  char *edit_unit (int_4 num)
   121  {
   122    static RECORD buf;
   123    _srecordf (buf, "$u_%d_", num);
   124    return buf;
   125  }
   126  
   127  char *encode (char *buf, char *name)
   128  {
   129    bufcpy (buf, name, RECLN);
   130    int_4 len = (int_4) strlen (buf);
   131    if (buf[0] == '_' || buf[len - 1] == '_') {
   132      return buf;
   133    }
   134    bufcpy (buf, edit_v (name), RECLN);
   135    return buf;
   136  }
   137  
   138  char *c_name (char *name)
   139  {
   140    NEW_RECORD (safe);
   141    (void) encode (safe, name);
   142    return f_stralloc (safe);
   143  }
   144  
   145  logical_4 same_name (char *name, char * id)
   146  {
   147  if (name == NO_TEXT || id == NO_TEXT) return FALSE;
   148    NEW_RECORD (u);
   149    NEW_RECORD (v);
   150    (void) encode (u, name);
   151    (void) encode (v, id);
   152    return EQUAL (u, v);
   153  }
   154  
   155  LBL *find_label (char *lab)
   156  {
   157    int_4 k, num;
   158    sscanf (lab, "%d", &num);
   159    for (k = 0; k < nlabels; k++) {
   160      LBL *L = &labels[k];
   161      if (num == L->num) {
   162        return L;
   163      }
   164    }
   165    return NO_LABEL;
   166  }
   167  
   168  void impl_type (char *name, MODE * mode)
   169  {
   170    int_4 k = ord (tolower (name[0]));
   171    (*mode) = implic[k].mode;
   172  }
   173  
   174  int_4 add_block (char *name)
   175  {
   176    int_4 k;
   177    for (k = 0; k < ncommons; k++) {
   178      if (same_name (name, commons[k])) {
   179        return k;
   180      }
   181    }
   182    if (ncommons >= MAX_COMMONS) {
   183      FATAL (3103, "too many common blocks", NO_TEXT);
   184    }
   185    k = ncommons++;
   186    commons[k] = c_name (name);
   187    return k;
   188  }
   189  
   190  IDENT *find_local (char *name, MODE * mode)
   191  {
   192    int_4 k;
   193    if (!IS_VAR (name)) {
   194      ERROR (3104, "not a variable name", curlex);
   195      return NO_IDENT;
   196    }
   197  // Search backwards, do not change.
   198    for (k = nlocals - 1; k >= 0; k--) {
   199      IDENT *idf = &locals[k];
   200      if (idf->nest >= 0 && (EQUAL (name, C_NAME (idf)) || EQUAL (name, F_NAME (idf)))) {
   201        if (macro_nest > 0 ? TRUE : idf->nest == 0) {
   202          if (mode != NO_MODE) {
   203            (*mode) = idf->mode;
   204          }
   205          idf->used = TRUE;
   206          return idf;
   207        }
   208      }
   209    }
   210    return NO_IDENT;
   211  }
   212  
   213  IDENT *void_decl (char *name, MODE * mode)
   214  {
   215    if (!IS_VAR (name)) {
   216      ERROR (3105, "not a variable name", curlex);
   217      return NO_IDENT;
   218    }
   219  // Apparently a normal local variable.
   220    IDENT *idf = find_local (name, mode);
   221    if (idf == NO_IDENT) {
   222      if (nlocals >= MAX_IDENTS) {
   223        FATAL (3106, "too many identifiers", NO_TEXT);
   224        return NO_IDENT;
   225      }
   226      idf = &locals[nlocals++];
   227      memset (idf, 0, sizeof (IDENT));
   228      idf->line = curlin;
   229      C_NAME (idf) = c_name (name);
   230      F_NAME (idf) = f_stralloc (name);
   231      idf->external = FALSE;
   232      idf->mode.type = NOTYPE;
   233      idf->mode.len = 0;
   234      if (mode != NO_MODE) {
   235        *mode = idf->mode;
   236      }
   237    }
   238    return idf;
   239  }
   240  
   241  IDENT *add_local (char *name, int_4 type, int_4 len, int_4 uniq, int_4 apatch, int_4 arg, int_4 blck, int_4 src)
   242  {
   243    MODE mode;
   244    if (!IS_VAR (name)) {
   245      ERROR (3107, "not a variable name", curlex);
   246      return NO_IDENT;
   247    }
   248    IDENT *idf = find_local (name, &mode);
   249    if (type == CHARACTER) {
   250      MODE m = {.type = type, .len = len};
   251      norm_mode (&m);
   252      len = m.len;
   253      if (idf == NO_IDENT) {
   254        if (len == 0 && arg == FALSE) {
   255          ERROR (3108, "variable length character must be argument", name);
   256        }
   257      } else {
   258        if (len == 0 && idf->arg == FALSE) {
   259          ERROR (3109, "variable length character must be argument", name);
   260        }
   261      }
   262    }
   263    if (idf != NO_IDENT) {
   264      if (uniq) {
   265        if (idf->mode.type == NOTYPE) {
   266          if (type != NOTYPE) {
   267            // Do not overwrite 'dim', respect previous dimension statement.
   268            idf->mode.type = type;
   269            idf->mode.len = len;
   270          } else {
   271            idf->patch2 = apatch;
   272          }
   273        } else if (idf->parm != NO_TEXT) {
   274          if (accept_mode (idf->mode.type, idf->mode.len, type, len)) {
   275            idf->mode = PLAIN_MODE (type, len);
   276          } else {
   277            MODE err = PLAIN_MODE (type, len);
   278            MODE_ERROR (3110, qtype (&err), qtype (&(idf->mode)));
   279          }
   280        } else if (NOT_LOCAL (idf)) {
   281          idf->mode = PLAIN_MODE (type, len);
   282        } else if (idf->external) {
   283          idf->mode = PLAIN_MODE (type, len);
   284        } else if (idf->mode.type == type && idf->mode.len == len) {
   285          /* Let it pass */
   286        } else {
   287          ERROR (3111, "multiple definition", name);
   288        }
   289      }
   290      return idf;
   291    }
   292    if (nlocals >= MAX_IDENTS) {
   293      FATAL (3112, "too many identifiers", NO_TEXT);
   294      return NO_IDENT;
   295    }
   296    idf = &locals[nlocals++];
   297    memset (idf, 0, sizeof (IDENT));
   298    idf->line = curlin;
   299    C_NAME (idf) = c_name (name);
   300    F_NAME (idf) = f_stralloc (name);
   301    idf->arg = arg;
   302    idf->common = blck;
   303    idf->external = FALSE;
   304    idf->mode = PLAIN_MODE (type, len);
   305    idf->patch1 = apatch;
   306    idf->source = src;
   307    return idf;
   308  }
   309  
   310  IDENT *add_nest (char *name, int_4 nest, MODE *mode)
   311  {
   312    if (!IS_VAR (name)) {
   313      ERROR (3113, "not a variable name", curlex);
   314      return NO_IDENT;
   315    }
   316    if (nlocals >= MAX_IDENTS) {
   317      FATAL (3114, "too many identifiers", NO_TEXT);
   318      return NO_IDENT;
   319    }
   320  // Already declared? Take this mode.
   321    IDENT *pre = find_local (name, mode);
   322  //
   323    IDENT *idf = &locals[nlocals++];
   324    memset (idf, 0, sizeof (IDENT));
   325    idf->line = curlin;
   326    C_NAME (idf) = c_name (name);
   327    F_NAME (idf) = f_stralloc (name);
   328    idf->arg = NOARG;
   329    idf->external = FALSE;
   330    idf->common = 0;
   331    idf->patch1 = NOPATCH;
   332    idf->source = TEMP;
   333    idf->nest = nest;
   334    if (pre == NO_IDENT) {
   335      impl_type (name, &idf->mode);
   336      *mode = idf->mode;
   337    } else {
   338      *mode = pre->mode;
   339      idf->mode = *mode;
   340    }
   341    return idf;
   342  }


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