a68g-options.c

     
   1  //! @file a68g-options.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-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  //! Algol 68 Genie options.
  25  
  26  #include "a68g.h"
  27  #include "a68g-prelude.h"
  28  #include "a68g-mp.h"
  29  #include "a68g-options.h"
  30  #include "a68g-parser.h"
  31  
  32  // This code options to Algol68G.
  33  // 
  34  // Option syntax does not follow GNU standards.
  35  // 
  36  // Options come from:
  37  //   [1] A rc file (normally .a68grc).
  38  //   [2] The A68G_OPTIONS environment variable overrules [1].
  39  //   [3] Command line options overrule [2].
  40  //   [4] Pragmat items overrule [3]. 
  41  
  42  //! @brief Strip minus preceeding a string.
  43  
  44  char *strip_sign (char *p)
  45  {
  46    char *q = p;
  47    while (q[0] == '-' || q[0] == '+') {
  48      q++;
  49    }
  50    if (strlen (q) > 0) {
  51      return new_string (q, NO_TEXT);
  52    } else {
  53      return p;
  54    }
  55  }
  56  
  57  //! @brief Error handler for options.
  58  
  59  void option_error (LINE_T * l, char *option, char *info)
  60  {
  61    if (option != NO_TEXT) {
  62      ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "%s", strip_sign (option)) >= 0);
  63      if (info != NO_TEXT) {
  64        ASSERT (a68g_bufprt (A68G (edit_line), SNPRINTF_SIZE, "%s at option \"%s\"", info, A68G (output_line)) >= 0);
  65      } else {
  66        ASSERT (a68g_bufprt (A68G (edit_line), SNPRINTF_SIZE, "at option \"%s\"", A68G (output_line)) >= 0);
  67      }
  68    } else if (info != NO_TEXT) {
  69      ASSERT (a68g_bufprt (A68G (edit_line), SNPRINTF_SIZE, "%s", info) >= 0);
  70    } else {
  71      ASSERT (a68g_bufprt (A68G (edit_line), SNPRINTF_SIZE, "at option") >= 0);
  72    }
  73    scan_error (l, NO_TEXT, A68G (edit_line));
  74  }
  75  
  76  //! @brief Check overflow at integer multiplication.
  77  
  78  BOOL_T int_mul_overflow (UNSIGNED_T u, UNSIGNED_T v, UNSIGNED_T max_int)
  79  {
  80    if (u == 0 || v == 0) {
  81      return (A68G_FALSE);
  82    } else {
  83      return v > max_int / u;
  84    }
  85  }
  86  
  87  //! @brief Set default core size.
  88  
  89  void default_mem_sizes (INT_T n, LINE_T *start_l, char *start_c)
  90  {
  91    #define SET_SIZE(m, n) {\
  92      if (int_mul_overflow (n, MEGABYTE, MAX_MEM_SIZE)) {\
  93        option_error (start_l, start_c, ERROR_VALUE_TOO_LARGE);\
  94        return;\
  95      } else if ((n) * MEGABYTE + A68G (storage_overhead) > MAX_MEM_SIZE) {\
  96        option_error (start_l, start_c, ERROR_VALUE_TOO_LARGE);\
  97        return;\
  98      } else {\
  99        (m) = (n) * MEGABYTE + A68G (storage_overhead);\
 100      }}
 101  
 102    n = MAX (n, 1);
 103    A68G (storage_overhead) = MEM_OVERHEAD;
 104    SET_SIZE (A68G (frame_stack_size), 10 * n);
 105    SET_SIZE (A68G (expr_stack_size), 5 * n);
 106    SET_SIZE (A68G (heap_size), 65 * n);
 107    SET_SIZE (A68G (handle_pool_size), 20 * n);
 108  #undef SET_SIZE
 109  }
 110  
 111  //! @brief Read options from the .rc file.
 112  
 113  void read_rc_options (void)
 114  {
 115    BUFFER name, new_name;
 116    BUFCLR (name);
 117    BUFCLR (new_name);
 118    ASSERT (a68g_bufprt (name, SNPRINTF_SIZE, ".%src", A68G (a68g_cmd_name)) >= 0);
 119    FILE *f = a68g_fopen (name, "r", new_name);
 120    if (f != NO_FILE) {
 121      while (!feof (f)) {
 122        if (fgets (A68G (input_line), BUFFER_SIZE, f) != NO_TEXT) {
 123          size_t len = strlen (A68G (input_line));
 124          if (len > 0 && A68G (input_line)[len - 1] == NEWLINE_CHAR) {
 125            A68G (input_line)[len - 1] = NULL_CHAR;
 126          }
 127          isolate_options (A68G (input_line), NO_LINE);
 128        }
 129      }
 130      ASSERT (fclose (f) == 0);
 131      (void) set_options (OPTION_LIST (&A68G_JOB), A68G_FALSE);
 132    } else {
 133      errno = 0;
 134    }
 135  }
 136  
 137  //! @brief Read options from A68G_OPTIONS.
 138  
 139  void read_env_options (void)
 140  {
 141    if (getenv ("A68G_OPTIONS") != NULL) {
 142      isolate_options (getenv ("A68G_OPTIONS"), NO_LINE);
 143      (void) set_options (OPTION_LIST (&A68G_JOB), A68G_FALSE);
 144      errno = 0;
 145    }
 146  }
 147  
 148  //! @brief Tokenise string 'p' that holds options.
 149  
 150  void isolate_options (char *p, LINE_T * line)
 151  {
 152    while (p != NO_TEXT && p[0] != NULL_CHAR) {
 153  // Skip white space etc.
 154      while ((p[0] == BLANK_CHAR || p[0] == TAB_CHAR || p[0] == ',' || p[0] == NEWLINE_CHAR) && p[0] != NULL_CHAR) {
 155        p++;
 156      }
 157  // ... then tokenise an item.
 158      if (p[0] != NULL_CHAR) {
 159        char *q;
 160  // Item can be "string". Note that these are not A68 strings.
 161        if (p[0] == QUOTE_CHAR || p[0] == '\'' || p[0] == '`') {
 162          char delim = p[0];
 163          p++;
 164  // 'q' points at first significant char in item.
 165          q = p;
 166          while (p[0] != delim && p[0] != NULL_CHAR) {
 167            p++;
 168          }
 169          if (p[0] != NULL_CHAR) {
 170            p[0] = NULL_CHAR;     // p[0] was delimiter
 171            p++;
 172          } else {
 173            scan_error (line, NO_TEXT, ERROR_UNTERMINATED_STRING);
 174          }
 175        } else {
 176  // Item is not a delimited string.
 177          q = p;
 178  // Tokenise symbol and gather it in the option list for later processing.
 179  // Skip '='s, we accept if someone writes -prec=60 -heap=8192
 180          if (*q == '=') {
 181            p++;
 182          } else {
 183  // Skip item 
 184            while (p[0] != BLANK_CHAR && p[0] != NULL_CHAR && p[0] != '=' && p[0] != ',' && p[0] != NEWLINE_CHAR) {
 185              p++;
 186            }
 187          }
 188          if (p[0] != NULL_CHAR) {
 189            p[0] = NULL_CHAR;
 190            p++;
 191          }
 192        }
 193  // 'q' points to first significant char in item, and 'p' points after item.
 194        add_option_list (&(OPTION_LIST (&A68G_JOB)), q, line);
 195      }
 196    }
 197  }
 198  
 199  //! @brief Set default values for options.
 200  
 201  void default_options (MODULE_T * p)
 202  {
 203    OPTION_BACKTRACE (p) = A68G_FALSE;
 204    OPTION_BRACKETS (p) = A68G_FALSE;
 205    OPTION_CHECK_ONLY (p) = A68G_FALSE;
 206    OPTION_CLOCK (p) = A68G_FALSE;
 207    OPTION_COMPILE_CHECK (p) = A68G_FALSE;
 208    OPTION_COMPILE (p) = A68G_FALSE;
 209    OPTION_CONSERVATIVE_GC (p) = A68G_GC_GO;
 210    OPTION_CROSS_REFERENCE (p) = A68G_FALSE;
 211    OPTION_DEBUG (p) = A68G_FALSE;
 212    OPTION_FOLD (p) = A68G_FALSE;
 213    OPTION_INDENT (p) = 2;
 214    OPTION_KEEP (p) = A68G_FALSE;
 215    OPTION_LICENSE (p) = A68G_FALSE;
 216    OPTION_MOID_LISTING (p) = A68G_FALSE;
 217    OPTION_NODEMASK (p) = (STATUS_MASK_T) (ASSERT_MASK | SOURCE_MASK);
 218    OPTION_NO_NOTICES (p) = A68G_TRUE;
 219    OPTION_NO_WARNINGS (p) = A68G_FALSE;
 220    OPTION_OPT_LEVEL (p) = NO_OPTIMISE;
 221    OPTION_PORTCHECK (p) = A68G_FALSE;
 222    OPTION_PRAGMAT_SEMA (p) = A68G_TRUE;
 223    OPTION_PRETTY (p) = A68G_FALSE;
 224    OPTION_QUIET (p) = A68G_FALSE;
 225    OPTION_REDUCTIONS (p) = A68G_FALSE;
 226    OPTION_REGRESSION_TEST (p) = A68G_FALSE;
 227    OPTION_RERUN (p) = A68G_FALSE;
 228    OPTION_RUN (p) = A68G_FALSE;
 229    OPTION_RUN_SCRIPT (p) = A68G_FALSE;
 230    OPTION_SOURCE_LISTING (p) = A68G_FALSE;
 231    OPTION_STANDARD_PRELUDE_LISTING (p) = A68G_FALSE;
 232    OPTION_STATISTICS_LISTING (p) = A68G_FALSE;
 233    OPTION_STRICT (p) = A68G_FALSE;
 234    OPTION_STROPPING (p) = UPPER_STROPPING;
 235    OPTION_TIME_LIMIT (p) = 0;
 236    OPTION_TRACE (p) = A68G_FALSE;
 237    OPTION_TREE_LISTING (p) = A68G_FALSE;
 238    OPTION_UNUSED (p) = A68G_FALSE;
 239    OPTION_VERBOSE (p) = A68G_FALSE;
 240    OPTION_VERSION (p) = A68G_FALSE;
 241    set_long_mp_digits (0);
 242  }
 243  
 244  //! @brief Add an option to the list, to be processed later.
 245  
 246  void add_option_list (OPTION_LIST_T ** l, char *str, LINE_T * line)
 247  {
 248    if (*l == NO_OPTION_LIST) {
 249      *l = (OPTION_LIST_T *) get_heap_space (SIZE_ALIGNED (OPTION_LIST_T));
 250      SCAN (*l) = SOURCE_SCAN (&A68G_JOB);
 251      STR (*l) = new_string (str, NO_TEXT);
 252      PROCESSED (*l) = A68G_FALSE;
 253      LINE (*l) = line;
 254      NEXT (*l) = NO_OPTION_LIST;
 255    } else {
 256      add_option_list (&(NEXT (*l)), str, line);
 257    }
 258  }
 259  
 260  //! @brief Free an option list.
 261  
 262  void free_option_list (OPTION_LIST_T * l)
 263  {
 264    if (l != NO_OPTION_LIST) {
 265      free_option_list (NEXT (l));
 266      a68g_free (STR (l));
 267      a68g_free (l);
 268    }
 269  }
 270  
 271  //! @brief Initialise option handler.
 272  
 273  void init_options (void)
 274  {
 275    A68G (options) = (OPTIONS_T *) a68g_alloc (SIZE_ALIGNED (OPTIONS_T), __func__, __LINE__);
 276    OPTION_LIST (&A68G_JOB) = NO_OPTION_LIST;
 277  }
 278  
 279  //! @brief Test equality of p and q, upper case letters in q are mandatory.
 280  
 281  static inline BOOL_T eq (char *p, char *q)
 282  {
 283  // Upper case letters in 'q' are mandatory, lower case must match.
 284    if (OPTION_PRAGMAT_SEMA (&A68G_JOB)) {
 285      return match_string (p, q, '=');
 286    } else {
 287      return A68G_FALSE;
 288    }
 289  }
 290  
 291  //! @brief Process echoes gathered in the option list.
 292  
 293  void prune_echoes (OPTION_LIST_T * ol)
 294  {
 295    while (ol != NO_OPTION_LIST) {
 296      if (SCAN (ol) == SOURCE_SCAN (&A68G_JOB)) {
 297        char *p = strip_sign (STR (ol));
 298  // ECHO echoes a string.
 299        if (eq (p, "ECHO")) {
 300          {
 301            char *car = strchr (p, '=');
 302            if (car != NO_TEXT) {
 303              io_close_tty_line ();
 304              ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "%s", &car[1]) >= 0);
 305              WRITE (A68G_STDOUT, A68G (output_line));
 306            } else {
 307              FORWARD (ol);
 308              if (ol != NO_OPTION_LIST) {
 309                if (strcmp (STR (ol), "=") == 0) {
 310                  FORWARD (ol);
 311                }
 312                if (ol != NO_OPTION_LIST) {
 313                  io_close_tty_line ();
 314                  ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "%s", STR (ol)) >= 0);
 315                  WRITE (A68G_STDOUT, A68G (output_line));
 316                }
 317              }
 318            }
 319          }
 320        }
 321        a68g_free (p);
 322      }
 323      if (ol != NO_OPTION_LIST) {
 324        FORWARD (ol);
 325      }
 326    }
 327  }
 328  
 329  //! @brief Translate integral option argument.
 330  
 331  static UNSIGNED_T fetch_integral (char *p, OPTION_LIST_T ** i, BOOL_T * error, UNSIGNED_T max_int)
 332  {
 333    LINE_T *start_l = LINE (*i);
 334    char *start_c = STR (*i);
 335    char *car = NO_TEXT, *num = NO_TEXT;
 336    *error = A68G_FALSE;
 337  // Fetch argument.
 338    car = strchr (p, '=');
 339    if (car == NO_TEXT) {
 340      FORWARD (*i);
 341      *error = (BOOL_T) (*i == NO_OPTION_LIST);
 342      if (!*error && strcmp (STR (*i), "=") == 0) {
 343        FORWARD (*i);
 344        *error = (BOOL_T) (*i == NO_OPTION_LIST);
 345      }
 346      if (!*error) {
 347        num = STR (*i);
 348      }
 349    } else {
 350      num = &car[1];
 351      *error = (BOOL_T) (num[0] == NULL_CHAR);
 352    }
 353  // Translate argument into integer.
 354    if (*error) {
 355      option_error (start_l, start_c, ERROR_MISSING_STUFF);
 356      return 0;
 357    } else {
 358      if (num[0] == '-') {
 359        option_error (start_l, start_c, ERROR_INVALID_VALUE);
 360        return 0;
 361      }
 362      char *suffix;
 363      errno = 0;
 364      #if (A68G_LEVEL >= 3)
 365        UNSIGNED_T mult = 1, value = (UNSIGNED_T) strtoul (num, &suffix, 0);
 366      #else
 367        UNSIGNED_T mult = 1, value = (UNSIGNED_T) strtoull (num, &suffix, 0);
 368      #endif
 369      *error = (BOOL_T) (suffix == num);
 370      if (errno != 0 || *error) {
 371        option_error (start_l, start_c, ERROR_INVALID_VALUE);
 372        *error = A68G_TRUE;
 373      } else if (value < 0) {
 374        option_error (start_l, start_c, ERROR_INVALID_VALUE);
 375        *error = A68G_TRUE;
 376      } else {
 377  // Accept suffix multipliers: 32k, 64M, 1G, (2T, 1P).
 378        if (suffix != NO_TEXT) {
 379          switch (suffix[0]) {
 380          case NULL_CHAR: {
 381              mult = 1;
 382              break;
 383            }
 384          case 'k':
 385          case 'K': {
 386              mult = KILOBYTE;
 387              break;
 388            }
 389          case 'm':
 390          case 'M': {
 391              mult = MEGABYTE;
 392              break;
 393            }
 394          case 'g':
 395          case 'G': {
 396              mult = GIGABYTE;
 397              break;
 398            }
 399          #if defined (TERABYTE)
 400            case 't':
 401            case 'T': {
 402                mult = TERABYTE;
 403                break;
 404              }
 405          #endif
 406          #if defined (PETABYTE)
 407            case 'p':
 408            case 'P': {
 409                mult = PETABYTE;
 410                break;
 411              }
 412          #endif
 413          default: {
 414              option_error (start_l, start_c, ERROR_INVALID_VALUE);
 415              *error = A68G_TRUE;
 416              break;
 417            }
 418          }
 419          if (suffix[0] != NULL_CHAR && suffix[1] != NULL_CHAR) {
 420            option_error (start_l, start_c, ERROR_INVALID_VALUE);
 421            *error = A68G_TRUE;
 422          }
 423        }
 424      }
 425  // Check overflow.
 426      if (int_mul_overflow (value, mult, max_int)) {
 427        option_error (start_l, start_c, ERROR_VALUE_TOO_LARGE);
 428        return 0;
 429      } else {
 430        return value * mult;
 431      }
 432    }
 433  }
 434  
 435  //! @brief Dump technical information.
 436  
 437  static void tech_stuff (void)
 438  {
 439    state_version (A68G_STDOUT);
 440    ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "sizeof (A68G_REF) = " A68G_LU, (UNSIGNED_T) sizeof (A68G_REF)) >= 0);
 441    WRITELN (A68G_STDOUT, A68G (output_line));
 442    ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "sizeof (A68G_PROCEDURE) = " A68G_LU, (UNSIGNED_T) sizeof (A68G_PROCEDURE)) >= 0);
 443    WRITELN (A68G_STDOUT, A68G (output_line));
 444  #if (A68G_LEVEL >= 3)
 445    ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "sizeof (DOUBLE_T) = " A68G_LU, (UNSIGNED_T) sizeof (DOUBLE_T)) >= 0);
 446    WRITELN (A68G_STDOUT, A68G (output_line));
 447    ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "sizeof (DOUBLE_NUM_T) = " A68G_LU, (UNSIGNED_T) sizeof (DOUBLE_NUM_T)) >= 0);
 448    WRITELN (A68G_STDOUT, A68G (output_line));
 449  #endif
 450    ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "sizeof (A68G_INT) = " A68G_LU, (UNSIGNED_T) sizeof (A68G_INT)) >= 0);
 451    WRITELN (A68G_STDOUT, A68G (output_line));
 452    ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "sizeof (A68G_REAL) = " A68G_LU, (UNSIGNED_T) sizeof (A68G_REAL)) >= 0);
 453    WRITELN (A68G_STDOUT, A68G (output_line));
 454    ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "sizeof (A68G_BOOL) = " A68G_LU, (UNSIGNED_T) sizeof (A68G_BOOL)) >= 0);
 455    WRITELN (A68G_STDOUT, A68G (output_line));
 456    ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "sizeof (A68G_CHAR) = " A68G_LU, (UNSIGNED_T) sizeof (A68G_CHAR)) >= 0);
 457    WRITELN (A68G_STDOUT, A68G (output_line));
 458    ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "sizeof (A68G_BITS) = " A68G_LU, (UNSIGNED_T) sizeof (A68G_BITS)) >= 0);
 459    WRITELN (A68G_STDOUT, A68G (output_line));
 460  #if (A68G_LEVEL >= 3)
 461    ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "sizeof (A68G_LONG_INT) = " A68G_LU, (UNSIGNED_T) sizeof (A68G_LONG_INT)) >= 0);
 462    WRITELN (A68G_STDOUT, A68G (output_line));
 463    ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "sizeof (A68G_LONG_REAL) = " A68G_LU, (UNSIGNED_T) sizeof (A68G_LONG_REAL)) >= 0);
 464    WRITELN (A68G_STDOUT, A68G (output_line));
 465  #else
 466    ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "sizeof (A68G_LONG_REAL) = " A68G_LU, (UNSIGNED_T) size_mp ()) >= 0);
 467    WRITELN (A68G_STDOUT, A68G (output_line));
 468  #endif
 469    ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "sizeof (A68G_LONG_LONG_REAL) = " A68G_LU, (UNSIGNED_T) (UNSIGNED_T) SIZE_MP (LONG_LONG_MP_DIGITS)) >= 0);
 470    WRITELN (A68G_STDOUT, A68G (output_line));
 471    WRITELN (A68G_STDOUT, "");
 472    ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "sizeof (INT_T) = " A68G_LU, (UNSIGNED_T) sizeof (INT_T)) >= 0);
 473    WRITELN (A68G_STDOUT, A68G (output_line));
 474    ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "sizeof (UNSIGNED_T) = " A68G_LU, (UNSIGNED_T) sizeof (UNSIGNED_T)) >= 0);
 475    WRITELN (A68G_STDOUT, A68G (output_line));
 476    ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "sizeof (a68g_off_t) = " A68G_LU, (UNSIGNED_T) sizeof (a68g_off_t)) >= 0);
 477    WRITELN (A68G_STDOUT, A68G (output_line));
 478    ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "sizeof (size_t) = " A68G_LU, (UNSIGNED_T) sizeof (size_t)) >= 0);
 479    WRITELN (A68G_STDOUT, A68G (output_line));
 480    ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "sizeof (ssize_t) = " A68G_LU, (UNSIGNED_T) sizeof (ssize_t)) >= 0);
 481    WRITELN (A68G_STDOUT, A68G (output_line));
 482    ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "UPB size_t = " A68G_LU, (UNSIGNED_T) MAX_MEM_SIZE) >= 0);
 483    WRITELN (A68G_STDOUT, A68G (output_line));
 484    WRITELN (A68G_STDOUT, "");
 485    exit (EXIT_SUCCESS);
 486  }
 487  
 488  //! @brief Process options gathered in the option list.
 489  
 490  BOOL_T need_library (OPTION_LIST_T *i)
 491  {
 492    char *q = strip_sign (STR (i));
 493    if (eq (q, "compiler")) {
 494  #if defined (BUILD_A68G_COMPILER)
 495      return (A68G_TRUE);
 496  #else
 497      io_close_tty_line ();
 498      WRITE (A68G_STDERR, "plugin compiler required - exiting graciously");
 499      a68g_exit (EXIT_SUCCESS);
 500  #endif
 501    }
 502    if (eq (q, "curl")) {
 503  #if defined (HAVE_CURL)
 504      return (A68G_TRUE);
 505  #else
 506      io_close_tty_line ();
 507      WRITE (A68G_STDERR, "curl library required - exiting graciously");
 508      a68g_exit (EXIT_SUCCESS);
 509  #endif
 510    }
 511    if (eq (q, "curses")) {
 512  #if defined (HAVE_CURSES)
 513      return (A68G_TRUE);
 514  #else
 515      io_close_tty_line ();
 516      WRITE (A68G_STDERR, "curses required - exiting graciously");
 517      a68g_exit (EXIT_SUCCESS);
 518  #endif
 519    }
 520    if (eq (q, "gsl")) {
 521  #if defined (HAVE_GSL)
 522      return (A68G_TRUE);
 523  #else
 524      io_close_tty_line ();
 525      WRITE (A68G_STDERR, "GNU Scientific Library required - exiting graciously");
 526      a68g_exit (EXIT_SUCCESS);
 527  #endif
 528    }
 529    if (eq (q, "http")) {
 530  #if !defined (HAVE_CURL)
 531      io_close_tty_line ();
 532      WRITELN (A68G_STDERR, "curl required - exiting graciously");
 533      a68g_exit (EXIT_SUCCESS);
 534  #else
 535      return (A68G_TRUE);
 536  #endif
 537    }
 538    if (eq (q, "ieee")) {
 539  #if defined (HAVE_IEEE_754)
 540      return (A68G_TRUE);
 541  #else
 542      io_close_tty_line ();
 543      WRITE (A68G_STDERR, "IEEE required - exiting graciously");
 544      a68g_exit (EXIT_SUCCESS);
 545  #endif
 546    }
 547    if (eq (q, "linux")) {
 548  #if defined (BUILD_LINUX)
 549      return (A68G_TRUE);
 550  #else
 551      io_close_tty_line ();
 552      WRITE (A68G_STDERR, "linux required - exiting graciously");
 553      a68g_exit (EXIT_SUCCESS);
 554  #endif
 555    }
 556    if (eq (q, "mathlib")) {
 557  #if defined (HAVE_MATHLIB)
 558      return (A68G_TRUE);
 559  #else
 560      io_close_tty_line ();
 561      WRITE (A68G_STDERR, "R mathlib required - exiting graciously");
 562      a68g_exit (EXIT_SUCCESS);
 563  #endif
 564    }
 565    if (eq (q, "mpfr")) {
 566  #if defined (HAVE_GNU_MPFR)
 567      return (A68G_TRUE);
 568  #else
 569      io_close_tty_line ();
 570      WRITE (A68G_STDERR, "GNU MPFR required - exiting graciously");
 571      a68g_exit (EXIT_SUCCESS);
 572  #endif
 573    }
 574    if (eq (q, "plotutils")) {
 575  #if defined (HAVE_GNU_PLOTUTILS)
 576      return (A68G_TRUE);
 577  #else
 578      io_close_tty_line ();
 579      WRITE (A68G_STDERR, "GNU plotutils required - exiting graciously");
 580      a68g_exit (EXIT_SUCCESS);
 581  #endif
 582    }
 583    if (eq (q, "postgresql")) {
 584  #if defined (HAVE_POSTGRESQL)
 585      return (A68G_TRUE);
 586  #else
 587      io_close_tty_line ();
 588      WRITE (A68G_STDERR, "postgresql required - exiting graciously");
 589      a68g_exit (EXIT_SUCCESS);
 590  #endif
 591    }
 592    if (eq (q, "threads")) {
 593  #if defined (BUILD_PARALLEL_CLAUSE)
 594      return (A68G_TRUE);
 595  #else
 596      io_close_tty_line ();
 597      WRITE (A68G_STDERR, "POSIX threads required - exiting graciously");
 598      a68g_exit (EXIT_SUCCESS);
 599  #endif
 600    }
 601    return A68G_FALSE;
 602  }
 603  
 604  //! @brief Process options gathered in the option list.
 605  
 606  BOOL_T set_options (OPTION_LIST_T *i, BOOL_T cmd_line)
 607  {
 608    BOOL_T siga = A68G_TRUE, name_set = A68G_FALSE, skip = A68G_FALSE;
 609    OPTION_LIST_T *j = i;
 610    errno = 0;
 611    while (i != NO_OPTION_LIST && siga) {
 612  // Once SCRIPT is processed we skip options on the command line.
 613      if (cmd_line && skip) {
 614        FORWARD (i);
 615      } else {
 616        LINE_T *start_l = LINE (i);
 617        char *start_c = STR (i);
 618        size_t n = strlen (STR (i));
 619  // Allow for spaces ending in # to have A68 comment syntax with '#!'.
 620        while (n > 0 && (IS_SPACE ((STR (i))[n - 1]) || (STR (i))[n - 1] == '#')) {
 621          (STR (i))[--n] = NULL_CHAR;
 622        }
 623        if (!(PROCESSED (i))) {
 624  // Accept UNIX '-option [=] value'.
 625          BOOL_T minus_sign = (BOOL_T) ((STR (i))[0] == '-');
 626          char *p = strip_sign (STR (i));
 627          if (!minus_sign && eq (p, "#")) {
 628            ;
 629          } else if (!minus_sign && cmd_line) {
 630  // Item without '-'s is a filename.
 631            if (!name_set) {
 632              FILE_INITIAL_NAME (&A68G_JOB) = new_string (p, NO_TEXT);
 633              name_set = A68G_TRUE;
 634            } else {
 635              option_error (NO_LINE, start_c, ERROR_MULTIPLE_SOURCE_FILES);
 636            }
 637          } else if (eq (p, "INCLUDE")) {
 638  // Preprocessor items stop option processing.
 639            siga = A68G_FALSE;
 640          } else if (eq (p, "READ")) {
 641            siga = A68G_FALSE;
 642          } else if (eq (p, "PREPROCESSOR")) {
 643            siga = A68G_FALSE;
 644          } else if (eq (p, "NOPREPROCESSOR")) {
 645            siga = A68G_FALSE;
 646          } else if (eq (p, "TECHnicalities")) {
 647  // TECH prints out some tech stuff.
 648            tech_stuff ();
 649          }
 650  // EXIT stops option processing.
 651          else if (eq (p, "EXIT")) {
 652            siga = A68G_FALSE;
 653          }
 654  // Empty item (from specifying '-' or '--') stops option processing.
 655          else if (eq (p, "-") || eq (p, "--")) {
 656            siga = A68G_FALSE;
 657          }
 658  // FILE accepts its argument as filename.
 659          else if (eq (p, "File") && cmd_line) {
 660            FORWARD (i);
 661            if (i != NO_OPTION_LIST && strcmp (STR (i), "=") == 0) {
 662              FORWARD (i);
 663            }
 664            if (i != NO_OPTION_LIST) {
 665              if (!name_set) {
 666                FILE_INITIAL_NAME (&A68G_JOB) = new_string (STR (i), NO_TEXT);
 667                name_set = A68G_TRUE;
 668              } else {
 669                option_error (start_l, start_c, ERROR_MULTIPLE_SOURCE_FILES);
 670              }
 671            } else {
 672              option_error (start_l, start_c, ERROR_MISSING_STUFF);
 673            }
 674          }
 675  // NEED or LIBrary require the argument as environ.
 676          else if (eq (p, "NEED") || eq (p, "LIBrary")) {
 677            FORWARD (i);
 678            if (i == NO_OPTION_LIST) {
 679              option_error (start_l, start_c, ERROR_MISSING_STUFF);
 680            } else {
 681              OPTION_LIST_T *save = i; BOOL_T good = A68G_FALSE;
 682              do {
 683                good = need_library (i);
 684                if (good) {
 685                  save = i;
 686                  FORWARD (i);
 687                } else {
 688                  i = save;
 689                }
 690              } while (good && i != NO_OPTION_LIST);
 691            }
 692          }
 693  // SCRIPT takes next argument as filename.
 694  // Further options on the command line are not processed, but stored.
 695          else if (eq (p, "Script") && cmd_line) {
 696            FORWARD (i);
 697            if (i != NO_OPTION_LIST) {
 698              if (!name_set) {
 699                FILE_INITIAL_NAME (&A68G_JOB) = new_string (STR (i), NO_TEXT);
 700                name_set = A68G_TRUE;
 701              } else {
 702                option_error (start_l, start_c, ERROR_MULTIPLE_SOURCE_FILES);
 703              }
 704            } else {
 705              option_error (start_l, start_c, ERROR_MISSING_STUFF);
 706            }
 707            skip = A68G_TRUE;
 708          }
 709  // VERIFY checks that argument is current a68g version number.
 710          else if (eq (p, "VERIFY")) {
 711            FORWARD (i);
 712            if (i != NO_OPTION_LIST && strcmp (STR (i), "=") == 0) {
 713              FORWARD (i);
 714            }
 715            if (i != NO_OPTION_LIST) {
 716              ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "%s verification \"%s\" does not match script verification \"%s\"", A68G (a68g_cmd_name), PACKAGE_STRING, STR (i)) >= 0);
 717              ABEND (strcmp (PACKAGE_STRING, STR (i)) != 0, new_string (A68G (output_line), __func__), "outdated script");
 718            } else {
 719              option_error (start_l, start_c, ERROR_MISSING_STUFF);
 720            }
 721          }
 722  // HELP gives online help.
 723          else if ((eq (p, "APropos") || eq (p, "Help") || eq (p, "INfo")) && cmd_line) {
 724            FORWARD (i);
 725            if (i != NO_OPTION_LIST && strcmp (STR (i), "=") == 0) {
 726              FORWARD (i);
 727            }
 728            if (i != NO_OPTION_LIST) {
 729              apropos (A68G_STDOUT, NO_TEXT, STR (i));
 730            } else {
 731              apropos (A68G_STDOUT, NO_TEXT, "options");
 732            }
 733            a68g_exit (EXIT_SUCCESS);
 734          }
 735  // ECHO is treated later.
 736          else if (eq (p, "ECHO")) {
 737            if (strchr (p, '=') == NO_TEXT) {
 738              FORWARD (i);
 739              if (i != NO_OPTION_LIST) {
 740                if (strcmp (STR (i), "=") == 0) {
 741                  FORWARD (i);
 742                }
 743              }
 744            }
 745          }
 746  // EXECUTE and PRINT execute their argument as Algol 68 text.
 747          else if (eq (p, "Execute") || eq (p, "X") || eq (p, "Print")) {
 748            if (cmd_line == A68G_FALSE) {
 749              option_error (start_l, start_c, ERROR_COMMAND_LINE);
 750            } else if ((FORWARD (i)) != NO_OPTION_LIST) {
 751              BOOL_T error = A68G_FALSE;
 752              if (strcmp (STR (i), "=") == 0) {
 753                error = (BOOL_T) ((FORWARD (i)) == NO_OPTION_LIST);
 754              }
 755              if (!error) {
 756                BUFFER name, new_name;
 757                int s_errno = errno;
 758                a68g_bufcpy (name, HIDDEN_TEMP_FILE_NAME, BUFFER_SIZE);
 759                a68g_bufcat (name, ".a68", BUFFER_SIZE);
 760                FILE *f = a68g_fopen (name, "w", new_name);
 761                ABEND (f == NO_FILE, ERROR_ACTION, __func__);
 762                errno = s_errno;
 763                if (eq (p, "Execute") || eq (p, "X")) {
 764                  fprintf (f, "(%s)\n", STR (i));
 765                } else {
 766                  fprintf (f, "(print (((%s), new line)))\n", STR (i));
 767                }
 768                ASSERT (fclose (f) == 0);
 769                FILE_INITIAL_NAME (&A68G_JOB) = new_string (new_name, NO_TEXT);
 770              } else {
 771                option_error (start_l, start_c, ERROR_MISSING_STUFF);
 772              }
 773            } else {
 774              option_error (start_l, start_c, ERROR_MISSING_STUFF);
 775            }
 776          }
 777  // STORAGE, HEAP, HANDLES, STACK, FRAME and OVERHEAD set core allocation.
 778          else if (eq (p, "STOrage")) {
 779            BOOL_T error = A68G_FALSE;
 780            INT_T k = fetch_integral (p, &i, &error, MAX_MEM_SIZE);
 781  
 782  // Adjust size.
 783            if (error || errno > 0) {
 784              option_error (start_l, start_c, ERROR_MISSING_STUFF);
 785            } else if (k > 0) {
 786              default_mem_sizes (k, start_l, start_c);
 787            }
 788          } else if (eq (p, "HEAP") || eq (p, "HANDLES") || eq (p, "STACK") || eq (p, "FRAME") || eq (p, "OVERHEAD")) {
 789            BOOL_T error = A68G_FALSE;
 790            INT_T k = fetch_integral (p, &i, &error, MAX_MEM_SIZE);
 791  // Adjust size.
 792            if (error || errno > 0) {
 793              option_error (start_l, start_c, ERROR_INVALID_VALUE);
 794            } else if (k > 0) {
 795              if (k < A68G (storage_overhead)) {
 796                option_error (start_l, start_c, ERROR_INVALID_VALUE);
 797                k = A68G (storage_overhead);
 798              }
 799              storage_limit (k + A68G (storage_overhead));
 800              if (eq (p, "HEAP")) {
 801                A68G (heap_size) = k;
 802              } else if (eq (p, "HANDLES")) {
 803                A68G (handle_pool_size) = k;
 804              } else if (eq (p, "STACK")) {
 805                A68G (expr_stack_size) = k;
 806              } else if (eq (p, "FRAME")) {
 807                A68G (frame_stack_size) = k;
 808              } else if (eq (p, "OVERHEAD")) {
 809                A68G (storage_overhead) = k;
 810              }
 811            }
 812          }
 813  // COMPILE and NOCOMPILE switch on/off compilation.
 814          else if (eq (p, "Compile")) {
 815  #if defined (BUILD_LINUX) || defined (BUILD_BSD)
 816            OPTION_COMPILE (&A68G_JOB) = A68G_TRUE;
 817            OPTION_COMPILE_CHECK (&A68G_JOB) = A68G_TRUE;
 818            if (OPTION_OPT_LEVEL (&A68G_JOB) < OPTIMISE_1) {
 819              OPTION_OPT_LEVEL (&A68G_JOB) = OPTIMISE_1;
 820            }
 821            OPTION_RUN_SCRIPT (&A68G_JOB) = A68G_FALSE;
 822  #else
 823            option_error (start_l, start_c, ERROR_PLATFORM);
 824  #endif
 825          } else if (eq (p, "NOCompile") || eq (p, "NO-Compile")) {
 826            OPTION_COMPILE (&A68G_JOB) = A68G_FALSE;
 827            OPTION_RUN_SCRIPT (&A68G_JOB) = A68G_FALSE;
 828          }
 829  // OPTIMISE and NOOPTIMISE switch on/off optimisation.
 830          else if (eq (p, "NOOptimize") || eq (p, "NO-Optimize")) {
 831            OPTION_OPT_LEVEL (&A68G_JOB) = NO_OPTIMISE;
 832          } else if (eq (p, "O0")) {
 833            OPTION_OPT_LEVEL (&A68G_JOB) = NO_OPTIMISE;
 834          } else if (eq (p, "OG")) {
 835            OPTION_COMPILE_CHECK (&A68G_JOB) = A68G_TRUE;
 836            OPTION_OPT_LEVEL (&A68G_JOB) = OPTIMISE_0;
 837          } else if (eq (p, "OPTimise") || eq (p, "OPTimize")) {
 838            OPTION_COMPILE_CHECK (&A68G_JOB) = A68G_TRUE;
 839            OPTION_OPT_LEVEL (&A68G_JOB) = OPTIMISE_1;
 840          } else if (eq (p, "O") || eq (p, "O1")) {
 841            OPTION_COMPILE_CHECK (&A68G_JOB) = A68G_TRUE;
 842            OPTION_OPT_LEVEL (&A68G_JOB) = OPTIMISE_1;
 843          } else if (eq (p, "O2")) {
 844            OPTION_COMPILE_CHECK (&A68G_JOB) = A68G_FALSE;
 845            OPTION_OPT_LEVEL (&A68G_JOB) = OPTIMISE_2;
 846          } else if (eq (p, "O3")) {
 847            OPTION_COMPILE_CHECK (&A68G_JOB) = A68G_FALSE;
 848            OPTION_OPT_LEVEL (&A68G_JOB) = OPTIMISE_3;
 849          } else if (eq (p, "Ofast")) {
 850            OPTION_COMPILE_CHECK (&A68G_JOB) = A68G_FALSE;
 851            OPTION_OPT_LEVEL (&A68G_JOB) = OPTIMISE_FAST;
 852          }
 853  // ERROR-CHECK generates (some) runtime checks for O2, O3, Ofast.
 854          else if (eq (p, "ERRor-check")) {
 855            OPTION_COMPILE_CHECK (&A68G_JOB) = A68G_TRUE;
 856          }
 857  // RUN-SCRIPT runs a compiled .sh script.
 858          else if (eq (p, "RUN-SCRIPT")) {
 859  #if defined (BUILD_LINUX) || defined (BUILD_BSD)
 860            FORWARD (i);
 861            if (i != NO_OPTION_LIST) {
 862              if (!name_set) {
 863                FILE_INITIAL_NAME (&A68G_JOB) = new_string (STR (i), NO_TEXT);
 864                name_set = A68G_TRUE;
 865              } else {
 866                option_error (start_l, start_c, ERROR_MULTIPLE_SOURCE_FILES);
 867              }
 868            } else {
 869              option_error (start_l, start_c, ERROR_MISSING_STUFF);
 870            }
 871            skip = A68G_TRUE;
 872            OPTION_RUN_SCRIPT (&A68G_JOB) = A68G_TRUE;
 873            OPTION_NO_NOTICES (&A68G_JOB) = A68G_TRUE;
 874            OPTION_NO_WARNINGS (&A68G_JOB) = A68G_TRUE;
 875            OPTION_COMPILE (&A68G_JOB) = A68G_FALSE;
 876  #else
 877            option_error (start_l, start_c, ERROR_PLATFORM);
 878  #endif
 879          }
 880  // RUN-QUOTE-SCRIPT runs a compiled .sh script.
 881          else if (eq (p, "RUN-QUOTE-SCRIPT")) {
 882  #if defined (BUILD_LINUX) || defined (BUILD_BSD)
 883            FORWARD (i);
 884            if (i != NO_OPTION_LIST) {
 885              if (!name_set) {
 886                FILE_INITIAL_NAME (&A68G_JOB) = new_string (STR (i), NO_TEXT);
 887                name_set = A68G_TRUE;
 888              } else {
 889                option_error (start_l, start_c, ERROR_MULTIPLE_SOURCE_FILES);
 890              }
 891            } else {
 892              option_error (start_l, start_c, ERROR_MISSING_STUFF);
 893            }
 894            skip = A68G_TRUE;
 895            OPTION_RUN_SCRIPT (&A68G_JOB) = A68G_TRUE;
 896            OPTION_STROPPING (&A68G_JOB) = QUOTE_STROPPING;
 897            OPTION_COMPILE (&A68G_JOB) = A68G_FALSE;
 898  #else
 899            option_error (start_l, start_c, ERROR_PLATFORM);
 900  #endif
 901          }
 902  // RERUN re-uses an existing .so file.
 903          else if (eq (p, "RERUN")) {
 904            OPTION_COMPILE (&A68G_JOB) = A68G_FALSE;
 905            OPTION_RERUN (&A68G_JOB) = A68G_TRUE;
 906            if (OPTION_OPT_LEVEL (&A68G_JOB) < OPTIMISE_1) {
 907              OPTION_OPT_LEVEL (&A68G_JOB) = OPTIMISE_1;
 908            }
 909          }
 910  // KEEP and NOKEEP switch off/on object file deletion.
 911          else if (eq (p, "KEEP")) {
 912            OPTION_KEEP (&A68G_JOB) = A68G_TRUE;
 913          } else if (eq (p, "NOKEEP")) {
 914            OPTION_KEEP (&A68G_JOB) = A68G_FALSE;
 915          } else if (eq (p, "NO-KEEP")) {
 916            OPTION_KEEP (&A68G_JOB) = A68G_FALSE;
 917          }
 918  // BRACKETS extends Algol 68 syntax for brackets.
 919          else if (eq (p, "BRackets")) {
 920            OPTION_BRACKETS (&A68G_JOB) = A68G_TRUE;
 921          }
 922  // PRETTY and INDENT perform basic pretty printing.
 923  // This is meant for synthetic code.
 924          else if (eq (p, "PRETty-print")) {
 925            OPTION_PRETTY (&A68G_JOB) = A68G_TRUE;
 926            OPTION_CHECK_ONLY (&A68G_JOB) = A68G_TRUE;
 927          } else if (eq (p, "INDENT")) {
 928            OPTION_PRETTY (&A68G_JOB) = A68G_TRUE;
 929            OPTION_CHECK_ONLY (&A68G_JOB) = A68G_TRUE;
 930          }
 931  // FOLD performs constant folding in basic lay-out formatting..
 932          else if (eq (p, "FOLD")) {
 933            OPTION_INDENT (&A68G_JOB) = A68G_TRUE;
 934            OPTION_FOLD (&A68G_JOB) = A68G_TRUE;
 935            OPTION_CHECK_ONLY (&A68G_JOB) = A68G_TRUE;
 936          }
 937  // REDUCTIONS gives parser reductions.
 938          else if (eq (p, "REDuctions")) {
 939            OPTION_REDUCTIONS (&A68G_JOB) = A68G_TRUE;
 940          }
 941  // ALGOL60STROPPING sets stropping to quote stropping.
 942          else if (eq (p, "ALGOL60stropping")) {
 943            OPTION_STROPPING (&A68G_JOB) = QUOTE_STROPPING;
 944          } else if (eq (p, "ALGOL60-stropping")) {
 945            OPTION_STROPPING (&A68G_JOB) = QUOTE_STROPPING;
 946          }
 947  // QUOTESTROPPING sets stropping to quote stropping.
 948          else if (eq (p, "QUOTEstropping")) {
 949            OPTION_STROPPING (&A68G_JOB) = QUOTE_STROPPING;
 950          } else if (eq (p, "QUOTE-stropping")) {
 951            OPTION_STROPPING (&A68G_JOB) = QUOTE_STROPPING;
 952          }
 953  // UPPERSTROPPING sets stropping to upper stropping, which is nowadays the expected default.
 954          else if (eq (p, "UPPERstropping")) {
 955            OPTION_STROPPING (&A68G_JOB) = UPPER_STROPPING;
 956          } else if (eq (p, "UPPER-stropping")) {
 957            OPTION_STROPPING (&A68G_JOB) = UPPER_STROPPING;
 958          }
 959  // CHECK and NORUN just check for syntax.
 960          else if (eq (p, "CHeck") || eq (p, "NORun") || eq (p, "NO-Run")) {
 961            OPTION_CHECK_ONLY (&A68G_JOB) = A68G_TRUE;
 962          }
 963  // CLOCK times program execution.
 964          else if (eq (p, "CLock")) {
 965            OPTION_CLOCK (&A68G_JOB) = A68G_TRUE;
 966          }
 967  // RUN overrides NORUN.
 968          else if (eq (p, "RUN")) {
 969            OPTION_RUN (&A68G_JOB) = A68G_TRUE;
 970          }
 971  // MONITOR or DEBUG invokes the debugger at runtime errors.
 972          else if (eq (p, "MONitor") || eq (p, "DEBUG")) {
 973            OPTION_DEBUG (&A68G_JOB) = A68G_TRUE;
 974          }
 975  // REGRESSION is an option that sets preferences when running the test suite - undocumented option.
 976          else if (eq (p, "REGRession")) {
 977            OPTION_NO_NOTICES (&A68G_JOB) = A68G_FALSE;
 978            OPTION_NO_WARNINGS (&A68G_JOB) = A68G_FALSE;
 979            OPTION_PORTCHECK (&A68G_JOB) = A68G_TRUE;
 980            OPTION_REGRESSION_TEST (&A68G_JOB) = A68G_TRUE;
 981            OPTION_TIME_LIMIT (&A68G_JOB) = 300;
 982            OPTION_KEEP (&A68G_JOB) = A68G_TRUE;
 983            A68G (term_width) = MAX_TERM_WIDTH;
 984          }
 985  // LICense states the license
 986          else if (eq (p, "LICense")) {
 987            OPTION_LICENSE (&A68G_JOB) = A68G_TRUE;
 988          }
 989  // NONOTICES switches notices off.
 990          else if (eq (p, "NONotices")) {
 991            OPTION_NO_NOTICES (&A68G_JOB) = A68G_TRUE;
 992          } else if (eq (p, "NO-NOTICEs")) {
 993            OPTION_NO_NOTICES (&A68G_JOB) = A68G_TRUE;
 994          }
 995  // NOWARNINGS switches unsuppressible warnings off.
 996          else if (eq (p, "NOWarnings")) {
 997            OPTION_NO_WARNINGS (&A68G_JOB) = A68G_TRUE;
 998          } else if (eq (p, "NO-Warnings")) {
 999            OPTION_NO_WARNINGS (&A68G_JOB) = A68G_TRUE;
1000          }
1001  // QUIET switches all warnings and notices off.
1002          else if (eq (p, "Quiet")) {
1003            OPTION_QUIET (&A68G_JOB) = A68G_TRUE;
1004          }
1005  // WARNINGS switches warnings on.
1006          else if (eq (p, "Warnings")) {
1007            OPTION_NO_WARNINGS (&A68G_JOB) = A68G_FALSE;
1008          }
1009  // NOTICES switches notices on.
1010          else if (eq (p, "NOTices")) {
1011            OPTION_NO_NOTICES (&A68G_JOB) = A68G_FALSE;
1012          }
1013  // NOPORTCHECK switches portcheck off.
1014          else if (eq (p, "NOPORTcheck")) {
1015            OPTION_PORTCHECK (&A68G_JOB) = A68G_FALSE;
1016          } else if (eq (p, "NO-PORTcheck")) {
1017            OPTION_PORTCHECK (&A68G_JOB) = A68G_FALSE;
1018          }
1019  // PORTCHECK switches portcheck on.
1020          else if (eq (p, "PORTcheck")) {
1021            OPTION_PORTCHECK (&A68G_JOB) = A68G_TRUE;
1022          }
1023  // PEDANTIC switches portcheck and warnings on.
1024          else if (eq (p, "PEDANTIC")) {
1025            OPTION_PORTCHECK (&A68G_JOB) = A68G_TRUE;
1026            OPTION_NO_NOTICES (&A68G_JOB) = A68G_FALSE;
1027            OPTION_NO_WARNINGS (&A68G_JOB) = A68G_FALSE;
1028          }
1029  // PRAGMATS and NOPRAGMATS switch on/off pragmat processing.
1030          else if (eq (p, "PRagmats")) {
1031            OPTION_PRAGMAT_SEMA (&A68G_JOB) = A68G_TRUE;
1032          } else if (eq (p, "NOPRagmats")) {
1033            OPTION_PRAGMAT_SEMA (&A68G_JOB) = A68G_FALSE;
1034          } else if (eq (p, "NO-PRagmats")) {
1035            OPTION_PRAGMAT_SEMA (&A68G_JOB) = A68G_FALSE;
1036          }
1037  // STRICT ignores A68G extensions to A68 syntax.
1038          else if (eq (p, "STRict")) {
1039            OPTION_STRICT (&A68G_JOB) = A68G_TRUE;
1040            OPTION_PORTCHECK (&A68G_JOB) = A68G_TRUE;
1041          }
1042  // VERBOSE in case you want to know what Algol68G is doing.
1043          else if (eq (p, "VERBose")) {
1044            OPTION_VERBOSE (&A68G_JOB) = A68G_TRUE;
1045          }
1046  // VERSION lists the current version at an appropriate time in the future.
1047          else if (eq (p, "Version")) {
1048            OPTION_VERSION (&A68G_JOB) = A68G_TRUE;
1049          } else if (eq (p, "MODular-arithmetic")) {
1050  // MODULAR-ARITHMETIC makes A68G permissive towards BITS values corresponding
1051  // to negative INT values. RR forbids these BITS values.
1052            OPTION_NODEMASK (&A68G_JOB) |= MODULAR_MASK;
1053          } else if (eq (p, "NOMODular-arithmetic")) {
1054            OPTION_NODEMASK (&A68G_JOB) &= ~MODULAR_MASK;
1055          } else if (eq (p, "NO-MODular-arithmetic")) {
1056            OPTION_NODEMASK (&A68G_JOB) &= ~MODULAR_MASK;
1057          }
1058  // XREF and NOXREF switch on/off a cross reference.
1059          else if (eq (p, "XREF")) {
1060            OPTION_SOURCE_LISTING (&A68G_JOB) = A68G_TRUE;
1061            OPTION_CROSS_REFERENCE (&A68G_JOB) = A68G_TRUE;
1062            OPTION_NODEMASK (&A68G_JOB) |= (CROSS_REFERENCE_MASK | SOURCE_MASK);
1063          } else if (eq (p, "NOXREF")) {
1064            OPTION_NODEMASK (&A68G_JOB) &= ~(CROSS_REFERENCE_MASK | SOURCE_MASK);
1065          } else if (eq (p, "NO-Xref")) {
1066            OPTION_NODEMASK (&A68G_JOB) &= ~(CROSS_REFERENCE_MASK | SOURCE_MASK);
1067          }
1068  // PRELUDELISTING cross references preludes, if they ever get implemented ...
1069          else if (eq (p, "PRELUDElisting") || eq (p, "PRELUDE-listing")) {
1070            OPTION_SOURCE_LISTING (&A68G_JOB) = A68G_TRUE;
1071            OPTION_CROSS_REFERENCE (&A68G_JOB) = A68G_TRUE;
1072            OPTION_STATISTICS_LISTING (&A68G_JOB) = A68G_TRUE;
1073            OPTION_NODEMASK (&A68G_JOB) |= (SOURCE_MASK | CROSS_REFERENCE_MASK);
1074            OPTION_STANDARD_PRELUDE_LISTING (&A68G_JOB) = A68G_TRUE;
1075          }
1076  // STATISTICS prints process statistics.
1077          else if (eq (p, "STatistics")) {
1078            OPTION_STATISTICS_LISTING (&A68G_JOB) = A68G_TRUE;
1079          }
1080  // TREE and NOTREE switch on/off printing of the syntax tree. This gets bulky!.
1081          else if (eq (p, "TREE")) {
1082            OPTION_SOURCE_LISTING (&A68G_JOB) = A68G_TRUE;
1083            OPTION_TREE_LISTING (&A68G_JOB) = A68G_TRUE;
1084            OPTION_NODEMASK (&A68G_JOB) |= (TREE_MASK | SOURCE_MASK);
1085          } else if (eq (p, "NOTREE")) {
1086            OPTION_NODEMASK (&A68G_JOB) ^= (TREE_MASK | SOURCE_MASK);
1087          } else if (eq (p, "NO-TREE")) {
1088            OPTION_NODEMASK (&A68G_JOB) ^= (TREE_MASK | SOURCE_MASK);
1089          }
1090  // UNUSED indicates unused tags.
1091          else if (eq (p, "UNUSED")) {
1092            OPTION_UNUSED (&A68G_JOB) = A68G_TRUE;
1093          }
1094  // EXTENSIVE set of options for an extensive listing.
1095          else if (eq (p, "EXTensive")) {
1096            OPTION_SOURCE_LISTING (&A68G_JOB) = A68G_TRUE;
1097            OPTION_OBJECT_LISTING (&A68G_JOB) = A68G_TRUE;
1098            OPTION_TREE_LISTING (&A68G_JOB) = A68G_TRUE;
1099            OPTION_CROSS_REFERENCE (&A68G_JOB) = A68G_TRUE;
1100            OPTION_MOID_LISTING (&A68G_JOB) = A68G_TRUE;
1101            OPTION_STANDARD_PRELUDE_LISTING (&A68G_JOB) = A68G_TRUE;
1102            OPTION_STATISTICS_LISTING (&A68G_JOB) = A68G_TRUE;
1103            OPTION_UNUSED (&A68G_JOB) = A68G_TRUE;
1104            OPTION_NODEMASK (&A68G_JOB) |= (CROSS_REFERENCE_MASK | TREE_MASK | CODE_MASK | SOURCE_MASK);
1105          }
1106  // LISTING set of options for a default listing.
1107          else if (eq (p, "Listing")) {
1108            OPTION_SOURCE_LISTING (&A68G_JOB) = A68G_TRUE;
1109            OPTION_CROSS_REFERENCE (&A68G_JOB) = A68G_TRUE;
1110            OPTION_STATISTICS_LISTING (&A68G_JOB) = A68G_TRUE;
1111            OPTION_NODEMASK (&A68G_JOB) |= (SOURCE_MASK | CROSS_REFERENCE_MASK);
1112          }
1113  // TTY send listing to standout. Remnant from my mainframe past.
1114          else if (eq (p, "TTY")) {
1115            OPTION_CROSS_REFERENCE (&A68G_JOB) = A68G_TRUE;
1116            OPTION_STATISTICS_LISTING (&A68G_JOB) = A68G_TRUE;
1117            OPTION_NODEMASK (&A68G_JOB) |= (SOURCE_MASK | CROSS_REFERENCE_MASK);
1118          }
1119  // SOURCE and NOSOURCE print source lines.
1120          else if (eq (p, "SOURCE")) {
1121            OPTION_SOURCE_LISTING (&A68G_JOB) = A68G_TRUE;
1122            OPTION_NODEMASK (&A68G_JOB) |= SOURCE_MASK;
1123          } else if (eq (p, "NOSOURCE")) {
1124            OPTION_NODEMASK (&A68G_JOB) &= ~SOURCE_MASK;
1125          } else if (eq (p, "NO-SOURCE")) {
1126            OPTION_NODEMASK (&A68G_JOB) &= ~SOURCE_MASK;
1127          }
1128  // OBJECT and NOOBJECT print object lines.
1129          else if (eq (p, "OBJECT")) {
1130            OPTION_OBJECT_LISTING (&A68G_JOB) = A68G_TRUE;
1131          } else if (eq (p, "NOOBJECT")) {
1132            OPTION_OBJECT_LISTING (&A68G_JOB) = A68G_FALSE;
1133          } else if (eq (p, "NO-OBJECT")) {
1134            OPTION_OBJECT_LISTING (&A68G_JOB) = A68G_FALSE;
1135          }
1136  // MOIDS prints an overview of moids used in the program.
1137          else if (eq (p, "MOIDS")) {
1138            OPTION_MOID_LISTING (&A68G_JOB) = A68G_TRUE;
1139          }
1140  // ASSERTIONS and NOASSERTIONS switch on/off the processing of assertions.
1141          else if (eq (p, "Assertions")) {
1142            OPTION_NODEMASK (&A68G_JOB) |= ASSERT_MASK;
1143          } else if (eq (p, "NOAssertions")) {
1144            OPTION_NODEMASK (&A68G_JOB) &= ~ASSERT_MASK;
1145          } else if (eq (p, "NO-Assertions")) {
1146            OPTION_NODEMASK (&A68G_JOB) &= ~ASSERT_MASK;
1147          }
1148  // PRECISION sets the LONG LONG precision.
1149          else if (eq (p, "PRECision")) {
1150            BOOL_T error = A68G_FALSE;
1151            INT_T N = fetch_integral (p, &i, &error, A68G_MAX_INT);
1152            int k = width_to_mp_digits (N);
1153            if (k <= 0 || error || errno > 0) {
1154              option_error (start_l, start_c, ERROR_INVALID_VALUE);
1155            } else if (long_mp_digits () > 0 && long_mp_digits () != k) {
1156              option_error (start_l, start_c, ERROR_PRECISION_SET);
1157            } else if (k > mp_digits ()) {
1158              set_long_mp_digits (k);
1159            } else {
1160              option_error (start_l, start_c, ERROR_PRECISION_TOO_LOW);
1161            }
1162          }
1163  // BACKTRACE and NOBACKTRACE switch on/off stack backtracing.
1164          else if (eq (p, "BACKtrace")) {
1165            OPTION_BACKTRACE (&A68G_JOB) = A68G_TRUE;
1166          } else if (eq (p, "NOBACKtrace")) {
1167            OPTION_BACKTRACE (&A68G_JOB) = A68G_FALSE;
1168          } else if (eq (p, "NO-BACKtrace")) {
1169            OPTION_BACKTRACE (&A68G_JOB) = A68G_FALSE;
1170          }
1171  // BREAK and NOBREAK switch on/off tracing of the running program.
1172          else if (eq (p, "BReakpoint")) {
1173            OPTION_NODEMASK (&A68G_JOB) |= BREAKPOINT_MASK;
1174          } else if (eq (p, "NOBReakpoint")) {
1175            OPTION_NODEMASK (&A68G_JOB) &= ~BREAKPOINT_MASK;
1176          } else if (eq (p, "NO-BReakpoint")) {
1177            OPTION_NODEMASK (&A68G_JOB) &= ~BREAKPOINT_MASK;
1178          }
1179  // TRACE and NOTRACE switch on/off tracing of the running program.
1180          else if (eq (p, "TRace")) {
1181            OPTION_TRACE (&A68G_JOB) = A68G_TRUE;
1182            OPTION_NODEMASK (&A68G_JOB) |= BREAKPOINT_TRACE_MASK;
1183          } else if (eq (p, "NOTRace")) {
1184            OPTION_NODEMASK (&A68G_JOB) &= ~BREAKPOINT_TRACE_MASK;
1185          } else if (eq (p, "NO-TRace")) {
1186            OPTION_NODEMASK (&A68G_JOB) &= ~BREAKPOINT_TRACE_MASK;
1187          }
1188  // TIMELIMIT lets the interpreter stop after so-many seconds.
1189          else if (eq (p, "TImelimit") || eq (p, "TIME-Limit")) {
1190            BOOL_T error = A68G_FALSE;
1191            INT_T k = fetch_integral (p, &i, &error, A68G_MAX_INT);
1192            if (error || errno > 0) {
1193              option_error (start_l, start_c, ERROR_INVALID_VALUE);
1194            } else if (k < 1) {
1195              option_error (start_l, start_c, ERROR_INVALID_VALUE);
1196            } else {
1197              OPTION_TIME_LIMIT (&A68G_JOB) = k;
1198            }
1199          }
1200  // Next undocumented option is for a68g development purposes.
1201          else if (eq (p, "SAFEGC") || eq (p, "SAFE-GC")) {
1202            OPTION_CONSERVATIVE_GC (&A68G_JOB) = A68G_GC_SAFE;
1203          } else if (eq (p, "NOGC") || eq (p, "NO-GC")) {
1204            OPTION_CONSERVATIVE_GC (&A68G_JOB) = A68G_GC_HALT;
1205          } else {
1206  // Unrecognised.
1207            option_error (start_l, start_c, ERROR_UNRECOGNISED_OPTION);
1208          }
1209        }
1210  // Go processing next item, if present.
1211        if (i != NO_OPTION_LIST) {
1212          FORWARD (i);
1213        }
1214      }
1215    }
1216  // Mark options as processed.
1217    for (; j != NO_OPTION_LIST; FORWARD (j)) {
1218      PROCESSED (j) = A68G_TRUE;
1219    }
1220    return (BOOL_T) (errno == 0);
1221  }
     


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