X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fcontrol%2Floop.c;h=5c22f3ca57d377c48d2ff25b0b612ec9a7cda4ad;hb=0ed7ffcf1a0ed3c8ae68099c9f212592e8a5ec4a;hp=da1dc2fc49dfeda732b6f8e599ffe3d14fd92496;hpb=a19b858e0ac3c69e4a28c0ca6d8674427268a863;p=pspp diff --git a/src/language/control/loop.c b/src/language/control/loop.c index da1dc2fc49..5c22f3ca57 100644 --- a/src/language/control/loop.c +++ b/src/language/control/loop.c @@ -18,21 +18,23 @@ 02110-1301, USA. */ #include -#include -#include + +#include "control-stack.h" #include -#include -#include #include -#include "control-stack.h" -#include +#include +#include +#include +#include +#include #include #include +#include +#include +#include #include #include -#include #include -#include #include "gettext.h" #define _(msgid) gettext (msgid) @@ -56,6 +58,7 @@ struct loop_trns { struct pool *pool; + struct dataset *ds; /* Iteration limit. */ int max_pass_count; /* Maximum number of passes (-1=unlimited). */ @@ -77,12 +80,13 @@ struct loop_trns 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 *); @@ -91,13 +95,13 @@ 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")) @@ -109,19 +113,20 @@ cmd_loop (void) /* 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; @@ -129,6 +134,8 @@ cmd_end_loop (void) loop = ctl_stack_top (&loop_class); if (loop == NULL) return CMD_CASCADING_FAILURE; + + assert (loop->ds == ds); /* Parse syntax. */ if (lex_match_id ("IF")) @@ -141,18 +148,18 @@ cmd_end_loop (void) 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 (); } @@ -164,8 +171,8 @@ close_loop (void *loop_) { 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. */ @@ -182,7 +189,7 @@ close_loop (void *loop_) 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; } @@ -203,7 +210,7 @@ parse_index_clause (struct loop_trns *loop, char index_var_name[]) 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; @@ -222,7 +229,7 @@ parse_index_clause (struct loop_trns *loop, char index_var_name[]) 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; } @@ -239,7 +246,7 @@ parse_index_clause (struct loop_trns *loop, char index_var_name[]) /* 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; @@ -247,18 +254,31 @@ create_loop_trns (void) 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_; @@ -310,7 +330,7 @@ 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, int case_num UNUSED) +end_loop_trns_proc (void *loop_, struct ccase *c, casenumber case_num UNUSED) { struct loop_trns *loop = loop_; @@ -348,7 +368,7 @@ end_loop_trns_proc (void *loop_, struct ccase *c, int case_num UNUSED) /* 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_; @@ -356,7 +376,7 @@ break_trns_proc (void *loop_, struct ccase *c UNUSED, int case_num UNUSED) } /* LOOP control structure class definition. */ -static struct ctl_class loop_class = +static const struct ctl_class loop_class = { "LOOP", "END LOOP",