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=a4d0e49ca042ab9f628e014f49df0041d22bfa1a;hpb=dcf9b154cbcaa35c3d8459a201b77eec8bcb30bd;p=pspp diff --git a/src/language/control/loop.c b/src/language/control/loop.c index a4d0e49ca0..5c22f3ca57 100644 --- a/src/language/control/loop.c +++ b/src/language/control/loop.c @@ -18,20 +18,23 @@ 02110-1301, USA. */ #include -#include "message.h" -#include "alloc.h" -#include "case.h" -#include "command.h" -#include "dictionary.h" + #include "control-stack.h" -#include "message.h" -#include "expressions/public.h" -#include "lexer.h" -#include "misc.h" -#include "pool.h" -#include "settings.h" -#include "str.h" -#include "variable.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "gettext.h" #define _(msgid) gettext (msgid) @@ -55,6 +58,7 @@ struct loop_trns { struct pool *pool; + struct dataset *ds; /* Iteration limit. */ int max_pass_count; /* Maximum number of passes (-1=unlimited). */ @@ -76,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 *); @@ -90,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")) @@ -108,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; @@ -128,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")) @@ -140,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 (); } @@ -163,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. */ @@ -181,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; } @@ -202,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; @@ -221,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; } @@ -238,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; @@ -246,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_; @@ -309,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_; @@ -347,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_; @@ -355,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",