1 /* ------------------------------------------------------------------------- */
2 /* "directs" : Directives (# commands) */
4 /* Copyright (c) Graham Nelson 1993 - 2020 */
6 /* This file is part of Inform. */
8 /* Inform is free software: you can redistribute it and/or modify */
9 /* it under the terms of the GNU General Public License as published by */
10 /* the Free Software Foundation, either version 3 of the License, or */
11 /* (at your option) any later version. */
13 /* Inform is distributed in the hope that it will be useful, */
14 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
15 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
16 /* GNU General Public License for more details. */
18 /* You should have received a copy of the GNU General Public License */
19 /* along with Inform. If not, see https://gnu.org/licenses/ */
21 /* ------------------------------------------------------------------------- */
25 int no_routines, /* Number of routines compiled so far */
26 no_named_routines, /* Number not embedded in objects */
27 no_locals, /* Number of locals in current routine */
28 no_termcs; /* Number of terminating characters */
29 int terminating_characters[32];
31 brief_location routine_starts_line; /* Source code location where the current
32 routine starts. (Useful for reporting
33 "unused variable" warnings on the start
34 line rather than the end line.) */
36 static int constant_made_yet; /* Have any constants been defined yet? */
38 static int ifdef_stack[32], ifdef_sp;
40 /* ------------------------------------------------------------------------- */
42 static int ebf_error_recover(char *s1, char *s2)
44 /* Display an "expected... but found..." error, then skim forward
45 to the next semicolon and return FALSE. This is such a common
46 case in parse_given_directive() that it's worth a utility
47 function. You will see many error paths that look like:
48 return ebf_error_recover(...);
51 panic_mode_error_recovery();
55 /* ------------------------------------------------------------------------- */
57 extern int parse_given_directive(int internal_flag)
58 { /* Internal_flag is FALSE if the directive is encountered normally,
59 TRUE if encountered with a # prefix inside a routine or object
62 Returns: FALSE if program continues, TRUE if end of file reached. */
64 int *trace_level = NULL; int32 i, j, k, n, flag;
65 const char *constant_name;
66 debug_location_beginning beginning_debug_location;
71 /* --------------------------------------------------------------------- */
72 /* Abbreviate "string1" ["string2" ...] */
73 /* --------------------------------------------------------------------- */
79 if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
82 /* Z-code has a 64-abbrev limit; Glulx doesn't. */
83 if (!glulx_mode && no_abbreviations==64)
84 { error("All 64 abbreviations already declared");
85 panic_mode_error_recovery(); return FALSE;
87 if (no_abbreviations==MAX_ABBREVS)
88 memoryerror("MAX_ABBREVS", MAX_ABBREVS);
90 if (abbrevs_lookup_table_made)
91 { error("All abbreviations must be declared together");
92 panic_mode_error_recovery(); return FALSE;
94 if (token_type != DQ_TT)
95 return ebf_error_recover("abbreviation string", token_text);
96 if (strlen(token_text)<2)
97 { error_named("It's not worth abbreviating", token_text);
100 /* Abbreviation string with null must fit in a MAX_ABBREV_LENGTH
102 if (strlen(token_text)>=MAX_ABBREV_LENGTH)
103 { error_named("Abbreviation too long", token_text);
106 make_abbreviation(token_text);
109 /* --------------------------------------------------------------------- */
110 /* Array arrayname array... */
111 /* --------------------------------------------------------------------- */
113 case ARRAY_CODE: make_global(TRUE, FALSE); break; /* See "tables.c" */
115 /* --------------------------------------------------------------------- */
116 /* Attribute newname [alias oldname] */
117 /* --------------------------------------------------------------------- */
120 make_attribute(); break; /* See "objects.c" */
122 /* --------------------------------------------------------------------- */
123 /* Class classname ... */
124 /* --------------------------------------------------------------------- */
128 { error("Cannot nest #Class inside a routine or object");
129 panic_mode_error_recovery(); return FALSE;
131 make_class(NULL); /* See "objects.c" */
134 /* --------------------------------------------------------------------- */
135 /* Constant newname [[=] value] [, ...] */
136 /* --------------------------------------------------------------------- */
139 constant_made_yet=TRUE;
142 get_next_token(); i = token_value;
143 beginning_debug_location = get_token_location_beginning();
145 if ((token_type != SYMBOL_TT)
146 || (!(sflags[i] & (UNKNOWN_SFLAG + REDEFINABLE_SFLAG))))
147 { discard_token_location(beginning_debug_location);
148 return ebf_error_recover("new constant name", token_text);
151 assign_symbol(i, 0, CONSTANT_T);
152 constant_name = token_text;
156 if ((token_type == SEP_TT) && (token_value == COMMA_SEP))
157 { if (debugfile_switch && !(sflags[i] & REDEFINABLE_SFLAG))
158 { debug_file_printf("<constant>");
159 debug_file_printf("<identifier>%s</identifier>", constant_name);
160 write_debug_symbol_optional_backpatch(i);
161 write_debug_locations(get_token_location_end(beginning_debug_location));
162 debug_file_printf("</constant>");
164 goto ParseConstantSpec;
167 if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
168 { if (debugfile_switch && !(sflags[i] & REDEFINABLE_SFLAG))
169 { debug_file_printf("<constant>");
170 debug_file_printf("<identifier>%s</identifier>", constant_name);
171 write_debug_symbol_optional_backpatch(i);
172 write_debug_locations(get_token_location_end(beginning_debug_location));
173 debug_file_printf("</constant>");
178 if (!((token_type == SEP_TT) && (token_value == SETEQUALS_SEP)))
181 { assembly_operand AO = parse_expression(CONSTANT_CONTEXT);
183 { assign_marked_symbol(i, AO.marker, AO.value,
185 sflags[i] |= CHANGE_SFLAG;
186 if (i == grammar_version_symbol)
188 "Grammar__Version must be given an explicit constant value");
191 { assign_symbol(i, AO.value, CONSTANT_T);
192 if (i == grammar_version_symbol)
193 { if ((grammar_version_number != AO.value)
194 && (no_fake_actions > 0))
196 "Once a fake action has been defined it is too late to \
197 change the grammar version. (If you are using the library, move any \
198 Fake_Action directives to a point after the inclusion of \"Parser\".)");
199 grammar_version_number = AO.value;
204 if (debugfile_switch && !(sflags[i] & REDEFINABLE_SFLAG))
205 { debug_file_printf("<constant>");
206 debug_file_printf("<identifier>%s</identifier>", constant_name);
207 write_debug_symbol_optional_backpatch(i);
208 write_debug_locations
209 (get_token_location_end(beginning_debug_location));
210 debug_file_printf("</constant>");
214 if ((token_type == SEP_TT) && (token_value == COMMA_SEP))
215 goto ParseConstantSpec;
219 /* --------------------------------------------------------------------- */
220 /* Default constantname integer */
221 /* --------------------------------------------------------------------- */
225 { error("'Default' cannot be used in -M (Module) mode");
226 panic_mode_error_recovery(); return FALSE;
230 if (token_type != SYMBOL_TT)
231 return ebf_error_recover("name", token_text);
234 if (sflags[token_value] & UNKNOWN_SFLAG)
236 sflags[i] |= DEFCON_SFLAG;
240 if (!((token_type == SEP_TT) && (token_value == SETEQUALS_SEP)))
243 { assembly_operand AO;
244 AO = parse_expression(CONSTANT_CONTEXT);
246 { if (AO.marker != 0)
247 { assign_marked_symbol(i, AO.marker, AO.value,
249 sflags[i] |= CHANGE_SFLAG;
251 else assign_symbol(i, AO.value, CONSTANT_T);
257 /* --------------------------------------------------------------------- */
258 /* Dictionary 'word' */
259 /* Dictionary 'word' val1 */
260 /* Dictionary 'word' val1 val3 */
261 /* --------------------------------------------------------------------- */
263 case DICTIONARY_CODE:
264 /* In Inform 5, this directive had the form
265 Dictionary SYMBOL "word";
266 This was deprecated as of I6 (if not earlier), and is no longer
267 supported at all. The current form just creates a dictionary word,
268 with the given values for dict_par1 and dict_par3. If the word
269 already exists, the values are bit-or'd in with the existing
271 (We don't offer a way to set dict_par2, because that is entirely
272 reserved for the verb number. Or'ing values into it would create
276 if (token_type != SQ_TT && token_type != DQ_TT)
277 return ebf_error_recover("dictionary word", token_text);
280 char *wd = token_text;
285 if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) {
291 AO = parse_expression(CONSTANT_CONTEXT);
292 if (module_switch && (AO.marker != 0))
293 error("A definite value must be given as a Dictionary flag");
298 if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) {
304 AO = parse_expression(CONSTANT_CONTEXT);
305 if (module_switch && (AO.marker != 0))
306 error("A definite value must be given as a Dictionary flag");
313 if ((val1 & ~0xFF) || (val3 & ~0xFF)) {
314 warning("Dictionary flag values cannot exceed $FF in Z-code");
318 if ((val1 & ~0xFFFF) || (val3 & ~0xFFFF)) {
319 warning("Dictionary flag values cannot exceed $FFFF in Glulx");
323 dictionary_add(wd, val1, 0, val3);
327 /* --------------------------------------------------------------------- */
329 /* --------------------------------------------------------------------- */
331 case END_CODE: return(TRUE);
334 if (ifdef_sp == 0) error("'Endif' without matching 'If...'");
338 /* --------------------------------------------------------------------- */
340 /* --------------------------------------------------------------------- */
342 case EXTEND_CODE: extend_verb(); return FALSE; /* see "tables.c" */
344 /* --------------------------------------------------------------------- */
345 /* Fake_Action name */
346 /* --------------------------------------------------------------------- */
348 case FAKE_ACTION_CODE:
349 make_fake_action(); break; /* see "verbs.c" */
351 /* --------------------------------------------------------------------- */
352 /* Global variable [= value / array...] */
353 /* --------------------------------------------------------------------- */
355 case GLOBAL_CODE: make_global(FALSE, FALSE); break; /* See "tables.c" */
357 /* --------------------------------------------------------------------- */
360 /* Note that each time Inform tests an If... condition, it stacks the */
361 /* result (TRUE or FALSE) on ifdef_stack: thus, the top of this stack */
362 /* reveals what clause of the current If... is being compiled: */
364 /* If...; ... Ifnot; ... Endif; */
365 /* top of stack: TRUE FALSE */
367 /* This is used to detect "two Ifnots in same If" errors. */
368 /* --------------------------------------------------------------------- */
378 if (token_type != SYMBOL_TT)
379 return ebf_error_recover("symbol name", token_text);
381 if ((token_text[0] == 'V')
382 && (token_text[1] == 'N')
383 && (token_text[2] == '_')
384 && (strlen(token_text)==7))
385 { i = atoi(token_text+3);
386 if (VNUMBER < i) flag = (flag)?FALSE:TRUE;
387 goto HashIfCondition;
390 if (sflags[token_value] & UNKNOWN_SFLAG) flag = (flag)?FALSE:TRUE;
391 else sflags[token_value] |= USED_SFLAG;
392 goto HashIfCondition;
396 error("'Ifnot' without matching 'If...'");
398 if (!(ifdef_stack[ifdef_sp-1]))
399 error("Second 'Ifnot' for the same 'If...' condition");
401 { dont_enter_into_symbol_table = -2; n = 1;
402 directives.enabled = TRUE;
405 if (token_type == EOF_TT)
406 { error("End of file reached in code 'If...'d out");
407 directives.enabled = FALSE;
410 if (token_type == DIRECTIVE_TT)
411 { switch(token_value)
424 "Second 'Ifnot' for the same 'If...' condition");
431 dont_enter_into_symbol_table = FALSE;
432 directives.enabled = FALSE;
438 if (!glulx_mode && version_number <= 3) flag = TRUE;
439 goto HashIfCondition;
443 if (!glulx_mode && version_number <= 3) flag = FALSE;
444 goto HashIfCondition;
447 { assembly_operand AO;
448 AO = parse_expression(CONSTANT_CONTEXT);
449 if (module_switch && (AO.marker != 0))
450 { error("This condition can't be determined");
453 else flag = (AO.value != 0);
455 goto HashIfCondition;
458 { assembly_operand AO;
459 AO = parse_expression(CONSTANT_CONTEXT);
460 if (module_switch && (AO.marker != 0))
461 { error("This condition can't be determined");
464 else flag = (AO.value == 0);
466 goto HashIfCondition;
470 if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)))
471 return ebf_error_recover("semicolon after 'If...' condition", token_text);
474 { ifdef_stack[ifdef_sp++] = TRUE; return FALSE; }
476 { dont_enter_into_symbol_table = -2; n = 1;
477 directives.enabled = TRUE;
480 if (token_type == EOF_TT)
481 { error("End of file reached in code 'If...'d out");
482 directives.enabled = FALSE;
485 if (token_type == DIRECTIVE_TT)
499 { ifdef_stack[ifdef_sp++] = FALSE;
505 directives.enabled = FALSE;
506 dont_enter_into_symbol_table = FALSE;
510 /* --------------------------------------------------------------------- */
511 /* Import global <varname> [, ...] */
513 /* (Further imported goods may be allowed later.) */
514 /* --------------------------------------------------------------------- */
518 { error("'Import' can only be used in -M (Module) mode");
519 panic_mode_error_recovery(); return FALSE;
521 directives.enabled = TRUE;
524 if ((token_type == DIRECTIVE_TT) && (token_value == GLOBAL_CODE))
525 make_global(FALSE, TRUE);
526 else error_named("'Import' cannot import things of this type:",
529 } while ((token_type == SEP_TT) && (token_value == COMMA_SEP));
531 directives.enabled = FALSE;
534 /* --------------------------------------------------------------------- */
535 /* Include "[>]filename" */
537 /* The ">" character means to load the file from the same directory as */
538 /* the current file, instead of relying on the include path. */
539 /* --------------------------------------------------------------------- */
543 if (token_type != DQ_TT)
544 return ebf_error_recover("filename in double-quotes", token_text);
546 { char *name = token_text;
549 if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)))
550 ebf_error("semicolon ';' after Include filename", token_text);
552 if (strcmp(name, "language__") == 0)
553 load_sourcefile(Language_Name, 0);
554 else if (name[0] == '>')
555 load_sourcefile(name+1, 1);
556 else load_sourcefile(name, 0);
560 /* --------------------------------------------------------------------- */
561 /* Link "filename" */
562 /* --------------------------------------------------------------------- */
566 if (token_type != DQ_TT)
567 return ebf_error_recover("filename in double-quotes", token_text);
568 link_module(token_text); /* See "linker.c" */
571 /* --------------------------------------------------------------------- */
572 /* Lowstring constantname "text of string" */
573 /* --------------------------------------------------------------------- */
574 /* Unlike most constant creations, these do not require backpatching: */
575 /* the low strings always occupy a table at a fixed offset in the */
576 /* Z-machine (after the abbreviations table has finished, at 0x100). */
577 /* --------------------------------------------------------------------- */
581 { error("'LowString' cannot be used in -M (Module) mode");
582 panic_mode_error_recovery(); return FALSE;
584 get_next_token(); i = token_value;
585 if ((token_type != SYMBOL_TT) || (!(sflags[i] & UNKNOWN_SFLAG)))
586 return ebf_error_recover("new low string name", token_text);
589 if (token_type != DQ_TT)
590 return ebf_error_recover("literal string in double-quotes", token_text);
592 assign_symbol(i, compile_string(token_text, TRUE, TRUE), CONSTANT_T);
595 /* --------------------------------------------------------------------- */
596 /* Message | "information" */
597 /* | error "error message" */
598 /* | fatalerror "fatal error message" */
599 /* | warning "warning message" */
600 /* --------------------------------------------------------------------- */
603 directive_keywords.enabled = TRUE;
605 directive_keywords.enabled = FALSE;
606 if (token_type == DQ_TT)
608 if (hash_printed_since_newline) printf("\n");
609 for (i=0; token_text[i]!=0; i++)
610 { if (token_text[i] == '^') printf("\n");
612 if (token_text[i] == '~') printf("\"");
613 else printf("%c", token_text[i]);
618 if ((token_type == DIR_KEYWORD_TT) && (token_value == ERROR_DK))
620 if (token_type != DQ_TT)
621 { return ebf_error_recover("error message in double-quotes", token_text);
623 error(token_text); break;
625 if ((token_type == DIR_KEYWORD_TT) && (token_value == FATALERROR_DK))
627 if (token_type != DQ_TT)
628 { return ebf_error_recover("fatal error message in double-quotes", token_text);
630 fatalerror(token_text); break;
632 if ((token_type == DIR_KEYWORD_TT) && (token_value == WARNING_DK))
634 if (token_type != DQ_TT)
635 { return ebf_error_recover("warning message in double-quotes", token_text);
637 warning(token_text); break;
639 return ebf_error_recover("a message in double-quotes, 'error', 'fatalerror' or 'warning'",
643 /* --------------------------------------------------------------------- */
644 /* Nearby objname "short name" ... */
645 /* --------------------------------------------------------------------- */
649 { error("Cannot nest #Nearby inside a routine or object");
650 panic_mode_error_recovery(); return FALSE;
652 make_object(TRUE, NULL, -1, -1, -1);
653 return FALSE; /* See "objects.c" */
655 /* --------------------------------------------------------------------- */
656 /* Object objname "short name" ... */
657 /* --------------------------------------------------------------------- */
661 { error("Cannot nest #Object inside a routine or object");
662 panic_mode_error_recovery(); return FALSE;
664 make_object(FALSE, NULL, -1, -1, -1);
665 return FALSE; /* See "objects.c" */
667 /* --------------------------------------------------------------------- */
668 /* Origsource <file> */
669 /* Origsource <file> <line> */
670 /* Origsource <file> <line> <char> */
673 /* The first three forms declare that all following lines are derived */
674 /* from the named Inform 7 source file (with an optional line number */
675 /* and character number). This will be reported in error messages and */
676 /* in debug output. The declaration holds through the next Origsource */
677 /* directive (but does not apply to included files). */
679 /* The fourth form, with no arguments, clears the declaration. */
681 /* Unlike the Include directive, Origsource does not open the named */
682 /* file or even verify that it exists. The filename is treated as an */
684 /* --------------------------------------------------------------------- */
686 case ORIGSOURCE_CODE:
688 char *origsource_file = NULL;
689 int32 origsource_line = 0;
690 int32 origsource_char = 0;
692 /* Parse some optional tokens followed by a mandatory semicolon. */
695 if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))) {
696 if (token_type != DQ_TT) {
697 return ebf_error_recover("a file name in double-quotes",
700 origsource_file = token_text;
703 if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))) {
704 if (token_type != NUMBER_TT) {
705 return ebf_error_recover("a file line number",
708 origsource_line = token_value;
709 if (origsource_line < 0)
713 if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))) {
714 if (token_type != NUMBER_TT) {
715 return ebf_error_recover("a file line number",
718 origsource_char = token_value;
719 if (origsource_char < 0)
729 set_origsource_location(origsource_file, origsource_line, origsource_char);
733 /* --------------------------------------------------------------------- */
734 /* Property [long] [additive] name [alias oldname] */
735 /* --------------------------------------------------------------------- */
737 case PROPERTY_CODE: make_property(); break; /* See "objects.c" */
739 /* --------------------------------------------------------------------- */
740 /* Release <number> */
741 /* --------------------------------------------------------------------- */
744 { assembly_operand AO;
745 AO = parse_expression(CONSTANT_CONTEXT);
746 if (module_switch && (AO.marker != 0))
747 error("A definite value must be given as release number");
749 release_number = AO.value;
753 /* --------------------------------------------------------------------- */
754 /* Replace routine [routinename] */
755 /* --------------------------------------------------------------------- */
758 /* You can also replace system functions normally implemented in */
759 /* the "hardware" of the Z-machine, like "random()": */
761 system_functions.enabled = TRUE;
762 directives.enabled = FALSE;
763 directive_keywords.enabled = FALSE;
765 /* Don't count the upcoming symbol as a top-level reference
766 *to* the function. */
767 df_dont_note_global_symbols = TRUE;
769 df_dont_note_global_symbols = FALSE;
770 if (token_type == SYSFUN_TT)
771 { if (system_function_usage[token_value] == 1)
772 error("You can't 'Replace' a system function already used");
773 else system_function_usage[token_value] = 2;
775 if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)))
777 error("You can't give a 'Replace'd system function a new name");
778 panic_mode_error_recovery(); return FALSE;
783 if (token_type != SYMBOL_TT)
784 return ebf_error_recover("name of routine to replace", token_text);
785 if (!(sflags[token_value] & UNKNOWN_SFLAG))
786 return ebf_error_recover("name of routine not yet defined", token_text);
788 sflags[token_value] |= REPLACE_SFLAG;
790 /* If a second symbol is provided, it will refer to the
791 original (replaced) definition of the routine. */
794 system_functions.enabled = FALSE;
795 df_dont_note_global_symbols = TRUE;
797 df_dont_note_global_symbols = FALSE;
798 if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
802 if (token_type != SYMBOL_TT || !(sflags[token_value] & UNKNOWN_SFLAG))
803 return ebf_error_recover("semicolon ';' or new routine name", token_text);
805 /* Define the original-form symbol as a zero constant. Its
806 value will be overwritten later, when we define the
808 assign_symbol(token_value, 0, CONSTANT_T);
809 add_symbol_replacement_mapping(i, token_value);
813 /* --------------------------------------------------------------------- */
814 /* Serial "yymmdd" */
815 /* --------------------------------------------------------------------- */
819 if ((token_type != DQ_TT) || (strlen(token_text)!=6))
820 { error("The serial number must be a 6-digit date in double-quotes");
821 panic_mode_error_recovery(); return FALSE;
823 for (i=0; i<6; i++) if (isdigit(token_text[i])==0)
824 { error("The serial number must be a 6-digit date in double-quotes");
825 panic_mode_error_recovery(); return FALSE;
827 strcpy(serial_code_buffer, token_text);
828 serial_code_given_in_program = TRUE;
831 /* --------------------------------------------------------------------- */
832 /* Statusline score/time */
833 /* --------------------------------------------------------------------- */
835 case STATUSLINE_CODE:
837 warning("This does not set the final game's statusline");
839 directive_keywords.enabled = TRUE;
841 directive_keywords.enabled = FALSE;
842 if ((token_type != DIR_KEYWORD_TT)
843 || ((token_value != SCORE_DK) && (token_value != TIME_DK)))
844 return ebf_error_recover("'score' or 'time' after 'statusline'", token_text);
845 if (token_value == SCORE_DK) statusline_flag = SCORE_STYLE;
846 else statusline_flag = TIME_STYLE;
849 /* --------------------------------------------------------------------- */
850 /* Stub routinename number-of-locals */
851 /* --------------------------------------------------------------------- */
855 { error("Cannot nest #Stub inside a routine or object");
856 panic_mode_error_recovery(); return FALSE;
859 /* The upcoming symbol is a definition; don't count it as a
860 top-level reference *to* the stub function. */
861 df_dont_note_global_symbols = TRUE;
863 df_dont_note_global_symbols = FALSE;
864 if (token_type != SYMBOL_TT)
865 return ebf_error_recover("routine name to stub", token_text);
867 i = token_value; flag = FALSE;
869 if (sflags[i] & UNKNOWN_SFLAG)
870 { sflags[i] |= STUB_SFLAG;
874 get_next_token(); k = token_value;
875 if (token_type != NUMBER_TT)
876 return ebf_error_recover("number of local variables", token_text);
878 { error("Must specify 0 to 4 local variables for 'Stub' routine");
884 /* Give these parameter-receiving local variables names
885 for the benefit of the debugging information file,
886 and for assembly tracing to look sensible. */
888 local_variable_texts[0] = "dummy1";
889 local_variable_texts[1] = "dummy2";
890 local_variable_texts[2] = "dummy3";
891 local_variable_texts[3] = "dummy4";
894 assemble_routine_header(k, FALSE, (char *) symbs[i], FALSE, i),
897 /* Ensure the return value of a stubbed routine is false,
898 since this is necessary to make the library work properly */
901 assemblez_0(rfalse_zc);
903 assembleg_1(return_gc, zero_operand);
905 /* Inhibit "local variable unused" warnings */
907 for (i=1; i<=k; i++) variable_usage[i] = 1;
908 sequence_point_follows = FALSE;
909 assemble_routine_end(FALSE, get_token_locations());
913 /* --------------------------------------------------------------------- */
914 /* Switches switchblock */
915 /* (this directive is ignored if the -i switch was set at command line) */
916 /* --------------------------------------------------------------------- */
919 dont_enter_into_symbol_table = TRUE;
921 dont_enter_into_symbol_table = FALSE;
922 if (token_type != DQ_TT)
923 return ebf_error_recover("string of switches", token_text);
924 if (!ignore_switches_switch)
925 { if (constant_made_yet)
926 error("A 'Switches' directive must must come before \
927 the first constant definition");
928 switches(token_text, 0); /* see "inform.c" */
932 /* --------------------------------------------------------------------- */
935 /* Some files are declared as "system files": this information is used */
936 /* by Inform only to skip the definition of a routine X if the designer */
937 /* has indicated his intention to Replace X. */
938 /* --------------------------------------------------------------------- */
941 declare_systemfile(); break; /* see "files.c" */
943 /* --------------------------------------------------------------------- */
944 /* Trace dictionary */
949 /* assembly [on/off] */
950 /* expressions [on/off] */
952 /* --------------------------------------------------------------------- */
955 directives.enabled = FALSE;
956 trace_keywords.enabled = TRUE;
958 trace_keywords.enabled = FALSE;
959 directives.enabled = TRUE;
960 if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
961 { asm_trace_level = 1; return FALSE; }
963 if (token_type != TRACE_KEYWORD_TT)
964 return ebf_error_recover("debugging keyword", token_text);
966 trace_keywords.enabled = TRUE;
968 i = token_value; j = 0;
970 { case DICTIONARY_TK: break;
971 case OBJECTS_TK: break;
972 case VERBS_TK: break;
976 trace_level = &asm_trace_level; break;
978 trace_level = &expr_trace_level; break;
980 trace_level = &line_trace_level; break;
982 trace_level = &tokens_trace_level; break;
984 trace_level = &linker_trace_level; break;
986 trace_level = NULL; break;
989 trace_level = &asm_trace_level; break;
993 if ((token_type == SEP_TT) &&
994 (token_value == SEMICOLON_SEP))
995 { put_token_back(); break;
997 if (token_type == NUMBER_TT)
998 { j = token_value; break; }
999 if ((token_type == TRACE_KEYWORD_TT) && (token_value == ON_TK))
1001 if ((token_type == TRACE_KEYWORD_TT) && (token_value == OFF_TK))
1003 put_token_back(); break;
1007 { case DICTIONARY_TK: show_dictionary(); break;
1008 case OBJECTS_TK: list_object_tree(); break;
1009 case SYMBOLS_TK: list_symbols(j); break;
1010 case VERBS_TK: list_verb_table(); break;
1015 trace_keywords.enabled = FALSE;
1018 /* --------------------------------------------------------------------- */
1020 /* --------------------------------------------------------------------- */
1024 if (token_type != SYMBOL_TT)
1025 return ebf_error_recover("symbol name", token_text);
1027 if (sflags[token_value] & UNKNOWN_SFLAG)
1028 { break; /* undef'ing an undefined constant is okay */
1031 if (stypes[token_value] != CONSTANT_T)
1032 { error_named("Cannot Undef a symbol which is not a defined constant:", (char *)symbs[token_value]);
1036 if (debugfile_switch)
1037 { write_debug_undef(token_value);
1039 end_symbol_scope(token_value);
1040 sflags[token_value] |= USED_SFLAG;
1043 /* --------------------------------------------------------------------- */
1045 /* --------------------------------------------------------------------- */
1047 case VERB_CODE: make_verb(); return FALSE; /* see "tables.c" */
1049 /* --------------------------------------------------------------------- */
1050 /* Version <number> */
1051 /* --------------------------------------------------------------------- */
1055 { assembly_operand AO;
1056 AO = parse_expression(CONSTANT_CONTEXT);
1057 /* If a version has already been set on the command line,
1058 that overrides this. */
1059 if (version_set_switch)
1061 warning("The Version directive was overridden by a command-line argument.");
1065 if (module_switch && (AO.marker != 0))
1066 error("A definite value must be given as version number");
1070 warning("The Version directive does not work in Glulx. Use \
1071 -vX.Y.Z instead, as either a command-line argument or a header comment.");
1077 { error("The version number must be in the range 3 to 8");
1083 break; /* see "inform.c" */
1085 /* --------------------------------------------------------------------- */
1086 /* Zcharacter table <num> ... */
1087 /* Zcharacter table + <num> ... */
1088 /* Zcharacter <string> <string> <string> */
1089 /* Zcharacter <char> */
1090 /* --------------------------------------------------------------------- */
1092 case ZCHARACTER_CODE:
1095 error("The Zcharacter directive has no meaning in Glulx.");
1096 panic_mode_error_recovery(); return FALSE;
1099 directive_keywords.enabled = TRUE;
1101 directive_keywords.enabled = FALSE;
1105 new_alphabet(token_text, 0);
1107 if (token_type != DQ_TT)
1108 return ebf_error_recover("double-quoted alphabet string", token_text);
1109 new_alphabet(token_text, 1);
1111 if (token_type != DQ_TT)
1112 return ebf_error_recover("double-quoted alphabet string", token_text);
1113 new_alphabet(token_text, 2);
1117 map_new_zchar(text_to_unicode(token_text));
1118 if (token_text[textual_form_length] != 0)
1119 return ebf_error_recover("single character value", token_text);
1122 case DIR_KEYWORD_TT:
1125 { int plus_flag = FALSE;
1127 if ((token_type == SEP_TT) && (token_value == PLUS_SEP))
1131 while ((token_type!=SEP_TT) || (token_value!=SEMICOLON_SEP))
1132 { switch(token_type)
1134 new_zscii_character(token_value, plus_flag);
1135 plus_flag = TRUE; break;
1137 new_zscii_character(text_to_unicode(token_text),
1139 if (token_text[textual_form_length] != 0)
1140 return ebf_error_recover("single character value",
1145 return ebf_error_recover("character or Unicode number",
1150 if (plus_flag) new_zscii_finished();
1154 case TERMINATING_DK:
1156 while ((token_type!=SEP_TT) || (token_value!=SEMICOLON_SEP))
1157 { switch(token_type)
1159 terminating_characters[no_termcs++]
1163 return ebf_error_recover("ZSCII number",
1171 return ebf_error_recover("'table', 'terminating', \
1172 a string or a constant",
1177 return ebf_error_recover("three alphabet strings, \
1178 a 'table' or 'terminating' command or a single character", token_text);
1182 /* ===================================================================== */
1186 /* We are now at the end of a syntactically valid directive. It
1187 should be terminated by a semicolon. */
1190 if ((token_type != SEP_TT) || (token_value != SEMICOLON_SEP))
1191 { ebf_error("';'", token_text);
1192 /* Put the non-semicolon back. We will continue parsing from
1193 that point, in hope that it's the start of a new directive.
1194 (This recovers cleanly from a missing semicolon at the end
1195 of a directive. It's not so clean if the directive *does*
1196 end with a semicolon, but there's extra garbage before it.) */
1202 /* ========================================================================= */
1203 /* Data structure management routines */
1204 /* ------------------------------------------------------------------------- */
1206 extern void init_directs_vars(void)
1210 extern void directs_begin_pass(void)
1212 no_named_routines = 0;
1215 constant_made_yet = FALSE;
1219 extern void directs_allocate_arrays(void)
1223 extern void directs_free_arrays(void)
1227 /* ========================================================================= */