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