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