X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fcontrol%2Fdo-if.c;fp=src%2Flanguage%2Fcontrol%2Fdo-if.c;h=f5ebe799e34c0eb091513889d8123f3215431fa7;hb=765362af497f7b1f9c9a5ef387d40eac474fbbe3;hp=ea7056709115da24c396d84114de751a982345d9;hpb=cfe28ef151771c04be56d459c58d818f6c43f5e1;p=pspp diff --git a/src/language/control/do-if.c b/src/language/control/do-if.c index ea70567091..f5ebe799e3 100644 --- a/src/language/control/do-if.c +++ b/src/language/control/do-if.c @@ -76,9 +76,17 @@ struct do_if_trns struct dataset *ds; /* The dataset */ struct clause *clauses; /* Clauses. */ size_t clause_cnt; /* Number of clauses. */ + int DO_IF_index; /* DO IF transformation. */ int past_END_IF_index; /* Transformation just past last clause. */ }; +/* Jumps past the END IF. */ +struct end_if_trns + { + struct do_if_trns *do_if; + int index; + }; + static const struct ctl_class do_if_class; static int parse_clause (struct lexer *, struct do_if_trns *, struct dataset *ds); @@ -89,8 +97,8 @@ static bool has_else (struct do_if_trns *); static bool must_not_have_else (struct do_if_trns *); static void close_do_if (void *do_if); -static trns_proc_func do_if_trns_proc, break_trns_proc; -static trns_free_func do_if_trns_free; +static trns_proc_func do_if_trns_proc, end_if_trns_proc; +static trns_free_func do_if_trns_free, end_if_trns_free; /* Parse DO IF. */ int @@ -100,6 +108,7 @@ cmd_do_if (struct lexer *lexer, struct dataset *ds) do_if->clauses = NULL; do_if->clause_cnt = 0; do_if->ds = ds; + do_if->DO_IF_index = next_transformation (ds); ctl_stack_push (&do_if_class, do_if); add_transformation (ds, do_if_trns_proc, do_if_trns_free, do_if); @@ -214,7 +223,15 @@ add_clause (struct do_if_trns *do_if, struct expression *condition) struct clause *clause; if (do_if->clause_cnt > 0) - add_transformation (do_if->ds, break_trns_proc, NULL, do_if); + { + struct end_if_trns *end_if; + + end_if = xmalloc (sizeof *end_if); + end_if->do_if = do_if; + end_if->index = next_transformation (do_if->ds); + add_transformation (do_if->ds, + end_if_trns_proc, end_if_trns_free, end_if); + } do_if->clauses = xnrealloc (do_if->clauses, do_if->clause_cnt + 1, sizeof *do_if->clauses); @@ -239,12 +256,12 @@ do_if_trns_proc (void *do_if_, struct ccase **c, casenumber case_num UNUSED) { double boolean = expr_evaluate_num (clause->condition, *c, case_num); if (boolean == 1.0) - return clause->target_index; + return clause->target_index - do_if->DO_IF_index; else if (boolean == SYSMIS) - return do_if->past_END_IF_index; + return do_if->past_END_IF_index - do_if->DO_IF_index; } else - return clause->target_index; + return clause->target_index - do_if->DO_IF_index; } return do_if->past_END_IF_index; } @@ -266,14 +283,23 @@ do_if_trns_free (void *do_if_) /* Breaks out of a DO IF construct. */ static int -break_trns_proc (void *do_if_, struct ccase **c UNUSED, +end_if_trns_proc (void *end_if_, struct ccase **c UNUSED, casenumber case_num UNUSED) { - struct do_if_trns *do_if = do_if_; + struct end_if_trns *end_if = end_if_; - return do_if->past_END_IF_index; + return end_if->do_if->past_END_IF_index - end_if->index; } +/* Frees an END IF transformation. */ +static bool +end_if_trns_free (void *end_if_) +{ + struct end_if_trns *end_if = end_if_; + + free (end_if); + return true; +} /* DO IF control structure class definition. */ static const struct ctl_class do_if_class = {