X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=inline;f=src%2Flanguage%2Fcontrol%2Floop.c;h=cece7f68f647cf91e1fd925759c9b7c7a0c80f06;hb=refs%2Fbuilds%2F20130614010504%2Fpspp;hp=dafc0ba8b4c2a534657fc51a85e6f18a08fe4613;hpb=dbf12b0ee6a99119c6854a663184f8df4f4c5241;p=pspp
diff --git a/src/language/control/loop.c b/src/language/control/loop.c
index dafc0ba8b4..cece7f68f6 100644
--- a/src/language/control/loop.c
+++ b/src/language/control/loop.c
@@ -1,39 +1,39 @@
-/* PSPP - computes sample statistics.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+/* PSPP - a program for statistical analysis.
+ Copyright (C) 1997-9, 2000, 2009-2011 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 the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
+ 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
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA. */
+ along with this program. If not, see . */
#include
-#include "control-stack.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
+#include "language/control/control-stack.h"
+
+#include "data/case.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)
@@ -103,18 +103,18 @@ cmd_loop (struct lexer *lexer, struct dataset *ds)
bool ok = true;
loop = create_loop_trns (ds);
- while (lex_token (lexer) != '.' && ok)
+ while (lex_token (lexer) != T_ENDCMD && ok)
{
- if (lex_match_id (lexer, "IF"))
+ if (lex_match_id (lexer, "IF"))
ok = parse_if_clause (lexer, loop, &loop->loop_condition);
else
ok = parse_index_clause (ds, lexer, loop, &created_index_var);
}
/* Clean up if necessary. */
- if (!ok)
+ if (!ok)
{
- loop->max_pass_count = 0;
+ loop->max_pass_count = 0;
if (loop->index_var != NULL && created_index_var)
{
dict_delete_var (dataset_dict (ds), loop->index_var);
@@ -137,7 +137,7 @@ cmd_end_loop (struct lexer *lexer, struct dataset *ds)
return CMD_CASCADING_FAILURE;
assert (loop->ds == ds);
-
+
/* Parse syntax. */
if (lex_match_id (lexer, "IF"))
ok = parse_if_clause (lexer, loop, &loop->end_loop_condition);
@@ -148,13 +148,13 @@ cmd_end_loop (struct lexer *lexer, struct dataset *ds)
loop->max_pass_count = 0;
ctl_stack_pop (loop);
-
+
return ok ? CMD_SUCCESS : CMD_FAILURE;
}
/* 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)
@@ -162,7 +162,7 @@ cmd_break (struct lexer *lexer, struct dataset *ds)
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
@@ -171,7 +171,7 @@ static void
close_loop (void *loop_)
{
struct loop_trns *loop = loop_;
-
+
add_transformation (loop->ds, end_loop_trns_proc, NULL, loop);
loop->past_END_LOOP_index = next_transformation (loop->ds);
@@ -181,22 +181,22 @@ close_loop (void *loop_)
&& loop->index_var == NULL
&& loop->loop_condition == NULL
&& loop->end_loop_condition == NULL)
- loop->max_pass_count = get_mxloops ();
+ loop->max_pass_count = settings_get_mxloops ();
}
/* Parses an IF clause for LOOP or END LOOP and stores the
resulting expression to *CONDITION.
Returns true if successful, false on failure. */
static bool
-parse_if_clause (struct lexer *lexer,
- struct loop_trns *loop, struct expression **condition)
+parse_if_clause (struct lexer *lexer,
+ struct loop_trns *loop, struct expression **condition)
{
- if (*condition != NULL)
+ if (*condition != NULL)
{
lex_sbc_only_once ("IF");
return false;
}
-
+
*condition = expr_parse_pool (lexer, loop->pool, loop->ds, EXPR_BOOLEAN);
return *condition != NULL;
}
@@ -207,35 +207,35 @@ parse_if_clause (struct lexer *lexer,
Returns true if successful, false on failure. */
static bool
parse_index_clause (struct dataset *ds, struct lexer *lexer,
- struct loop_trns *loop, bool *created_index_var)
+ struct loop_trns *loop, bool *created_index_var)
{
- if (loop->index_var != NULL)
+ if (loop->index_var != NULL)
{
msg (SE, _("Only one index clause may be specified."));
return false;
}
- if (lex_token (lexer) != T_ID)
+ if (lex_token (lexer) != T_ID)
{
lex_error (lexer, NULL);
return false;
}
- loop->index_var = dict_lookup_var (dataset_dict (ds), lex_tokid (lexer));
+ loop->index_var = dict_lookup_var (dataset_dict (ds), lex_tokcstr (lexer));
if (loop->index_var != NULL)
*created_index_var = false;
else
{
- loop->index_var = dict_create_var_assert (dataset_dict (ds),
- lex_tokid (lexer), 0);
- *created_index_var = true;
+ loop->index_var = dict_create_var_assert (dataset_dict (ds),
+ lex_tokcstr (lexer), 0);
+ *created_index_var = true;
}
lex_get (lexer);
- if (!lex_force_match (lexer, '='))
+ if (!lex_force_match (lexer, T_EQUALS))
return false;
- loop->first_expr = expr_parse_pool (lexer, loop->pool,
+ loop->first_expr = expr_parse_pool (lexer, loop->pool,
loop->ds, EXPR_NUMBER);
if (loop->first_expr == NULL)
return false;
@@ -243,14 +243,14 @@ parse_index_clause (struct dataset *ds, struct lexer *lexer,
for (;;)
{
struct expression **e;
- if (lex_match (lexer, T_TO))
+ if (lex_match (lexer, T_TO))
e = &loop->last_expr;
- else if (lex_match (lexer, T_BY))
+ else if (lex_match (lexer, T_BY))
e = &loop->by_expr;
else
break;
- if (*e != NULL)
+ if (*e != NULL)
{
lex_sbc_only_once (e == &loop->last_expr ? "TO" : "BY");
return false;
@@ -259,9 +259,9 @@ parse_index_clause (struct dataset *ds, struct lexer *lexer,
if (*e == NULL)
return false;
}
- if (loop->last_expr == NULL)
+ if (loop->last_expr == NULL)
{
- lex_sbc_missing (lexer, "TO");
+ lex_sbc_missing ("TO");
return false;
}
if (loop->by_expr == NULL)
@@ -272,7 +272,7 @@ parse_index_clause (struct dataset *ds, struct lexer *lexer,
/* Creates, initializes, and returns a new loop_trns. */
static struct loop_trns *
-create_loop_trns (struct dataset *ds)
+create_loop_trns (struct dataset *ds)
{
struct loop_trns *loop = pool_create_container (struct loop_trns, pool);
loop->max_pass_count = -1;
@@ -292,9 +292,9 @@ create_loop_trns (struct dataset *ds)
}
/* Finalizes LOOP by clearing the control stack, thus ensuring
- that all open LOOPs are closed. */
+ that all open LOOPs are closed. */
static void
-loop_trns_finalize (void *do_if_ UNUSED)
+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
@@ -304,24 +304,26 @@ loop_trns_finalize (void *do_if_ UNUSED)
/* Sets up LOOP for the first pass. */
static int
-loop_trns_proc (void *loop_, struct ccase *c, casenumber case_num)
+loop_trns_proc (void *loop_, struct ccase **c, casenumber case_num)
{
struct loop_trns *loop = loop_;
if (loop->index_var != NULL)
{
/* Evaluate loop index expressions. */
- loop->cur = expr_evaluate_num (loop->first_expr, c, case_num);
+ loop->cur = expr_evaluate_num (loop->first_expr, *c, case_num);
if (loop->by_expr != NULL)
- loop->by = expr_evaluate_num (loop->by_expr, c, case_num);
- loop->last = expr_evaluate_num (loop->last_expr, c, case_num);
+ loop->by = expr_evaluate_num (loop->by_expr, *c, case_num);
+ loop->last = expr_evaluate_num (loop->last_expr, *c, case_num);
/* Even if the loop is never entered, set the index
variable to the initial value. */
- case_data_rw (c, loop->index_var)->f = loop->cur;
+ *c = case_unshare (*c);
+ case_data_rw (*c, loop->index_var)->f = loop->cur;
/* Throw out pathological cases. */
- if (!finite (loop->cur) || !finite (loop->by) || !finite (loop->last)
+ if (!isfinite (loop->cur) || !isfinite (loop->by)
+ || !isfinite (loop->last)
|| loop->by == 0.0
|| (loop->by > 0.0 && loop->cur > loop->last)
|| (loop->by < 0.0 && loop->cur < loop->last))
@@ -335,7 +337,7 @@ loop_trns_proc (void *loop_, struct ccase *c, casenumber case_num)
/* Check condition. */
if (loop->loop_condition != NULL
- && expr_evaluate_num (loop->loop_condition, c, case_num) != 1.0)
+ && expr_evaluate_num (loop->loop_condition, *c, case_num) != 1.0)
goto zero_pass;
return loop->past_LOOP_index;
@@ -356,34 +358,31 @@ loop_trns_free (void *loop_)
/* Finishes a pass through the loop and starts the next. */
static int
-end_loop_trns_proc (void *loop_, struct ccase *c, casenumber case_num UNUSED)
+end_loop_trns_proc (void *loop_, struct ccase **c, casenumber case_num UNUSED)
{
struct loop_trns *loop = loop_;
if (loop->end_loop_condition != NULL
- && expr_evaluate_num (loop->end_loop_condition, c, case_num) != 0.0)
+ && expr_evaluate_num (loop->end_loop_condition, *c, case_num) != 0.0)
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)
+ if (loop->index_var != NULL)
{
loop->cur += loop->by;
if ((loop->by > 0.0 && loop->cur > loop->last)
|| (loop->by < 0.0 && loop->cur < loop->last))
goto break_out;
- case_data_rw (c, loop->index_var)->f = loop->cur;
+ *c = case_unshare (*c);
+ case_data_rw (*c, loop->index_var)->f = loop->cur;
}
if (loop->loop_condition != NULL
- && expr_evaluate_num (loop->loop_condition, c, case_num) != 1.0)
+ && expr_evaluate_num (loop->loop_condition, *c, case_num) != 1.0)
goto break_out;
return loop->past_LOOP_index;
@@ -394,7 +393,8 @@ end_loop_trns_proc (void *loop_, struct ccase *c, casenumber case_num UNUSED)
/* Executes BREAK. */
static int
-break_trns_proc (void *loop_, struct ccase *c UNUSED, casenumber case_num UNUSED)
+break_trns_proc (void *loop_, struct ccase **c UNUSED,
+ casenumber case_num UNUSED)
{
struct loop_trns *loop = loop_;