X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fcontrol%2Floop.c;h=bfd364ccd1085a8d5874c6b018cfd2ded31fc4f8;hb=3b54533821614d17afc61f1cd3b87d3a06fbf4da;hp=5a2417131e49dd3b7ff1a24d2dd90da7b5a9071e;hpb=f5c108becd49d78f4898cab11352291f5689d24e;p=pspp
diff --git a/src/language/control/loop.c b/src/language/control/loop.c
index 5a2417131e..bfd364ccd1 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)
@@ -61,7 +61,7 @@ struct loop_trns
/* Iteration limit. */
int max_pass_count; /* Maximum number of passes (-1=unlimited). */
- int pass; /* Number of passes thru the loop so far. */
+ int pass; /* Number of passes through the loop so far. */
/* a=a TO b [BY c]. */
struct variable *index_var; /* Index variable. */
@@ -103,7 +103,7 @@ 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"))
ok = parse_if_clause (lexer, loop, &loop->loop_condition);
@@ -154,7 +154,7 @@ cmd_end_loop (struct lexer *lexer, struct dataset *ds)
/* 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
@@ -177,11 +177,8 @@ close_loop (void *loop_)
/* If there's nothing else limiting the number of loops, use
MXLOOPS as a limit. */
- if (loop->max_pass_count == -1
- && loop->index_var == NULL
- && loop->loop_condition == NULL
- && loop->end_loop_condition == NULL)
- loop->max_pass_count = get_mxloops ();
+ if (loop->max_pass_count == -1 && loop->index_var == NULL)
+ loop->max_pass_count = settings_get_mxloops ();
}
/* Parses an IF clause for LOOP or END LOOP and stores the
@@ -221,18 +218,18 @@ parse_index_clause (struct dataset *ds, struct lexer *lexer,
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);
+ 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,
@@ -261,7 +258,7 @@ parse_index_clause (struct dataset *ds, struct lexer *lexer,
}
if (loop->last_expr == NULL)
{
- lex_sbc_missing (lexer, "TO");
+ lex_sbc_missing ("TO");
return false;
}
if (loop->by_expr == NULL)
@@ -304,24 +301,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 +334,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,21 +355,17 @@ 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)
@@ -379,11 +374,12 @@ end_loop_trns_proc (void *loop_, struct ccase *c, casenumber case_num UNUSED)
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 +390,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_;