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