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