Update to commit e2647ad952b4d7afc9a186429c181efbc4958786
[inform.git] / src / directs.c
index 2fbc40bc369150f49b2ad3bd613378a5d5578038..fc725a0d611263044028c358f04f3a39839d602d 100644 (file)
@@ -1,9 +1,8 @@
 /* ------------------------------------------------------------------------- */
 /*   "directs" : Directives (# commands)                                     */
 /*                                                                           */
-/* Copyright (c) Graham Nelson 1993 - 2020                                   */
-/*                                                                           */
-/* This file is part of Inform.                                              */
+/*   Part of Inform 6.35                                                     */
+/*   copyright (c) Graham Nelson 1993 - 2020                                 */
 /*                                                                           */
 /* Inform is free software: you can redistribute it and/or modify            */
 /* it under the terms of the GNU General Public License as published by      */
@@ -52,6 +51,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 +72,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)
     {
 
@@ -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;
 
@@ -582,8 +609,10 @@ Fake_Action directives to a point after the inclusion of \"Parser\".)");
             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)
@@ -645,10 +674,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" */
 
@@ -657,10 +682,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" */
 
@@ -851,11 +872,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;