/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009-2011, 2013 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include <config.h>
-#include "control-stack.h"
-
-#include <data/case.h>
-#include <data/dictionary.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/compiler.h>
-#include <libpspp/message.h>
-#include <libpspp/misc.h>
-#include <libpspp/pool.h>
-#include <libpspp/str.h>
-
-#include "xalloc.h"
+#include "data/case.h"
+#include "data/control-stack.h"
+#include "data/dataset.h"
+#include "data/dictionary.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/compiler.h"
+#include "libpspp/message.h"
+#include "libpspp/misc.h"
+#include "libpspp/pool.h"
+#include "libpspp/str.h"
+
+#include "gl/xalloc.h"
#include "gettext.h"
#define _(msgid) gettext (msgid)
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;
/* Parses BREAK. */
int
-cmd_break (struct lexer *lexer, struct dataset *ds)
+cmd_break (struct lexer *lexer UNUSED, struct dataset *ds)
{
struct ctl_stmt *loop = ctl_stack_search (&loop_class);
if (loop == NULL)
add_transformation (ds, break_trns_proc, NULL, loop);
- return lex_end_of_command (lexer);
+ return CMD_SUCCESS;
}
/* Closes a LOOP construct by emitting the END LOOP
}
if (loop->last_expr == NULL)
{
- lex_sbc_missing (lexer, "TO");
+ lex_sbc_missing ("TO");
return false;
}
if (loop->by_expr == NULL)
loop->loop_condition = loop->end_loop_condition = NULL;
loop->ds = ds;
- add_transformation_with_finalizer (ds, loop_trns_finalize,
- loop_trns_proc, loop_trns_free, loop);
+ add_transformation (ds, 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, casenumber case_num)
&& expr_evaluate_num (loop->loop_condition, *c, case_num) != 1.0)
goto zero_pass;
- return loop->past_LOOP_index;
+ return TRNS_CONTINUE;
zero_pass:
- return loop->past_END_LOOP_index;
+ return loop->past_END_LOOP_index - loop->past_LOOP_index + 1;
}
/* Frees LOOP. */
goto break_out;
/* MXLOOPS limiter. */
- if (loop->max_pass_count >= 0)
- {
- if (loop->pass >= loop->max_pass_count)
- goto break_out;
- loop->pass++;
- }
+ if (loop->max_pass_count >= 0 && ++loop->pass >= loop->max_pass_count)
+ goto break_out;
/* Indexing clause limiter: counting downward. */
if (loop->index_var != NULL)
&& expr_evaluate_num (loop->loop_condition, *c, case_num) != 1.0)
goto break_out;
- return loop->past_LOOP_index;
+ return loop->past_LOOP_index - loop->past_END_LOOP_index;
break_out:
- return loop->past_END_LOOP_index;
+ return TRNS_CONTINUE;
}
/* Executes BREAK. */