X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=src%2Fdirects.c;h=15831728118b840102d401f7f67b7619c996a21e;hb=d8d68d0bd4c45af6f0dc69b4fc33d37d961aca85;hp=d3b7f32c6032e1f7548700b691f8ff3c7212a05a;hpb=81ffe9a7de1db0b3a318a053b38882d1b7ab304c;p=inform.git diff --git a/src/directs.c b/src/directs.c index d3b7f32..1583172 100644 --- a/src/directs.c +++ b/src/directs.c @@ -1,9 +1,8 @@ /* ------------------------------------------------------------------------- */ /* "directs" : Directives (# commands) */ /* */ -/* Copyright (c) Graham Nelson 1993 - 2018 */ -/* */ -/* This file is part of Inform. */ +/* Part of Inform 6.35 */ +/* copyright (c) Graham Nelson 1993 - 2021 */ /* */ /* Inform is free software: you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ @@ -35,7 +34,8 @@ brief_location routine_starts_line; /* Source code location where the current static int constant_made_yet; /* Have any constants been defined yet? */ -static int ifdef_stack[32], ifdef_sp; +#define MAX_IFDEF_STACK (32) +static int ifdef_stack[MAX_IFDEF_STACK], ifdef_sp; /* ------------------------------------------------------------------------- */ @@ -52,6 +52,14 @@ static int ebf_error_recover(char *s1, char *s2) return FALSE; } +static int ebf_symbol_error_recover(char *s1, char *name, char *type, brief_location report_line) +{ + /* Same for ebf_symbol_error(). */ + ebf_symbol_error(s1, name, type, report_line); + panic_mode_error_recovery(); + return FALSE; +} + /* ------------------------------------------------------------------------- */ extern int parse_given_directive(int internal_flag) @@ -65,6 +73,26 @@ extern int parse_given_directive(int internal_flag) const char *constant_name; debug_location_beginning beginning_debug_location; + if (internal_flag) + { + /* Only certain directives, such as #ifdef, are permitted within + a routine or object definition. In older versions of Inform, + nearly any directive was accepted, but this was -- to quote + an old code comment -- "about as well-supported as Wile E. + Coyote one beat before the plummet-lines kick in." */ + + if (token_value != IFV3_CODE && token_value != IFV5_CODE + && token_value != IFDEF_CODE && token_value != IFNDEF_CODE + && token_value != IFTRUE_CODE && token_value != IFFALSE_CODE + && token_value != IFNOT_CODE && token_value != ENDIF_CODE + && token_value != MESSAGE_CODE && token_value != ORIGSOURCE_CODE + && token_value != TRACE_CODE) { + char *dirname = directives.keywords[token_value]; + error_named("Cannot nest this directive inside a routine or object:", dirname); + panic_mode_error_recovery(); return FALSE; + } + } + switch(token_value) { @@ -79,9 +107,8 @@ extern int parse_given_directive(int internal_flag) if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) return FALSE; - /* Z-code has a 64-abbrev limit; Glulx doesn't. */ - if (!glulx_mode && no_abbreviations==64) - { error("All 64 abbreviations already declared"); + if (!glulx_mode && no_abbreviations==96) + { error("All 96 Z-machine abbreviations already declared"); panic_mode_error_recovery(); return FALSE; } if (no_abbreviations==MAX_ABBREVS) @@ -124,10 +151,6 @@ extern int parse_given_directive(int internal_flag) /* --------------------------------------------------------------------- */ case CLASS_CODE: - if (internal_flag) - { error("Cannot nest #Class inside a routine or object"); - panic_mode_error_recovery(); return FALSE; - } make_class(NULL); /* See "objects.c" */ return FALSE; @@ -142,12 +165,16 @@ extern int parse_given_directive(int internal_flag) get_next_token(); i = token_value; beginning_debug_location = get_token_location_beginning(); - if ((token_type != SYMBOL_TT) - || (!(sflags[i] & (UNKNOWN_SFLAG + REDEFINABLE_SFLAG)))) + if (token_type != SYMBOL_TT) { discard_token_location(beginning_debug_location); return ebf_error_recover("new constant name", token_text); } + if (!(sflags[i] & (UNKNOWN_SFLAG + REDEFINABLE_SFLAG))) + { discard_token_location(beginning_debug_location); + return ebf_symbol_error_recover("new constant name", token_text, typename(stypes[i]), slines[i]); + } + assign_symbol(i, 0, CONSTANT_T); constant_name = token_text; @@ -289,7 +316,7 @@ Fake_Action directives to a point after the inclusion of \"Parser\".)"); assembly_operand AO; put_token_back(); AO = parse_expression(CONSTANT_CONTEXT); - if (module_switch && (AO.marker != 0)) + if (AO.marker != 0) error("A definite value must be given as a Dictionary flag"); else val1 = AO.value; @@ -302,7 +329,7 @@ Fake_Action directives to a point after the inclusion of \"Parser\".)"); assembly_operand AO; put_token_back(); AO = parse_expression(CONSTANT_CONTEXT); - if (module_switch && (AO.marker != 0)) + if (AO.marker != 0) error("A definite value must be given as a Dictionary flag"); else val3 = AO.value; @@ -434,17 +461,19 @@ Fake_Action directives to a point after the inclusion of \"Parser\".)"); break; case IFV3_CODE: - flag = FALSE; if (version_number == 3) flag = TRUE; + flag = FALSE; + if (!glulx_mode && version_number <= 3) flag = TRUE; goto HashIfCondition; case IFV5_CODE: - flag = TRUE; if (version_number == 3) flag = FALSE; + flag = TRUE; + if (!glulx_mode && version_number <= 3) flag = FALSE; goto HashIfCondition; case IFTRUE_CODE: { assembly_operand AO; AO = parse_expression(CONSTANT_CONTEXT); - if (module_switch && (AO.marker != 0)) + if (AO.marker != 0) { error("This condition can't be determined"); flag = 0; } @@ -455,7 +484,7 @@ Fake_Action directives to a point after the inclusion of \"Parser\".)"); case IFFALSE_CODE: { assembly_operand AO; AO = parse_expression(CONSTANT_CONTEXT); - if (module_switch && (AO.marker != 0)) + if (AO.marker != 0) { error("This condition can't be determined"); flag = 1; } @@ -468,6 +497,11 @@ Fake_Action directives to a point after the inclusion of \"Parser\".)"); if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))) return ebf_error_recover("semicolon after 'If...' condition", token_text); + if (ifdef_sp >= MAX_IFDEF_STACK) { + error("'If' directives nested too deeply"); + panic_mode_error_recovery(); return FALSE; + } + if (flag) { ifdef_stack[ifdef_sp++] = TRUE; return FALSE; } else @@ -579,15 +613,21 @@ Fake_Action directives to a point after the inclusion of \"Parser\".)"); { error("'LowString' cannot be used in -M (Module) mode"); panic_mode_error_recovery(); return FALSE; } + if (glulx_mode) { + error("The LowString directive has no meaning in Glulx."); + panic_mode_error_recovery(); return FALSE; + } get_next_token(); i = token_value; - if ((token_type != SYMBOL_TT) || (!(sflags[i] & UNKNOWN_SFLAG))) + if (token_type != SYMBOL_TT) return ebf_error_recover("new low string name", token_text); + if (!(sflags[i] & UNKNOWN_SFLAG)) + return ebf_symbol_error_recover("new low string name", token_text, typename(stypes[i]), slines[i]); get_next_token(); if (token_type != DQ_TT) return ebf_error_recover("literal string in double-quotes", token_text); - assign_symbol(i, compile_string(token_text, TRUE, TRUE), CONSTANT_T); + assign_symbol(i, compile_string(token_text, STRCTX_LOWSTRING), CONSTANT_T); break; /* --------------------------------------------------------------------- */ @@ -643,10 +683,6 @@ Fake_Action directives to a point after the inclusion of \"Parser\".)"); /* --------------------------------------------------------------------- */ case NEARBY_CODE: - if (internal_flag) - { error("Cannot nest #Nearby inside a routine or object"); - panic_mode_error_recovery(); return FALSE; - } make_object(TRUE, NULL, -1, -1, -1); return FALSE; /* See "objects.c" */ @@ -655,10 +691,6 @@ Fake_Action directives to a point after the inclusion of \"Parser\".)"); /* --------------------------------------------------------------------- */ case OBJECT_CODE: - if (internal_flag) - { error("Cannot nest #Object inside a routine or object"); - panic_mode_error_recovery(); return FALSE; - } make_object(FALSE, NULL, -1, -1, -1); return FALSE; /* See "objects.c" */ @@ -741,7 +773,7 @@ Fake_Action directives to a point after the inclusion of \"Parser\".)"); case RELEASE_CODE: { assembly_operand AO; AO = parse_expression(CONSTANT_CONTEXT); - if (module_switch && (AO.marker != 0)) + if (AO.marker != 0) error("A definite value must be given as release number"); else release_number = AO.value; @@ -849,11 +881,6 @@ Fake_Action directives to a point after the inclusion of \"Parser\".)"); /* --------------------------------------------------------------------- */ case STUB_CODE: - if (internal_flag) - { error("Cannot nest #Stub inside a routine or object"); - panic_mode_error_recovery(); return FALSE; - } - /* The upcoming symbol is a definition; don't count it as a top-level reference *to* the stub function. */ df_dont_note_global_symbols = TRUE; @@ -1060,7 +1087,7 @@ the first constant definition"); break; } - if (module_switch && (AO.marker != 0)) + if (AO.marker != 0) error("A definite value must be given as version number"); else if (glulx_mode)