X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fcontrol%2Floop.c;h=01aad6fdaad36ae9d414c9b30127d9fdb8b4e5d1;hb=ade89522516fe8cc47299d8da6e28e129d96de94;hp=da1dc2fc49dfeda732b6f8e599ffe3d14fd92496;hpb=a19b858e0ac3c69e4a28c0ca6d8674427268a863;p=pspp-builds.git diff --git a/src/language/control/loop.c b/src/language/control/loop.c index da1dc2fc..01aad6fd 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,51 +80,53 @@ 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 bool parse_if_clause (struct loop_trns *, struct expression **); -static bool parse_index_clause (struct loop_trns *, char index_var_name[]); +static struct loop_trns *create_loop_trns (struct dataset *); +static bool parse_if_clause (struct lexer *, struct loop_trns *, struct expression **); +static bool parse_index_clause (struct lexer *, struct loop_trns *, char index_var_name[]); static void close_loop (void *); /* LOOP. */ /* Parses LOOP. */ int -cmd_loop (void) +cmd_loop (struct lexer *lexer, struct dataset *ds) { struct loop_trns *loop; char index_var_name[LONG_NAME_LEN + 1]; bool ok = true; - loop = create_loop_trns (); - while (token != '.' && ok) + loop = create_loop_trns (ds); + while (lex_token (lexer) != '.' && ok) { - if (lex_match_id ("IF")) - ok = parse_if_clause (loop, &loop->loop_condition); + if (lex_match_id (lexer, "IF")) + ok = parse_if_clause (lexer, loop, &loop->loop_condition); else - ok = parse_index_clause (loop, index_var_name); + ok = parse_index_clause (lexer, loop, index_var_name); } /* 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 lexer *lexer, struct dataset *ds) { struct loop_trns *loop; bool ok = true; @@ -129,32 +134,34 @@ 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")) - ok = parse_if_clause (loop, &loop->end_loop_condition); + if (lex_match_id (lexer, "IF")) + ok = parse_if_clause (lexer, loop, &loop->end_loop_condition); if (ok) - ok = lex_end_of_command () == CMD_SUCCESS; + ok = lex_end_of_command (lexer) == CMD_SUCCESS; if (!ok) loop->max_pass_count = 0; 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 lexer *lexer, 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 (); + return lex_end_of_command (lexer); } /* Closes a LOOP construct by emitting the END LOOP @@ -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. */ @@ -180,9 +187,10 @@ close_loop (void *loop_) resulting expression to *CONDITION. Returns true if successful, false on failure. */ static bool -parse_if_clause (struct loop_trns *loop, struct expression **condition) +parse_if_clause (struct lexer *lexer, + struct loop_trns *loop, struct expression **condition) { - *condition = expr_parse_pool (loop->pool, default_dict, EXPR_BOOLEAN); + *condition = expr_parse_pool (lexer, loop->pool, loop->ds, EXPR_BOOLEAN); return *condition != NULL; } @@ -190,29 +198,30 @@ parse_if_clause (struct loop_trns *loop, struct expression **condition) Stores the index variable's name in INDEX_VAR_NAME[]. Returns true if successful, false on failure. */ static bool -parse_index_clause (struct loop_trns *loop, char index_var_name[]) +parse_index_clause (struct lexer *lexer, struct loop_trns *loop, char index_var_name[]) { - if (token != T_ID) + if (lex_token (lexer) != T_ID) { - lex_error (NULL); + lex_error (lexer, NULL); return false; } - strcpy (index_var_name, tokid); - lex_get (); + strcpy (index_var_name, lex_tokid (lexer)); + lex_get (lexer); - if (!lex_force_match ('=')) + if (!lex_force_match (lexer, '=')) return false; - loop->first_expr = expr_parse_pool (loop->pool, default_dict, EXPR_NUMBER); + loop->first_expr = expr_parse_pool (lexer, loop->pool, + loop->ds, EXPR_NUMBER); if (loop->first_expr == NULL) return false; for (;;) { struct expression **e; - if (lex_match (T_TO)) + if (lex_match (lexer, T_TO)) e = &loop->last_expr; - else if (lex_match (T_BY)) + else if (lex_match (lexer, T_BY)) e = &loop->by_expr; else break; @@ -222,13 +231,13 @@ 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 (lexer, loop->pool, loop->ds, EXPR_NUMBER); if (*e == NULL) return false; } if (loop->last_expr == NULL) { - lex_sbc_missing ("TO"); + lex_sbc_missing (lexer, "TO"); return false; } if (loop->by_expr == NULL) @@ -239,7 +248,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 +256,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 +332,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 +370,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 +378,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",