parser-taxes.c

     
   1  //! @file parser-taxes.c
   2  //! @author J. Marcel van der Veer
   3  
   4  //! @section Copyright
   5  //!
   6  //! This file is part of Algol68G - an Algol 68 compiler-interpreter.
   7  //! Copyright 2001-2026 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 management.
  25  
  26  #include "a68g.h"
  27  #include "a68g-parser.h"
  28  
  29  // Symbol table handling, managing TAGS.
  30  
  31  //! @brief Set level for procedures.
  32  
  33  void set_proc_level (NODE_T * p, int n)
  34  {
  35    for (; p != NO_NODE; FORWARD (p)) {
  36      PROCEDURE_LEVEL (INFO (p)) = n;
  37      if (IS (p, ROUTINE_TEXT)) {
  38        set_proc_level (SUB (p), n + 1);
  39      } else {
  40        set_proc_level (SUB (p), n);
  41      }
  42    }
  43  }
  44  
  45  //! @brief Set nests for diagnostics.
  46  
  47  void set_nest (NODE_T * p, NODE_T * s)
  48  {
  49    for (; p != NO_NODE; FORWARD (p)) {
  50      NEST (p) = s;
  51      if (IS (p, PARTICULAR_PROGRAM)) {
  52        set_nest (SUB (p), p);
  53      } else if (IS (p, CLOSED_CLAUSE) && LINE_NUMBER (p) != 0) {
  54        set_nest (SUB (p), p);
  55      } else if (IS (p, COLLATERAL_CLAUSE) && LINE_NUMBER (p) != 0) {
  56        set_nest (SUB (p), p);
  57      } else if (IS (p, CONDITIONAL_CLAUSE) && LINE_NUMBER (p) != 0) {
  58        set_nest (SUB (p), p);
  59      } else if (IS (p, CASE_CLAUSE) && LINE_NUMBER (p) != 0) {
  60        set_nest (SUB (p), p);
  61      } else if (IS (p, CONFORMITY_CLAUSE) && LINE_NUMBER (p) != 0) {
  62        set_nest (SUB (p), p);
  63      } else if (IS (p, LOOP_CLAUSE) && LINE_NUMBER (p) != 0) {
  64        set_nest (SUB (p), p);
  65      } else {
  66        set_nest (SUB (p), s);
  67      }
  68    }
  69  }
  70  
  71  // Routines that work with tags and symbol tables.
  72  
  73  void tax_tags (NODE_T *);
  74  void tax_specifier_list (NODE_T *);
  75  void tax_parameter_list (NODE_T *);
  76  void tax_format_texts (NODE_T *);
  77  
  78  //! @brief Find a tag, searching symbol tables towards the root.
  79  
  80  int first_tag_global (TABLE_T * table, char *name)
  81  {
  82    if (table != NO_TABLE) {
  83      for (TAG_T *s = IDENTIFIERS (table); s != NO_TAG; FORWARD (s)) {
  84        if (NSYMBOL (NODE (s)) == name) {
  85          return IDENTIFIER;
  86        }
  87      }
  88      for (TAG_T *s = INDICANTS (table); s != NO_TAG; FORWARD (s)) {
  89        if (NSYMBOL (NODE (s)) == name) {
  90          return INDICANT;
  91        }
  92      }
  93      for (TAG_T *s = LABELS (table); s != NO_TAG; FORWARD (s)) {
  94        if (NSYMBOL (NODE (s)) == name) {
  95          return LABEL;
  96        }
  97      }
  98      for (TAG_T *s = OPERATORS (table); s != NO_TAG; FORWARD (s)) {
  99        if (NSYMBOL (NODE (s)) == name) {
 100          return OP_SYMBOL;
 101        }
 102      }
 103      for (TAG_T *s = PRIO (table); s != NO_TAG; FORWARD (s)) {
 104        if (NSYMBOL (NODE (s)) == name) {
 105          return PRIO_SYMBOL;
 106        }
 107      }
 108      return first_tag_global (PREVIOUS (table), name);
 109    } else {
 110      return STOP;
 111    }
 112  }
 113  
 114  #define PORTCHECK_TAX(p, q) {\
 115    if (q == A68G_FALSE) {\
 116      diagnostic (A68G_NOTICE, p, WARNING_TAG_NOT_PORTABLE);\
 117    }}
 118  
 119  //! @brief Check portability of sub tree.
 120  
 121  void portcheck (NODE_T * p)
 122  {
 123    for (; p != NO_NODE; FORWARD (p)) {
 124      portcheck (SUB (p));
 125      if (OPTION_PORTCHECK (&A68G_JOB)) {
 126        if (IS (p, INDICANT) && MOID (p) != NO_MOID) {
 127          PORTCHECK_TAX (p, PORTABLE (MOID (p)));
 128          PORTABLE (MOID (p)) = A68G_TRUE;
 129        } else if (IS (p, IDENTIFIER)) {
 130          PORTCHECK_TAX (p, PORTABLE (TAX (p)));
 131          PORTABLE (TAX (p)) = A68G_TRUE;
 132        } else if (IS (p, OPERATOR)) {
 133          PORTCHECK_TAX (p, PORTABLE (TAX (p)));
 134          PORTABLE (TAX (p)) = A68G_TRUE;
 135        } else if (IS (p, ASSERTION)) {
 136          diagnostic (A68G_NOTICE, p, WARNING_TAG_NOT_PORTABLE);
 137        }
 138      }
 139    }
 140  }
 141  
 142  //! @brief Whether routine can be "lengthety-mapped".
 143  
 144  #define CAR(u, v) (strncmp (u, v, strlen(v)) == 0)
 145  
 146  BOOL_T is_mappable_routine (char *z, char *length)
 147  {
 148    if (CAR (z, length)) {
 149      return is_mappable_routine (&z[strlen (length)], length);
 150    }
 151  #define ACCEPT(u, v) {\
 152    if (strcmp (u, v) == 0) {\
 153      return A68G_TRUE;\
 154    }}
 155  // Math routines.
 156    ACCEPT (z, "arccos");
 157    ACCEPT (z, "arccosdg");
 158    ACCEPT (z, "arccot");
 159    ACCEPT (z, "arccotdg");
 160    ACCEPT (z, "arcsin");
 161    ACCEPT (z, "arcsindg");
 162    ACCEPT (z, "arctan");
 163    ACCEPT (z, "arctandg");
 164    ACCEPT (z, "beta");
 165    ACCEPT (z, "betainc");
 166    ACCEPT (z, "cbrt");
 167    ACCEPT (z, "complexarccos");
 168    ACCEPT (z, "complexarccosh");
 169    ACCEPT (z, "complexarcsin");
 170    ACCEPT (z, "complexarcsinh");
 171    ACCEPT (z, "complexarctan");
 172    ACCEPT (z, "complexarctanh");
 173    ACCEPT (z, "complexcos");
 174    ACCEPT (z, "complexcosh");
 175    ACCEPT (z, "complexexp");
 176    ACCEPT (z, "complexln");
 177    ACCEPT (z, "complexsin");
 178    ACCEPT (z, "complexsinh");
 179    ACCEPT (z, "complexsqrt");
 180    ACCEPT (z, "complextan");
 181    ACCEPT (z, "complextanh");
 182    ACCEPT (z, "cos");
 183    ACCEPT (z, "cosdg");
 184    ACCEPT (z, "cospi");
 185    ACCEPT (z, "cot");
 186    ACCEPT (z, "cotdg");
 187    ACCEPT (z, "cotpi");
 188    ACCEPT (z, "curt");
 189    ACCEPT (z, "erf");
 190    ACCEPT (z, "erfc");
 191    ACCEPT (z, "exp");
 192    ACCEPT (z, "gamma");
 193    ACCEPT (z, "gammainc");
 194    ACCEPT (z, "gammaincg");
 195    ACCEPT (z, "gammaincgf");
 196    ACCEPT (z, "ln");
 197    ACCEPT (z, "log");
 198    ACCEPT (z, "pi");
 199    ACCEPT (z, "sin");
 200    ACCEPT (z, "sindg");
 201    ACCEPT (z, "sinpi");
 202    ACCEPT (z, "sqrt");
 203    ACCEPT (z, "tan");
 204    ACCEPT (z, "tandg");
 205    ACCEPT (z, "tanpi");
 206  // Random generator.
 207    ACCEPT (z, "nextrandom");
 208    ACCEPT (z, "random");
 209  // BITS.
 210    ACCEPT (z, "bitspack");
 211  // Enquiries.
 212    ACCEPT (z, "bitswidth");
 213    ACCEPT (z, "byteswidth");
 214    ACCEPT (z, "expwidth");
 215    ACCEPT (z, "intwidth");
 216    ACCEPT (z, "maxbits");
 217    ACCEPT (z, "maxint");
 218    ACCEPT (z, "maxreal");
 219    ACCEPT (z, "realwidth");
 220    ACCEPT (z, "smallreal");
 221    return A68G_FALSE;
 222  #undef ACCEPT
 223  }
 224  
 225  //! @brief Map "short sqrt" onto "sqrt" etcetera.
 226  
 227  TAG_T *bind_lengthety_identifier (char *u)
 228  {
 229  // We can only map routines blessed by "is_mappable_routine", so there is no
 230  // "short print" or "long char in string".
 231    if (CAR (u, "short")) {
 232      do {
 233        u = &u[strlen ("short")];
 234        char *v = TEXT (add_token (&A68G (top_token), u));
 235        TAG_T *w = find_tag_local (A68G_STANDENV, IDENTIFIER, v);
 236        if (w != NO_TAG && is_mappable_routine (v, "short")) {
 237          return w;
 238        }
 239      } while (CAR (u, "short"));
 240    } else if (CAR (u, "long")) {
 241      do {
 242        u = &u[strlen ("long")];
 243        char *v = TEXT (add_token (&A68G (top_token), u));
 244        TAG_T *w = find_tag_local (A68G_STANDENV, IDENTIFIER, v);
 245        if (w != NO_TAG && is_mappable_routine (v, "long")) {
 246          return w;
 247        }
 248      } while (CAR (u, "long"));
 249    }
 250    return NO_TAG;
 251  }
 252  
 253  #undef CAR
 254  
 255  //! @brief Bind identifier tags to the symbol table.
 256  
 257  void bind_identifier_tag_to_symbol_table (NODE_T * p)
 258  {
 259    for (; p != NO_NODE; FORWARD (p)) {
 260      bind_identifier_tag_to_symbol_table (SUB (p));
 261      if (is_one_of (p, IDENTIFIER, DEFINING_IDENTIFIER, STOP)) {
 262        int att = first_tag_global (TABLE (p), NSYMBOL (p));
 263        if (att == STOP) {
 264          TAG_T *z = bind_lengthety_identifier (NSYMBOL (p));
 265          if (z != NO_TAG) {
 266            MOID (p) = MOID (z);
 267          }
 268          TAX (p) = z;
 269        } else {
 270          TAG_T *z = find_tag_global (TABLE (p), att, NSYMBOL (p));
 271          if (att == IDENTIFIER && z != NO_TAG) {
 272            MOID (p) = MOID (z);
 273          } else if (att == LABEL && z != NO_TAG) {
 274            ;
 275          } else if ((z = bind_lengthety_identifier (NSYMBOL (p))) != NO_TAG) {
 276            MOID (p) = MOID (z);
 277          } else {
 278            diagnostic (A68G_ERROR, p, ERROR_UNDECLARED_TAG);
 279            z = add_tag (TABLE (p), IDENTIFIER, p, M_ERROR, NORMAL_IDENTIFIER);
 280            MOID (p) = M_ERROR;
 281          }
 282          TAX (p) = z;
 283          if (IS (p, DEFINING_IDENTIFIER)) {
 284            NODE (z) = p;
 285          }
 286        }
 287      }
 288    }
 289  }
 290  
 291  //! @brief Bind indicant tags to the symbol table.
 292  
 293  void bind_indicant_tag_to_symbol_table (NODE_T * p)
 294  {
 295    for (; p != NO_NODE; FORWARD (p)) {
 296      bind_indicant_tag_to_symbol_table (SUB (p));
 297      if (is_one_of (p, INDICANT, DEFINING_INDICANT, STOP)) {
 298        TAG_T *z = find_tag_global (TABLE (p), INDICANT, NSYMBOL (p));
 299        if (z != NO_TAG) {
 300          MOID (p) = MOID (z);
 301          TAX (p) = z;
 302          if (IS (p, DEFINING_INDICANT)) {
 303            NODE (z) = p;
 304          }
 305        }
 306      }
 307    }
 308  }
 309  
 310  //! @brief Enter specifier identifiers in the symbol table.
 311  
 312  void tax_specifiers (NODE_T * p)
 313  {
 314    for (; p != NO_NODE; FORWARD (p)) {
 315      tax_specifiers (SUB (p));
 316      if (SUB (p) != NO_NODE && IS (p, SPECIFIER)) {
 317        tax_specifier_list (SUB (p));
 318      }
 319    }
 320  }
 321  
 322  //! @brief Enter specifier identifiers in the symbol table.
 323  
 324  void tax_specifier_list (NODE_T * p)
 325  {
 326    if (p != NO_NODE) {
 327      if (IS (p, OPEN_SYMBOL)) {
 328        tax_specifier_list (NEXT (p));
 329      } else if (is_one_of (p, CLOSE_SYMBOL, VOID_SYMBOL, STOP)) {
 330        ;
 331      } else if (IS (p, IDENTIFIER)) {
 332        TAG_T *z = add_tag (TABLE (p), IDENTIFIER, p, NO_MOID, SPECIFIER_IDENTIFIER);
 333        HEAP (z) = LOC_SYMBOL;
 334      } else if (IS (p, DECLARER)) {
 335        tax_specifiers (SUB (p));
 336        tax_specifier_list (NEXT (p));
 337  // last identifier entry is identifier with this declarer.
 338        if (IDENTIFIERS (TABLE (p)) != NO_TAG && PRIO (IDENTIFIERS (TABLE (p))) == SPECIFIER_IDENTIFIER)
 339          MOID (IDENTIFIERS (TABLE (p))) = MOID (p);
 340      }
 341    }
 342  }
 343  
 344  //! @brief Enter parameter identifiers in the symbol table.
 345  
 346  void tax_parameters (NODE_T * p)
 347  {
 348    for (; p != NO_NODE; FORWARD (p)) {
 349      if (SUB (p) != NO_NODE) {
 350        tax_parameters (SUB (p));
 351        if (IS (p, PARAMETER_PACK)) {
 352          tax_parameter_list (SUB (p));
 353        }
 354      }
 355    }
 356  }
 357  
 358  //! @brief Enter parameter identifiers in the symbol table.
 359  
 360  void tax_parameter_list (NODE_T * p)
 361  {
 362    if (p != NO_NODE) {
 363      if (is_one_of (p, OPEN_SYMBOL, COMMA_SYMBOL, STOP)) {
 364        tax_parameter_list (NEXT (p));
 365      } else if (IS (p, CLOSE_SYMBOL)) {
 366        ;
 367      } else if (is_one_of (p, PARAMETER_LIST, PARAMETER, STOP)) {
 368        tax_parameter_list (NEXT (p));
 369        tax_parameter_list (SUB (p));
 370      } else if (IS (p, IDENTIFIER)) {
 371  // parameters are always local.
 372        HEAP (add_tag (TABLE (p), IDENTIFIER, p, NO_MOID, PARAMETER_IDENTIFIER)) = LOC_SYMBOL;
 373      } else if (IS (p, DECLARER)) {
 374        tax_parameter_list (NEXT (p));
 375  // last identifier entries are identifiers with this declarer.
 376        for (TAG_T *s = IDENTIFIERS (TABLE (p)); s != NO_TAG && MOID (s) == NO_MOID; FORWARD (s)) {
 377          MOID (s) = MOID (p);
 378        }
 379        tax_parameters (SUB (p));
 380      }
 381    }
 382  }
 383  
 384  //! @brief Enter FOR identifiers in the symbol table.
 385  
 386  void tax_for_identifiers (NODE_T * p)
 387  {
 388    for (; p != NO_NODE; FORWARD (p)) {
 389      tax_for_identifiers (SUB (p));
 390      if (IS (p, FOR_SYMBOL)) {
 391        if ((FORWARD (p)) != NO_NODE) {
 392          (void) add_tag (TABLE (p), IDENTIFIER, p, M_INT, LOOP_IDENTIFIER);
 393        }
 394      }
 395    }
 396  }
 397  
 398  //! @brief Enter routine texts in the symbol table.
 399  
 400  void tax_routine_texts (NODE_T * p)
 401  {
 402    for (; p != NO_NODE; FORWARD (p)) {
 403      tax_routine_texts (SUB (p));
 404      if (IS (p, ROUTINE_TEXT)) {
 405        TAG_T *z = add_tag (TABLE (p), ANONYMOUS, p, MOID (p), ROUTINE_TEXT);
 406        TAX (p) = z;
 407        HEAP (z) = LOC_SYMBOL;
 408        USE (z) = A68G_TRUE;
 409      }
 410    }
 411  }
 412  
 413  //! @brief Enter format texts in the symbol table.
 414  
 415  void tax_format_texts (NODE_T * p)
 416  {
 417    for (; p != NO_NODE; FORWARD (p)) {
 418      tax_format_texts (SUB (p));
 419      if (IS (p, FORMAT_TEXT)) {
 420        TAG_T *z = add_tag (TABLE (p), ANONYMOUS, p, M_FORMAT, FORMAT_TEXT);
 421        TAX (p) = z;
 422        USE (z) = A68G_TRUE;
 423      } else if (IS (p, FORMAT_DELIMITER_SYMBOL) && NEXT (p) != NO_NODE) {
 424        TAG_T *z = add_tag (TABLE (p), ANONYMOUS, p, M_FORMAT, FORMAT_IDENTIFIER);
 425        TAX (p) = z;
 426        USE (z) = A68G_TRUE;
 427      }
 428    }
 429  }
 430  
 431  //! @brief Enter FORMAT pictures in the symbol table.
 432  
 433  void tax_pictures (NODE_T * p)
 434  {
 435    for (; p != NO_NODE; FORWARD (p)) {
 436      tax_pictures (SUB (p));
 437      if (IS (p, PICTURE)) {
 438        TAX (p) = add_tag (TABLE (p), ANONYMOUS, p, M_COLLITEM, FORMAT_IDENTIFIER);
 439      }
 440    }
 441  }
 442  
 443  //! @brief Enter generators in the symbol table.
 444  
 445  void tax_generators (NODE_T * p)
 446  {
 447    for (; p != NO_NODE; FORWARD (p)) {
 448      tax_generators (SUB (p));
 449      if (IS (p, GENERATOR)) {
 450        if (IS (SUB (p), LOC_SYMBOL)) {
 451          TAG_T *z = add_tag (TABLE (p), ANONYMOUS, p, SUB_MOID (SUB (p)), GENERATOR);
 452          HEAP (z) = LOC_SYMBOL;
 453          USE (z) = A68G_TRUE;
 454          TAX (p) = z;
 455        }
 456      }
 457    }
 458  }
 459  
 460  //! @brief Find a firmly related operator for operands.
 461  
 462  TAG_T *find_firmly_related_op (TABLE_T * c, const char *n, MOID_T * l, MOID_T * r, const TAG_T * self)
 463  {
 464    if (c != NO_TABLE) {
 465      TAG_T *s = OPERATORS (c);
 466      for (; s != NO_TAG; FORWARD (s)) {
 467        if (s != self && NSYMBOL (NODE (s)) == n) {
 468          PACK_T *t = PACK (MOID (s));
 469          if (t != NO_PACK && is_firm (MOID (t), l)) {
 470  // catch monadic operator.
 471            if ((FORWARD (t)) == NO_PACK) {
 472              if (r == NO_MOID) {
 473                return s;
 474              }
 475            } else {
 476  // catch dyadic operator.
 477              if (r != NO_MOID && is_firm (MOID (t), r)) {
 478                return s;
 479              }
 480            }
 481          }
 482        }
 483      }
 484    }
 485    return NO_TAG;
 486  }
 487  
 488  //! @brief Check for firmly related operators in this range.
 489  
 490  void test_firmly_related_ops_local (NODE_T * p, TAG_T * s)
 491  {
 492    if (s != NO_TAG) {
 493      PACK_T *u = PACK (MOID (s));
 494      if (u != NO_PACK) {
 495        MOID_T *l = MOID (u);
 496        MOID_T *r = (NEXT (u) != NO_PACK ? MOID (NEXT (u)) : NO_MOID);
 497        TAG_T *t = find_firmly_related_op (TAG_TABLE (s), NSYMBOL (NODE (s)), l, r, s);
 498        if (t != NO_TAG) {
 499          if (TAG_TABLE (t) == A68G_STANDENV) {
 500            diagnostic (A68G_ERROR, p, ERROR_OPERATOR_RELATED, MOID (s), NSYMBOL (NODE (s)), MOID (t), NSYMBOL (NODE (t)));
 501            ABEND (A68G_TRUE, ERROR_INTERNAL_CONSISTENCY, NO_TEXT);
 502          } else {
 503            diagnostic (A68G_ERROR, p, ERROR_OPERATOR_RELATED, MOID (s), NSYMBOL (NODE (s)), MOID (t), NSYMBOL (NODE (t)));
 504          }
 505        }
 506      }
 507      if (NEXT (s) != NO_TAG) {
 508        test_firmly_related_ops_local ((p == NO_NODE ? NO_NODE : NODE (NEXT (s))), NEXT (s));
 509      }
 510    }
 511  }
 512  
 513  //! @brief Find firmly related operators in this program.
 514  
 515  void test_firmly_related_ops (NODE_T * p)
 516  {
 517    for (; p != NO_NODE; FORWARD (p)) {
 518      if (SUB (p) != NO_NODE && is_new_lexical_level (p)) {
 519        TAG_T *oops = OPERATORS (TABLE (SUB (p)));
 520        if (oops != NO_TAG) {
 521          test_firmly_related_ops_local (NODE (oops), oops);
 522        }
 523      }
 524      test_firmly_related_ops (SUB (p));
 525    }
 526  }
 527  
 528  //! @brief Driver for the processing of TAXes.
 529  
 530  void collect_taxes (NODE_T * p)
 531  {
 532    tax_tags (p);
 533    tax_specifiers (p);
 534    tax_parameters (p);
 535    tax_for_identifiers (p);
 536    tax_routine_texts (p);
 537    tax_pictures (p);
 538    tax_format_texts (p);
 539    tax_generators (p);
 540    bind_identifier_tag_to_symbol_table (p);
 541    bind_indicant_tag_to_symbol_table (p);
 542    test_firmly_related_ops (p);
 543    test_firmly_related_ops_local (NO_NODE, OPERATORS (A68G_STANDENV));
 544  }
 545  
 546  //! @brief Whether tag has already been declared in this range.
 547  
 548  void already_declared (NODE_T * n, int a)
 549  {
 550    if (find_tag_local (TABLE (n), a, NSYMBOL (n)) != NO_TAG) {
 551      diagnostic (A68G_ERROR, n, ERROR_MULTIPLE_TAG);
 552    }
 553  }
 554  
 555  //! @brief Whether tag has already been declared in this range.
 556  
 557  void already_declared_hidden (NODE_T * n, int a)
 558  {
 559    if (find_tag_local (TABLE (n), a, NSYMBOL (n)) != NO_TAG) {
 560      diagnostic (A68G_ERROR, n, ERROR_MULTIPLE_TAG);
 561    }
 562    TAG_T *s = find_tag_global (PREVIOUS (TABLE (n)), a, NSYMBOL (n));
 563    if (s != NO_TAG) {
 564      if (TAG_TABLE (s) == A68G_STANDENV) {
 565        diagnostic (A68G_NOTICE, n, WARNING_HIDES_PRELUDE, MOID (s), NSYMBOL (n));
 566      } else {
 567        diagnostic (A68G_NOTICE, n, WARNING_HIDES, NSYMBOL (n));
 568      }
 569    }
 570  }
 571  
 572  //! @brief Add tag to local symbol table.
 573  
 574  TAG_T *add_tag (TABLE_T * s, int a, NODE_T * n, MOID_T * m, int p)
 575  {
 576  #define INSERT_TAG(l, n) {NEXT (n) = *(l); *(l) = (n);}
 577    if (s != NO_TABLE) {
 578      TAG_T *z = new_tag ();
 579      TAG_TABLE (z) = s;
 580      PRIO (z) = p;
 581      MOID (z) = m;
 582      NODE (z) = n;
 583  //    TAX (n) = z;.
 584      switch (a) {
 585      case IDENTIFIER: {
 586          already_declared_hidden (n, IDENTIFIER);
 587          already_declared_hidden (n, LABEL);
 588          INSERT_TAG (&IDENTIFIERS (s), z);
 589          break;
 590        }
 591      case INDICANT: {
 592          already_declared_hidden (n, INDICANT);
 593          already_declared (n, OP_SYMBOL);
 594          already_declared (n, PRIO_SYMBOL);
 595          INSERT_TAG (&INDICANTS (s), z);
 596          break;
 597        }
 598      case LABEL: {
 599          already_declared_hidden (n, LABEL);
 600          already_declared_hidden (n, IDENTIFIER);
 601          INSERT_TAG (&LABELS (s), z);
 602          break;
 603        }
 604      case OP_SYMBOL: {
 605          already_declared (n, INDICANT);
 606          INSERT_TAG (&OPERATORS (s), z);
 607          break;
 608        }
 609      case PRIO_SYMBOL: {
 610          already_declared (n, PRIO_SYMBOL);
 611          already_declared (n, INDICANT);
 612          INSERT_TAG (&PRIO (s), z);
 613          break;
 614        }
 615      case ANONYMOUS: {
 616          INSERT_TAG (&ANONYMOUS (s), z);
 617          break;
 618        }
 619      default: {
 620          ABEND (A68G_TRUE, ERROR_INTERNAL_CONSISTENCY, NO_TEXT);
 621        }
 622      }
 623      return z;
 624    } else {
 625      return NO_TAG;
 626    }
 627  }
 628  
 629  //! @brief Find a tag, searching symbol tables towards the root.
 630  
 631  TAG_T *find_tag_global (TABLE_T * table, int a, char *name)
 632  {
 633    if (table != NO_TABLE) {
 634      TAG_T *s = NO_TAG;
 635      switch (a) {
 636      case IDENTIFIER: {
 637          s = IDENTIFIERS (table);
 638          break;
 639        }
 640      case INDICANT: {
 641          s = INDICANTS (table);
 642          break;
 643        }
 644      case LABEL: {
 645          s = LABELS (table);
 646          break;
 647        }
 648      case OP_SYMBOL: {
 649          s = OPERATORS (table);
 650          break;
 651        }
 652      case PRIO_SYMBOL: {
 653          s = PRIO (table);
 654          break;
 655        }
 656      default: {
 657          ABEND (A68G_TRUE, ERROR_INTERNAL_CONSISTENCY, NO_TEXT);
 658          break;
 659        }
 660      }
 661      for (; s != NO_TAG; FORWARD (s)) {
 662        if (NSYMBOL (NODE (s)) == name) {
 663          return s;
 664        }
 665      }
 666      return find_tag_global (PREVIOUS (table), a, name);
 667    } else {
 668      return NO_TAG;
 669    }
 670  }
 671  
 672  //! @brief Whether identifier or label global.
 673  
 674  int is_identifier_or_label_global (TABLE_T * table, char *name)
 675  {
 676    if (table != NO_TABLE) {
 677      for (TAG_T *s = IDENTIFIERS (table); s != NO_TAG; FORWARD (s)) {
 678        if (NSYMBOL (NODE (s)) == name) {
 679          return IDENTIFIER;
 680        }
 681      }
 682      for (TAG_T *s = LABELS (table); s != NO_TAG; FORWARD (s)) {
 683        if (NSYMBOL (NODE (s)) == name) {
 684          return LABEL;
 685        }
 686      }
 687      return is_identifier_or_label_global (PREVIOUS (table), name);
 688    } else {
 689      return 0;
 690    }
 691  }
 692  
 693  //! @brief Find a tag, searching only local symbol table.
 694  
 695  TAG_T *find_tag_local (TABLE_T * table, int a, const char *name)
 696  {
 697    if (table != NO_TABLE) {
 698      TAG_T *s = NO_TAG;
 699      if (a == OP_SYMBOL) {
 700        s = OPERATORS (table);
 701      } else if (a == PRIO_SYMBOL) {
 702        s = PRIO (table);
 703      } else if (a == IDENTIFIER) {
 704        s = IDENTIFIERS (table);
 705      } else if (a == INDICANT) {
 706        s = INDICANTS (table);
 707      } else if (a == LABEL) {
 708        s = LABELS (table);
 709      } else {
 710        ABEND (A68G_TRUE, ERROR_INTERNAL_CONSISTENCY, NO_TEXT);
 711      }
 712      for (; s != NO_TAG; FORWARD (s)) {
 713        if (NSYMBOL (NODE (s)) == name) {
 714          return s;
 715        }
 716      }
 717    }
 718    return NO_TAG;
 719  }
 720  
 721  //! @brief Whether context specifies HEAP or LOC for an identifier.
 722  
 723  int tab_qualifier (NODE_T * p)
 724  {
 725    if (p != NO_NODE) {
 726      if (is_one_of (p, UNIT, ASSIGNATION, TERTIARY, SECONDARY, GENERATOR, STOP)) {
 727        return tab_qualifier (SUB (p));
 728      } else if (is_one_of (p, LOC_SYMBOL, HEAP_SYMBOL, NEW_SYMBOL, STOP)) {
 729        return ATTRIBUTE (p) == LOC_SYMBOL ? LOC_SYMBOL : HEAP_SYMBOL;
 730      } else {
 731        return LOC_SYMBOL;
 732      }
 733    } else {
 734      return LOC_SYMBOL;
 735    }
 736  }
 737  
 738  //! @brief Enter identity declarations in the symbol table.
 739  
 740  void tax_identity_dec (NODE_T * p, MOID_T ** m)
 741  {
 742    if (p != NO_NODE) {
 743      if (IS (p, IDENTITY_DECLARATION)) {
 744        tax_identity_dec (SUB (p), m);
 745        tax_identity_dec (NEXT (p), m);
 746      } else if (IS (p, DECLARER)) {
 747        tax_tags (SUB (p));
 748        *m = MOID (p);
 749        tax_identity_dec (NEXT (p), m);
 750      } else if (IS (p, COMMA_SYMBOL)) {
 751        tax_identity_dec (NEXT (p), m);
 752      } else if (IS (p, DEFINING_IDENTIFIER)) {
 753        TAG_T *entry = find_tag_local (TABLE (p), IDENTIFIER, NSYMBOL (p));
 754        MOID (p) = *m;
 755        HEAP (entry) = LOC_SYMBOL;
 756        TAX (p) = entry;
 757        MOID (entry) = *m;
 758        if (ATTRIBUTE (*m) == REF_SYMBOL) {
 759          HEAP (entry) = tab_qualifier (NEXT_NEXT (p));
 760        }
 761        tax_identity_dec (NEXT_NEXT (p), m);
 762      } else {
 763        tax_tags (p);
 764      }
 765    }
 766  }
 767  
 768  //! @brief Enter variable declarations in the symbol table.
 769  
 770  void tax_variable_dec (NODE_T * p, int *q, MOID_T ** m)
 771  {
 772    if (p != NO_NODE) {
 773      if (IS (p, VARIABLE_DECLARATION)) {
 774        tax_variable_dec (SUB (p), q, m);
 775        tax_variable_dec (NEXT (p), q, m);
 776      } else if (IS (p, DECLARER)) {
 777        tax_tags (SUB (p));
 778        *m = MOID (p);
 779        tax_variable_dec (NEXT (p), q, m);
 780      } else if (IS (p, QUALIFIER)) {
 781        *q = ATTRIBUTE (SUB (p));
 782        tax_variable_dec (NEXT (p), q, m);
 783      } else if (IS (p, COMMA_SYMBOL)) {
 784        tax_variable_dec (NEXT (p), q, m);
 785      } else if (IS (p, DEFINING_IDENTIFIER)) {
 786        TAG_T *entry = find_tag_local (TABLE (p), IDENTIFIER, NSYMBOL (p));
 787        MOID (p) = *m;
 788        TAX (p) = entry;
 789        HEAP (entry) = *q;
 790        if (*q == LOC_SYMBOL) {
 791          TAG_T *z = add_tag (TABLE (p), ANONYMOUS, p, SUB (*m), GENERATOR);
 792          HEAP (z) = LOC_SYMBOL;
 793          USE (z) = A68G_TRUE;
 794          BODY (entry) = z;
 795        } else {
 796          BODY (entry) = NO_TAG;
 797        }
 798        MOID (entry) = *m;
 799        tax_variable_dec (NEXT (p), q, m);
 800      } else {
 801        tax_tags (p);
 802      }
 803    }
 804  }
 805  
 806  //! @brief Enter procedure variable declarations in the symbol table.
 807  
 808  void tax_proc_variable_dec (NODE_T * p, int *q)
 809  {
 810    if (p != NO_NODE) {
 811      if (IS (p, PROCEDURE_VARIABLE_DECLARATION)) {
 812        tax_proc_variable_dec (SUB (p), q);
 813        tax_proc_variable_dec (NEXT (p), q);
 814      } else if (IS (p, QUALIFIER)) {
 815        *q = ATTRIBUTE (SUB (p));
 816        tax_proc_variable_dec (NEXT (p), q);
 817      } else if (is_one_of (p, PROC_SYMBOL, COMMA_SYMBOL, STOP)) {
 818        tax_proc_variable_dec (NEXT (p), q);
 819      } else if (IS (p, DEFINING_IDENTIFIER)) {
 820        TAG_T *entry = find_tag_local (TABLE (p), IDENTIFIER, NSYMBOL (p));
 821        TAX (p) = entry;
 822        HEAP (entry) = *q;
 823        MOID (entry) = MOID (p);
 824        if (*q == LOC_SYMBOL) {
 825          TAG_T *z = add_tag (TABLE (p), ANONYMOUS, p, SUB_MOID (p), GENERATOR);
 826          HEAP (z) = LOC_SYMBOL;
 827          USE (z) = A68G_TRUE;
 828          BODY (entry) = z;
 829        } else {
 830          BODY (entry) = NO_TAG;
 831        }
 832        tax_proc_variable_dec (NEXT (p), q);
 833      } else {
 834        tax_tags (p);
 835      }
 836    }
 837  }
 838  
 839  //! @brief Enter procedure declarations in the symbol table.
 840  
 841  void tax_proc_dec (NODE_T * p)
 842  {
 843    if (p != NO_NODE) {
 844      if (IS (p, PROCEDURE_DECLARATION)) {
 845        tax_proc_dec (SUB (p));
 846        tax_proc_dec (NEXT (p));
 847      } else if (is_one_of (p, PROC_SYMBOL, COMMA_SYMBOL, STOP)) {
 848        tax_proc_dec (NEXT (p));
 849      } else if (IS (p, DEFINING_IDENTIFIER)) {
 850        TAG_T *entry = find_tag_local (TABLE (p), IDENTIFIER, NSYMBOL (p));
 851        MOID_T *m = MOID (NEXT_NEXT (p));
 852        MOID (p) = m;
 853        TAX (p) = entry;
 854        CODEX (entry) |= PROC_DECLARATION_MASK;
 855        HEAP (entry) = LOC_SYMBOL;
 856        MOID (entry) = m;
 857        tax_proc_dec (NEXT (p));
 858      } else {
 859        tax_tags (p);
 860      }
 861    }
 862  }
 863  
 864  //! @brief Check validity of operator declaration.
 865  
 866  void check_operator_dec (NODE_T * p, MOID_T * u)
 867  {
 868    int k = 0;
 869    if (u == NO_MOID) {
 870      NODE_T *pack = SUB_SUB (NEXT_NEXT (p));     // Where the parameter pack is
 871      if (ATTRIBUTE (NEXT_NEXT (p)) != ROUTINE_TEXT) {
 872        pack = SUB (pack);
 873      }
 874      k = 1 + count_operands (pack);
 875    } else {
 876      k = count_pack_members (PACK (u));
 877    }
 878    if (k < 1 || k > 2) {
 879      diagnostic (A68G_SYNTAX_ERROR, p, ERROR_OPERAND_NUMBER);
 880      k = 0;
 881    }
 882    if (k == 1 && strchr (NOMADS, NSYMBOL (p)[0]) != NO_TEXT) {
 883      diagnostic (A68G_SYNTAX_ERROR, p, ERROR_OPERATOR_INVALID, NOMADS);
 884    } else if (k == 2 && !find_tag_global (TABLE (p), PRIO_SYMBOL, NSYMBOL (p))) {
 885      diagnostic (A68G_SYNTAX_ERROR, p, ERROR_DYADIC_PRIORITY);
 886    }
 887  }
 888  
 889  //! @brief Enter operator declarations in the symbol table.
 890  
 891  void tax_op_dec (NODE_T * p, MOID_T ** m)
 892  {
 893    if (p != NO_NODE) {
 894      if (IS (p, OPERATOR_DECLARATION)) {
 895        tax_op_dec (SUB (p), m);
 896        tax_op_dec (NEXT (p), m);
 897      } else if (IS (p, OPERATOR_PLAN)) {
 898        tax_tags (SUB (p));
 899        *m = MOID (p);
 900        tax_op_dec (NEXT (p), m);
 901      } else if (IS (p, OP_SYMBOL)) {
 902        tax_op_dec (NEXT (p), m);
 903      } else if (IS (p, COMMA_SYMBOL)) {
 904        tax_op_dec (NEXT (p), m);
 905      } else if (IS (p, DEFINING_OPERATOR)) {
 906        TAG_T *entry = OPERATORS (TABLE (p));
 907        check_operator_dec (p, *m);
 908        while (entry != NO_TAG && NODE (entry) != p) {
 909          FORWARD (entry);
 910        }
 911        MOID (p) = *m;
 912        TAX (p) = entry;
 913        HEAP (entry) = LOC_SYMBOL;
 914        MOID (entry) = *m;
 915        tax_op_dec (NEXT (p), m);
 916      } else {
 917        tax_tags (p);
 918      }
 919    }
 920  }
 921  
 922  //! @brief Enter brief operator declarations in the symbol table.
 923  
 924  void tax_brief_op_dec (NODE_T * p)
 925  {
 926    if (p != NO_NODE) {
 927      if (IS (p, BRIEF_OPERATOR_DECLARATION)) {
 928        tax_brief_op_dec (SUB (p));
 929        tax_brief_op_dec (NEXT (p));
 930      } else if (is_one_of (p, OP_SYMBOL, COMMA_SYMBOL, STOP)) {
 931        tax_brief_op_dec (NEXT (p));
 932      } else if (IS (p, DEFINING_OPERATOR)) {
 933        TAG_T *entry = OPERATORS (TABLE (p));
 934        MOID_T *m = MOID (NEXT_NEXT (p));
 935        check_operator_dec (p, NO_MOID);
 936        while (entry != NO_TAG && NODE (entry) != p) {
 937          FORWARD (entry);
 938        }
 939        MOID (p) = m;
 940        TAX (p) = entry;
 941        HEAP (entry) = LOC_SYMBOL;
 942        MOID (entry) = m;
 943        tax_brief_op_dec (NEXT (p));
 944      } else {
 945        tax_tags (p);
 946      }
 947    }
 948  }
 949  
 950  //! @brief Enter priority declarations in the symbol table.
 951  
 952  void tax_prio_dec (NODE_T * p)
 953  {
 954    if (p != NO_NODE) {
 955      if (IS (p, PRIORITY_DECLARATION)) {
 956        tax_prio_dec (SUB (p));
 957        tax_prio_dec (NEXT (p));
 958      } else if (is_one_of (p, PRIO_SYMBOL, COMMA_SYMBOL, STOP)) {
 959        tax_prio_dec (NEXT (p));
 960      } else if (IS (p, DEFINING_OPERATOR)) {
 961        TAG_T *entry = PRIO (TABLE (p));
 962        while (entry != NO_TAG && NODE (entry) != p) {
 963          FORWARD (entry);
 964        }
 965        MOID (p) = NO_MOID;
 966        TAX (p) = entry;
 967        HEAP (entry) = LOC_SYMBOL;
 968        tax_prio_dec (NEXT (p));
 969      } else {
 970        tax_tags (p);
 971      }
 972    }
 973  }
 974  
 975  //! @brief Enter TAXes in the symbol table.
 976  
 977  void tax_tags (NODE_T * p)
 978  {
 979    for (; p != NO_NODE; FORWARD (p)) {
 980      int heap = LOC_SYMBOL;
 981      MOID_T *m = NO_MOID;
 982      if (IS (p, IDENTITY_DECLARATION)) {
 983        tax_identity_dec (p, &m);
 984      } else if (IS (p, VARIABLE_DECLARATION)) {
 985        tax_variable_dec (p, &heap, &m);
 986      } else if (IS (p, PROCEDURE_DECLARATION)) {
 987        tax_proc_dec (p);
 988      } else if (IS (p, PROCEDURE_VARIABLE_DECLARATION)) {
 989        tax_proc_variable_dec (p, &heap);
 990      } else if (IS (p, OPERATOR_DECLARATION)) {
 991        tax_op_dec (p, &m);
 992      } else if (IS (p, BRIEF_OPERATOR_DECLARATION)) {
 993        tax_brief_op_dec (p);
 994      } else if (IS (p, PRIORITY_DECLARATION)) {
 995        tax_prio_dec (p);
 996      } else {
 997        tax_tags (SUB (p));
 998      }
 999    }
1000  }
1001  
1002  //! @brief Reset symbol table nest count.
1003  
1004  void reset_symbol_table_nest_count (NODE_T * p)
1005  {
1006    for (; p != NO_NODE; FORWARD (p)) {
1007      if (SUB (p) != NO_NODE && is_new_lexical_level (p)) {
1008        NEST (TABLE (SUB (p))) = A68G (symbol_table_count)++;
1009      }
1010      reset_symbol_table_nest_count (SUB (p));
1011    }
1012  }
1013  
1014  //! @brief Bind routines in symbol table to the tree.
1015  
1016  void bind_routine_tags_to_tree (NODE_T * p)
1017  {
1018  // By inserting coercions etc. some may have shifted.
1019    for (; p != NO_NODE; FORWARD (p)) {
1020      if (IS (p, ROUTINE_TEXT) && TAX (p) != NO_TAG) {
1021        NODE (TAX (p)) = p;
1022      }
1023      bind_routine_tags_to_tree (SUB (p));
1024    }
1025  }
1026  
1027  //! @brief Bind formats in symbol table to tree.
1028  
1029  void bind_format_tags_to_tree (NODE_T * p)
1030  {
1031  // By inserting coercions etc. some may have shifted.
1032    for (; p != NO_NODE; FORWARD (p)) {
1033      if (IS (p, FORMAT_TEXT) && TAX (p) != NO_TAG) {
1034        NODE (TAX (p)) = p;
1035      } else if (IS (p, FORMAT_DELIMITER_SYMBOL) && NEXT (p) != NO_NODE && TAX (p) != NO_TAG) {
1036        NODE (TAX (p)) = p;
1037      }
1038      bind_format_tags_to_tree (SUB (p));
1039    }
1040  }
1041  
1042  //! @brief Fill outer level of symbol table.
1043  
1044  void fill_symbol_table_outer (NODE_T * p, TABLE_T * s)
1045  {
1046    for (; p != NO_NODE; FORWARD (p)) {
1047      if (TABLE (p) != NO_TABLE) {
1048        OUTER (TABLE (p)) = s;
1049      }
1050      if (SUB (p) != NO_NODE && IS (p, ROUTINE_TEXT)) {
1051        fill_symbol_table_outer (SUB (p), TABLE (SUB (p)));
1052      } else if (SUB (p) != NO_NODE && IS (p, FORMAT_TEXT)) {
1053        fill_symbol_table_outer (SUB (p), TABLE (SUB (p)));
1054      } else {
1055        fill_symbol_table_outer (SUB (p), s);
1056      }
1057    }
1058  }
1059  
1060  //! @brief Flood branch in tree with local symbol table "s".
1061  
1062  void flood_with_symbol_table_restricted (NODE_T * p, TABLE_T * s)
1063  {
1064    for (; p != NO_NODE; FORWARD (p)) {
1065      TABLE (p) = s;
1066      if (ATTRIBUTE (p) != ROUTINE_TEXT && ATTRIBUTE (p) != SPECIFIED_UNIT) {
1067        if (is_new_lexical_level (p)) {
1068          PREVIOUS (TABLE (SUB (p))) = s;
1069        } else {
1070          flood_with_symbol_table_restricted (SUB (p), s);
1071        }
1072      }
1073    }
1074  }
1075  
1076  //! @brief Final structure of symbol table after parsing.
1077  
1078  void finalise_symbol_table_setup (NODE_T * p, int l)
1079  {
1080    TABLE_T *s = TABLE (p);
1081    NODE_T *q = p;
1082    while (q != NO_NODE) {
1083  // routine texts are ranges.
1084      if (IS (q, ROUTINE_TEXT)) {
1085        flood_with_symbol_table_restricted (SUB (q), new_symbol_table (s));
1086      }
1087  // specifiers are ranges.
1088      else if (IS (q, SPECIFIED_UNIT)) {
1089        flood_with_symbol_table_restricted (SUB (q), new_symbol_table (s));
1090      }
1091  // level count and recursion.
1092      if (SUB (q) != NO_NODE) {
1093        if (is_new_lexical_level (q)) {
1094          LEX_LEVEL (SUB (q)) = l + 1;
1095          PREVIOUS (TABLE (SUB (q))) = s;
1096          finalise_symbol_table_setup (SUB (q), l + 1);
1097          if (IS (q, WHILE_PART)) {
1098  // This was a bug that went unnoticed for 15 years!.
1099            TABLE_T *s2 = TABLE (SUB (q));
1100            if ((FORWARD (q)) == NO_NODE) {
1101              return;
1102            }
1103            if (IS (q, ALT_DO_PART)) {
1104              PREVIOUS (TABLE (SUB (q))) = s2;
1105              LEX_LEVEL (SUB (q)) = l + 2;
1106              finalise_symbol_table_setup (SUB (q), l + 2);
1107            }
1108          }
1109        } else {
1110          TABLE (SUB (q)) = s;
1111          finalise_symbol_table_setup (SUB (q), l);
1112        }
1113      }
1114      TABLE (q) = s;
1115      if (IS (q, FOR_SYMBOL)) {
1116        FORWARD (q);
1117      }
1118      FORWARD (q);
1119    }
1120  // FOR identifiers are in the DO ... OD range.
1121    for (q = p; q != NO_NODE; FORWARD (q)) {
1122      if (IS (q, FOR_SYMBOL)) {
1123        TABLE (NEXT (q)) = TABLE (SEQUENCE (NEXT (q)));
1124      }
1125    }
1126  }
1127  
1128  //! @brief First structure of symbol table for parsing.
1129  
1130  void preliminary_symbol_table_setup (NODE_T * p)
1131  {
1132    TABLE_T *s = TABLE (p);
1133    BOOL_T not_a_for_range = A68G_FALSE;
1134  // let the tree point to the current symbol table.
1135    for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1136      TABLE (q) = s;
1137    }
1138  // insert new tables when required.
1139    for (NODE_T *q = p; q != NO_NODE && !not_a_for_range; FORWARD (q)) {
1140      if (SUB (q) != NO_NODE) {
1141  // BEGIN ... END, CODE ... EDOC, DEF ... FED, DO ... OD, $ ... $, { ... } are ranges.
1142        if (is_one_of (q, BEGIN_SYMBOL, DO_SYMBOL, ALT_DO_SYMBOL, FORMAT_DELIMITER_SYMBOL, ACCO_SYMBOL, STOP)) {
1143          TABLE (SUB (q)) = new_symbol_table (s);
1144          preliminary_symbol_table_setup (SUB (q));
1145        }
1146  // ( ... ) is a range.
1147        else if (IS (q, OPEN_SYMBOL)) {
1148          if (whether (q, OPEN_SYMBOL, THEN_BAR_SYMBOL, STOP)) {
1149            TABLE (SUB (q)) = s;
1150            preliminary_symbol_table_setup (SUB (q));
1151            FORWARD (q);
1152            TABLE (SUB (q)) = new_symbol_table (s);
1153            preliminary_symbol_table_setup (SUB (q));
1154            if ((FORWARD (q)) == NO_NODE) {
1155              not_a_for_range = A68G_TRUE;
1156            } else {
1157              if (IS (q, THEN_BAR_SYMBOL)) {
1158                TABLE (SUB (q)) = new_symbol_table (s);
1159                preliminary_symbol_table_setup (SUB (q));
1160              }
1161              if (IS (q, OPEN_SYMBOL)) {
1162                TABLE (SUB (q)) = new_symbol_table (s);
1163                preliminary_symbol_table_setup (SUB (q));
1164              }
1165            }
1166          } else {
1167  // don't worry about STRUCT (...), UNION (...), PROC (...) yet.
1168            TABLE (SUB (q)) = new_symbol_table (s);
1169            preliminary_symbol_table_setup (SUB (q));
1170          }
1171        }
1172  // IF ... THEN ... ELSE ... FI are ranges.
1173        else if (IS (q, IF_SYMBOL)) {
1174          if (whether (q, IF_SYMBOL, THEN_SYMBOL, STOP)) {
1175            TABLE (SUB (q)) = s;
1176            preliminary_symbol_table_setup (SUB (q));
1177            FORWARD (q);
1178            TABLE (SUB (q)) = new_symbol_table (s);
1179            preliminary_symbol_table_setup (SUB (q));
1180            if ((FORWARD (q)) == NO_NODE) {
1181              not_a_for_range = A68G_TRUE;
1182            } else {
1183              if (IS (q, ELSE_SYMBOL)) {
1184                TABLE (SUB (q)) = new_symbol_table (s);
1185                preliminary_symbol_table_setup (SUB (q));
1186              }
1187              if (IS (q, IF_SYMBOL)) {
1188                TABLE (SUB (q)) = new_symbol_table (s);
1189                preliminary_symbol_table_setup (SUB (q));
1190              }
1191            }
1192          } else {
1193            TABLE (SUB (q)) = new_symbol_table (s);
1194            preliminary_symbol_table_setup (SUB (q));
1195          }
1196        }
1197  // CASE ... IN ... OUT ... ESAC are ranges.
1198        else if (IS (q, CASE_SYMBOL)) {
1199          if (whether (q, CASE_SYMBOL, IN_SYMBOL, STOP)) {
1200            TABLE (SUB (q)) = s;
1201            preliminary_symbol_table_setup (SUB (q));
1202            FORWARD (q);
1203            TABLE (SUB (q)) = new_symbol_table (s);
1204            preliminary_symbol_table_setup (SUB (q));
1205            if ((FORWARD (q)) == NO_NODE) {
1206              not_a_for_range = A68G_TRUE;
1207            } else {
1208              if (IS (q, OUT_SYMBOL)) {
1209                TABLE (SUB (q)) = new_symbol_table (s);
1210                preliminary_symbol_table_setup (SUB (q));
1211              }
1212              if (IS (q, CASE_SYMBOL)) {
1213                TABLE (SUB (q)) = new_symbol_table (s);
1214                preliminary_symbol_table_setup (SUB (q));
1215              }
1216            }
1217          } else {
1218            TABLE (SUB (q)) = new_symbol_table (s);
1219            preliminary_symbol_table_setup (SUB (q));
1220          }
1221        }
1222  // UNTIL ... OD is a range.
1223        else if (IS (q, UNTIL_SYMBOL) && SUB (q) != NO_NODE) {
1224          TABLE (SUB (q)) = new_symbol_table (s);
1225          preliminary_symbol_table_setup (SUB (q));
1226  // WHILE ... DO ... OD are ranges.
1227        } else if (IS (q, WHILE_SYMBOL)) {
1228          TABLE_T *u = new_symbol_table (s);
1229          TABLE (SUB (q)) = u;
1230          preliminary_symbol_table_setup (SUB (q));
1231          if ((FORWARD (q)) == NO_NODE) {
1232            not_a_for_range = A68G_TRUE;
1233          } else if (IS (q, ALT_DO_SYMBOL)) {
1234            TABLE (SUB (q)) = new_symbol_table (u);
1235            preliminary_symbol_table_setup (SUB (q));
1236          }
1237        } else {
1238          TABLE (SUB (q)) = s;
1239          preliminary_symbol_table_setup (SUB (q));
1240        }
1241      }
1242    }
1243  // FOR identifiers will go to the DO ... OD range.
1244    if (!not_a_for_range) {
1245      for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1246        if (IS (q, FOR_SYMBOL)) {
1247          NODE_T *r = q;
1248          TABLE (NEXT (q)) = NO_TABLE;
1249          for (; r != NO_NODE && TABLE (NEXT (q)) == NO_TABLE; FORWARD (r)) {
1250            if ((is_one_of (r, WHILE_SYMBOL, ALT_DO_SYMBOL, STOP)) && (NEXT (q) != NO_NODE && SUB (r) != NO_NODE)) {
1251              TABLE (NEXT (q)) = TABLE (SUB (r));
1252              SEQUENCE (NEXT (q)) = SUB (r);
1253            }
1254          }
1255        }
1256      }
1257    }
1258  }
1259  
1260  //! @brief Mark a mode as in use.
1261  
1262  void mark_mode (MOID_T * m)
1263  {
1264    if (m != NO_MOID && USE (m) == A68G_FALSE) {
1265      PACK_T *p = PACK (m);
1266      USE (m) = A68G_TRUE;
1267      for (; p != NO_PACK; FORWARD (p)) {
1268        mark_mode (MOID (p));
1269        mark_mode (SUB (m));
1270        mark_mode (SLICE (m));
1271      }
1272    }
1273  }
1274  
1275  //! @brief Traverse tree and mark modes as used.
1276  
1277  void mark_moids (NODE_T * p)
1278  {
1279    for (; p != NO_NODE; FORWARD (p)) {
1280      mark_moids (SUB (p));
1281      if (MOID (p) != NO_MOID) {
1282        mark_mode (MOID (p));
1283      }
1284    }
1285  }
1286  
1287  //! @brief Mark various tags as used.
1288  
1289  void mark_auxilliary (NODE_T * p)
1290  {
1291    for (; p != NO_NODE; FORWARD (p)) {
1292      if (SUB (p) != NO_NODE) {
1293  // You get no warnings on unused PROC parameters. That is ok since A68 has some
1294  // parameters that you may not use at all - think of PROC (REF FILE) BOOL event
1295  // routines in transput.
1296        mark_auxilliary (SUB (p));
1297      } else if (IS (p, OPERATOR)) {
1298        TAG_T *z;
1299        if (TAX (p) != NO_TAG) {
1300          USE (TAX (p)) = A68G_TRUE;
1301        }
1302        if ((z = find_tag_global (TABLE (p), PRIO_SYMBOL, NSYMBOL (p))) != NO_TAG) {
1303          USE (z) = A68G_TRUE;
1304        }
1305      } else if (IS (p, INDICANT)) {
1306        TAG_T *z = find_tag_global (TABLE (p), INDICANT, NSYMBOL (p));
1307        if (z != NO_TAG) {
1308          TAX (p) = z;
1309          USE (z) = A68G_TRUE;
1310        }
1311      } else if (IS (p, IDENTIFIER)) {
1312        if (TAX (p) != NO_TAG) {
1313          USE (TAX (p)) = A68G_TRUE;
1314        }
1315      }
1316    }
1317  }
1318  
1319  //! @brief Check a single tag.
1320  
1321  void unused (TAG_T * s)
1322  {
1323    for (; s != NO_TAG; FORWARD (s)) {
1324      if (LINE_NUMBER (NODE (s)) > 0 && !USE (s)) {
1325        diagnostic (A68G_NOTICE, NODE (s), WARNING_TAG_UNUSED, NODE (s));
1326      }
1327    }
1328  }
1329  
1330  //! @brief Driver for traversing tree and warn for unused tags.
1331  
1332  void warn_for_unused_tags (NODE_T * p)
1333  {
1334    for (; p != NO_NODE; FORWARD (p)) {
1335      if (SUB (p) != NO_NODE) {
1336        if (is_new_lexical_level (p) && ATTRIBUTE (TABLE (SUB (p))) != ENVIRON_SYMBOL) {
1337          unused (OPERATORS (TABLE (SUB (p))));
1338          unused (PRIO (TABLE (SUB (p))));
1339          unused (IDENTIFIERS (TABLE (SUB (p))));
1340          unused (LABELS (TABLE (SUB (p))));
1341          unused (INDICANTS (TABLE (SUB (p))));
1342        }
1343      }
1344      warn_for_unused_tags (SUB (p));
1345    }
1346  }
1347  
1348  //! @brief Mark jumps and procedured jumps.
1349  
1350  void jumps_from_procs (NODE_T * p)
1351  {
1352    for (; p != NO_NODE; FORWARD (p)) {
1353      if (IS (p, PROCEDURING)) {
1354        NODE_T *u = SUB_SUB (p);
1355        if (IS (u, GOTO_SYMBOL)) {
1356          FORWARD (u);
1357        }
1358        USE (TAX (u)) = A68G_TRUE;
1359      } else if (IS (p, JUMP)) {
1360        NODE_T *u = SUB (p);
1361        if (IS (u, GOTO_SYMBOL)) {
1362          FORWARD (u);
1363        }
1364        if ((TAX (u) == NO_TAG) && (MOID (u) == NO_MOID) && (find_tag_global (TABLE (u), LABEL, NSYMBOL (u)) == NO_TAG)) {
1365          TAG_T *t = add_tag (TABLE (u), LABEL, u, NO_MOID, LOCAL_LABEL);
1366          USE (t) = A68G_TRUE;
1367          diagnostic (A68G_ERROR, u, ERROR_UNDECLARED_TAG);
1368        } else if (TAX (u) != NO_TAG) {
1369          USE (TAX (u)) = A68G_TRUE;
1370        }
1371      } else {
1372        jumps_from_procs (SUB (p));
1373      }
1374    }
1375  }
1376  
1377  //! @brief Assign offset tags.
1378  
1379  ADDR_T assign_offset_tags (TAG_T * t, ADDR_T base)
1380  {
1381    ADDR_T sum = base;
1382    for (; t != NO_TAG; FORWARD (t)) {
1383      ABEND (MOID (t) == NO_MOID, ERROR_INTERNAL_CONSISTENCY, NSYMBOL (NODE (t)));
1384      SIZE (t) = moid_size (MOID (t));
1385      if (VALUE (t) == NO_TEXT) {
1386        OFFSET (t) = sum;
1387        sum += SIZE (t);
1388      }
1389    }
1390    return sum;
1391  }
1392  
1393  //! @brief Assign offsets table.
1394  
1395  void assign_offsets_table (TABLE_T * c)
1396  {
1397    AP_INCREMENT (c) = assign_offset_tags (IDENTIFIERS (c), 0);
1398    AP_INCREMENT (c) = assign_offset_tags (OPERATORS (c), AP_INCREMENT (c));
1399    AP_INCREMENT (c) = assign_offset_tags (ANONYMOUS (c), AP_INCREMENT (c));
1400    AP_INCREMENT (c) = A68G_ALIGN (AP_INCREMENT (c));
1401  }
1402  
1403  //! @brief Assign offsets.
1404  
1405  void assign_offsets (NODE_T * p)
1406  {
1407    for (; p != NO_NODE; FORWARD (p)) {
1408      if (SUB (p) != NO_NODE && is_new_lexical_level (p)) {
1409        assign_offsets_table (TABLE (SUB (p)));
1410      }
1411      assign_offsets (SUB (p));
1412    }
1413  }
1414  
1415  //! @brief Assign offsets packs in moid list.
1416  
1417  void assign_offsets_packs (MOID_T * q)
1418  {
1419    for (; q != NO_MOID; FORWARD (q)) {
1420      if (EQUIVALENT (q) == NO_MOID && IS (q, STRUCT_SYMBOL)) {
1421        PACK_T *p = PACK (q);
1422        ADDR_T offset = 0;
1423        for (; p != NO_PACK; FORWARD (p)) {
1424          SIZE (p) = moid_size (MOID (p));
1425          OFFSET (p) = offset;
1426          offset += SIZE (p);
1427        }
1428      }
1429    }
1430  }
     


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