Work toward getting rid of finalizers and control stacks and jumping around among...
[pspp] / src / language / command.c
index 924b221b22d2e3851dadc578bec58e64710fc284..522d53eaa2d34217a20371c0664d6709dda723f8 100644 (file)
@@ -89,19 +89,21 @@ cmd_result_is_failure (enum cmd_result result)
 /* Command processing states. */
 enum states
   {
-    S_INITIAL = 0x01,         /* Allowed before active dataset defined. */
-    S_DATA = 0x02,            /* Allowed after active dataset defined. */
-    S_INPUT_PROGRAM = 0x04,   /* Allowed in INPUT PROGRAM. */
-    S_FILE_TYPE = 0x08,       /* Allowed in FILE TYPE. */
-    S_ANY = 0x0f              /* Allowed anywhere. */
+    S_INITIAL = 1 << 0,         /* Allowed before active dataset defined. */
+    S_DATA = 1 << 1,            /* Allowed after active dataset defined. */
+    S_INPUT_PROGRAM = 1 << 2,   /* Allowed in INPUT PROGRAM. */
+    S_FILE_TYPE = 1 << 3,       /* Allowed in FILE TYPE. */
+    S_NESTED = 1 << 4,          /* Allowed in LOOP and DO IF. */
+
+    S_ANY = S_INITIAL | S_DATA | S_INPUT_PROGRAM | S_FILE_TYPE | S_NESTED,
   };
 
 /* Other command requirements. */
 enum flags
   {
-    F_ENHANCED = 0x10,        /* Allowed only in enhanced syntax mode. */
-    F_TESTING = 0x20,         /* Allowed only in testing mode. */
-    F_ABBREV = 0x80           /* Not a candidate for name completion. */
+    F_ENHANCED = 1 << 0,        /* Allowed only in enhanced syntax mode. */
+    F_TESTING = 1 << 1,         /* Allowed only in testing mode. */
+    F_ABBREV = 1 << 2           /* Not a candidate for name completion. */
   };
 
 /* A single command. */
@@ -126,7 +128,7 @@ static const struct command commands[] =
 static const size_t n_commands = sizeof commands / sizeof *commands;
 
 static bool in_correct_state (const struct command *, enum cmd_state);
-static bool report_state_mismatch (const struct command *, enum cmd_state);
+static void report_state_mismatch (const struct command *, enum cmd_state);
 static void set_completion_state (enum cmd_state);
 \f
 /* Command parser. */
@@ -360,21 +362,39 @@ parse_command_name (struct lexer *lexer, int *n_tokens)
 static bool
 in_correct_state (const struct command *command, enum cmd_state state)
 {
-  return ((state == CMD_STATE_INITIAL && command->states & S_INITIAL)
-          || (state == CMD_STATE_DATA && command->states & S_DATA)
-          || (state == CMD_STATE_INPUT_PROGRAM
-              && command->states & S_INPUT_PROGRAM)
-          || (state == CMD_STATE_FILE_TYPE && command->states & S_FILE_TYPE));
+  switch (state)
+    {
+    case CMD_STATE_INITIAL:
+      return command->states & S_INITIAL;
+
+    case CMD_STATE_DATA:
+      return command->states & S_DATA;
+
+    case CMD_STATE_INPUT_PROGRAM:
+      return command->states & S_INPUT_PROGRAM;
+
+    case CMD_STATE_FILE_TYPE:
+      return command->states & S_FILE_TYPE;
+
+    case CMD_STATE_NESTED:
+      return command->states & S_NESTED;
+
+    default:
+      NOT_REACHED ();
+    }
 }
 
 /* Emits an appropriate error message for trying to invoke
    COMMAND in STATE. */
-static bool
+static void
 report_state_mismatch (const struct command *command, enum cmd_state state)
 {
   assert (!in_correct_state (command, state));
-  if (state == CMD_STATE_INITIAL || state == CMD_STATE_DATA)
+
+  switch (state)
     {
+    case CMD_STATE_INITIAL:
+    case CMD_STATE_DATA:
       switch ((int) command->states)
         {
           /* One allowed state. */
@@ -441,14 +461,21 @@ report_state_mismatch (const struct command *command, enum cmd_state state)
         default:
           NOT_REACHED ();
         }
-    }
-  else if (state == CMD_STATE_INPUT_PROGRAM)
-    msg (SE, _("%s is not allowed inside %s."),
-        command->name, "INPUT PROGRAM");
-  else if (state == CMD_STATE_FILE_TYPE)
-    msg (SE, _("%s is not allowed inside %s."), command->name, "FILE TYPE");
+      break;
+
+    case CMD_STATE_INPUT_PROGRAM:
+      msg (SE, _("%s is not allowed inside %s."),
+           command->name, "INPUT PROGRAM");
+      break;
 
-  return false;
+    case CMD_STATE_FILE_TYPE:
+      msg (SE, _("%s is not allowed inside %s."), command->name, "FILE TYPE");
+      break;
+
+    case CMD_STATE_NESTED:
+      msg (SE, _("%s is not allowed inside DO IF or LOOP."), command->name);
+      break;
+    }
 }
 \f
 /* Command name completion. */