02110-1301, USA. */
#include <config.h>
-#include <libpspp/message.h>
-#include <libpspp/alloc.h>
+
+#include "control-stack.h"
#include <data/case.h>
-#include <language/command.h>
-#include <libpspp/compiler.h>
#include <data/dictionary.h>
-#include "control-stack.h"
-#include <libpspp/message.h>
+#include <data/procedure.h>
+#include <data/settings.h>
+#include <data/transformations.h>
+#include <data/variable.h>
+#include <language/command.h>
#include <language/expressions/public.h>
#include <language/lexer/lexer.h>
+#include <libpspp/alloc.h>
+#include <libpspp/compiler.h>
+#include <libpspp/message.h>
#include <libpspp/misc.h>
#include <libpspp/pool.h>
-#include <data/settings.h>
#include <libpspp/str.h>
-#include <data/variable.h>
#include "gettext.h"
#define _(msgid) gettext (msgid)
struct loop_trns
{
struct pool *pool;
+ struct dataset *ds;
/* Iteration limit. */
int max_pass_count; /* Maximum number of passes (-1=unlimited). */
int past_END_LOOP_index; /* Just past END LOOP transformation. */
};
-static struct ctl_class loop_class;
+static const struct ctl_class loop_class;
+static trns_finalize_func loop_trns_finalize;
static trns_proc_func loop_trns_proc, end_loop_trns_proc, break_trns_proc;
static trns_free_func loop_trns_free;
-static struct loop_trns *create_loop_trns (void);
+static struct loop_trns *create_loop_trns (struct dataset *);
static bool parse_if_clause (struct loop_trns *, struct expression **);
static bool parse_index_clause (struct loop_trns *, char index_var_name[]);
static void close_loop (void *);
/* Parses LOOP. */
int
-cmd_loop (void)
+cmd_loop (struct dataset *ds)
{
struct loop_trns *loop;
char index_var_name[LONG_NAME_LEN + 1];
bool ok = true;
- loop = create_loop_trns ();
+ loop = create_loop_trns (ds);
while (token != '.' && ok)
{
if (lex_match_id ("IF"))
/* Find index variable and create if necessary. */
if (ok && index_var_name[0] != '\0')
{
- loop->index_var = dict_lookup_var (default_dict, index_var_name);
+ loop->index_var = dict_lookup_var (dataset_dict (ds), index_var_name);
if (loop->index_var == NULL)
- loop->index_var = dict_create_var (default_dict, index_var_name, 0);
+ loop->index_var = dict_create_var (dataset_dict (ds),
+ index_var_name, 0);
}
if (!ok)
loop->max_pass_count = 0;
- return ok ? CMD_SUCCESS : CMD_PART_SUCCESS;
+ return ok ? CMD_SUCCESS : CMD_FAILURE;
}
/* Parses END LOOP. */
int
-cmd_end_loop (void)
+cmd_end_loop (struct dataset *ds)
{
struct loop_trns *loop;
bool ok = true;
loop = ctl_stack_top (&loop_class);
if (loop == NULL)
return CMD_CASCADING_FAILURE;
+
+ assert (loop->ds == ds);
/* Parse syntax. */
if (lex_match_id ("IF"))
ctl_stack_pop (loop);
- return ok ? CMD_SUCCESS : CMD_PART_SUCCESS;
+ return ok ? CMD_SUCCESS : CMD_FAILURE;
}
/* Parses BREAK. */
int
-cmd_break (void)
+cmd_break (struct dataset *ds)
{
struct ctl_stmt *loop = ctl_stack_search (&loop_class);
if (loop == NULL)
return CMD_CASCADING_FAILURE;
- add_transformation (break_trns_proc, NULL, loop);
+ add_transformation (ds, break_trns_proc, NULL, loop);
return lex_end_of_command ();
}
{
struct loop_trns *loop = loop_;
- add_transformation (end_loop_trns_proc, NULL, loop);
- loop->past_END_LOOP_index = next_transformation ();
+ add_transformation (loop->ds, end_loop_trns_proc, NULL, loop);
+ loop->past_END_LOOP_index = next_transformation (loop->ds);
/* If there's nothing else limiting the number of loops, use
MXLOOPS as a limit. */
static bool
parse_if_clause (struct loop_trns *loop, struct expression **condition)
{
- *condition = expr_parse_pool (loop->pool, default_dict, EXPR_BOOLEAN);
+ *condition = expr_parse_pool (loop->pool, loop->ds, EXPR_BOOLEAN);
return *condition != NULL;
}
if (!lex_force_match ('='))
return false;
- loop->first_expr = expr_parse_pool (loop->pool, default_dict, EXPR_NUMBER);
+ loop->first_expr = expr_parse_pool (loop->pool, loop->ds, EXPR_NUMBER);
if (loop->first_expr == NULL)
return false;
lex_sbc_only_once (e == &loop->last_expr ? "TO" : "BY");
return false;
}
- *e = expr_parse_pool (loop->pool, default_dict, EXPR_NUMBER);
+ *e = expr_parse_pool (loop->pool, loop->ds, EXPR_NUMBER);
if (*e == NULL)
return false;
}
/* Creates, initializes, and returns a new loop_trns. */
static struct loop_trns *
-create_loop_trns (void)
+create_loop_trns (struct dataset *ds)
{
struct loop_trns *loop = pool_create_container (struct loop_trns, pool);
loop->max_pass_count = -1;
loop->index_var = NULL;
loop->first_expr = loop->by_expr = loop->last_expr = NULL;
loop->loop_condition = loop->end_loop_condition = NULL;
+ loop->ds = ds;
- add_transformation (loop_trns_proc, loop_trns_free, loop);
- loop->past_LOOP_index = next_transformation ();
+ add_transformation_with_finalizer (ds, loop_trns_finalize,
+ loop_trns_proc, loop_trns_free, loop);
+ loop->past_LOOP_index = next_transformation (ds);
ctl_stack_push (&loop_class, loop);
return loop;
}
+/* Finalizes LOOP by clearing the control stack, thus ensuring
+ that all open LOOPs are closed. */
+static void
+loop_trns_finalize (void *do_if_ UNUSED)
+{
+ /* This will be called multiple times if multiple LOOPs were
+ executed, which is slightly unclean, but at least it's
+ idempotent. */
+ ctl_stack_clear ();
+}
+
/* Sets up LOOP for the first pass. */
static int
-loop_trns_proc (void *loop_, struct ccase *c, int case_num)
+loop_trns_proc (void *loop_, struct ccase *c, casenumber case_num)
{
struct loop_trns *loop = loop_;
/* Finishes a pass through the loop and starts the next. */
static int
-end_loop_trns_proc (void *loop_, struct ccase *c, int case_num UNUSED)
+end_loop_trns_proc (void *loop_, struct ccase *c, casenumber case_num UNUSED)
{
struct loop_trns *loop = loop_;
/* Executes BREAK. */
static int
-break_trns_proc (void *loop_, struct ccase *c UNUSED, int case_num UNUSED)
+break_trns_proc (void *loop_, struct ccase *c UNUSED, casenumber case_num UNUSED)
{
struct loop_trns *loop = loop_;
}
/* LOOP control structure class definition. */
-static struct ctl_class loop_class =
+static const struct ctl_class loop_class =
{
"LOOP",
"END LOOP",