X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Floop.c;h=b2685cfa201639c87eb86e86fc679902de174363;hb=9b4b94c6d3b5fd98bf396e23d015380b87d2d296;hp=424e5aabaf6aba050e536cadc7472b067924e2d7;hpb=18febf84744dc7ab4248542c2f88d91c01ef3fa1;p=pspp-builds.git diff --git a/src/loop.c b/src/loop.c index 424e5aab..b2685cfa 100644 --- a/src/loop.c +++ b/src/loop.c @@ -18,21 +18,20 @@ 02111-1307, USA. */ #include -#include +#include "error.h" #include "alloc.h" -#include "approx.h" #include "command.h" #include "do-ifP.h" #include "error.h" #include "expr.h" #include "lexer.h" +#include "misc.h" #include "settings.h" #include "str.h" #include "var.h" #include "debug-print.h" -/* *INDENT-OFF* */ /* LOOP strategy: Each loop causes 3 different transformations to be output. The @@ -43,42 +42,40 @@ transformation to -1. This ensures that the pass number is set to -1 every time the loop is encountered, before the first iteration. - The second transformation increments the pass number. If there is - no indexing or test clause on either LOOP or END LOOP, then the - pass number is checked against MXLOOPS and control may pass out of - the loop; otherwise the indexing or test clause(s) on LOOP are - checked, and again control may pass out of the loop. + The second transformation increments the pass number. If + there is no indexing or test clause on either LOOP or END + LOOP, then the pass number is checked against MXLOOPS and + control may pass out of the loop. Otherwise the indexing or + test clause(s) on LOOP are checked, and again control may pass + out of the loop. - After the second transformation the body of the loop is executed. + After the second transformation the body of the loop is + executed. The last transformation checks the test clause if present and - either jumps back up to the second transformation or terminates the - loop. - - Flow of control: (The characters ^V<> represents arrows.) - - 1. LOOP (sets pass # to -1) - V - V - >>2. LOOP (increment pass number) - ^ (test optional indexing clause) - ^ (test optional IF clause) - ^ if we need another trip if we're done with the loop>>V - ^ V V - ^ V V - ^ *. execute loop body V - ^ . V - ^ . (any number of transformations) V - ^ . V - ^ V - ^ 3. END LOOP (test optional IF clause) V - ^<<<>V - V - V - *. transformations after loop body<<<<<<<<<<<<<<<<<<<<<<<<<<< + either jumps back up to the second transformation or + terminates the loop. + + Flow of control: + + 1. LOOP. Sets pass number to -1 and continues to next + transformation. + + 2. LOOP. Increments pass number. Tests optional indexing + clause and optional IF clause. If we're done with the + loop, we jump to the transformation just after LOOP + transformation 3. + Otherwise, we continue through the transformations in the + loop body. + + 3. END LOOP. We test the optional IF clause. If we need to + make another pass through the loop, we jump to LOOP + transformation 2. + + Otherwise, we continue with the transformation jump after + the loop. */ -/* *INDENT-ON* */ /* Types of limits on loop execution. */ enum @@ -140,13 +137,9 @@ static struct loop_3_trns *thr; static int internal_cmd_loop (void); static int internal_cmd_end_loop (void); -static int break_trns_proc (struct trns_header *, struct ccase *); -static int loop_1_trns_proc (struct trns_header *, struct ccase *); -static void loop_1_trns_free (struct trns_header *); -static int loop_2_trns_proc (struct trns_header *, struct ccase *); -static void loop_2_trns_free (struct trns_header *); -static int loop_3_trns_proc (struct trns_header *, struct ccase *); -static void loop_3_trns_free (struct trns_header *); +static trns_proc_func break_trns_proc; +static trns_proc_func loop_1_trns_proc, loop_2_trns_proc, loop_3_trns_proc; +static trns_free_func loop_1_trns_free, loop_2_trns_free, loop_3_trns_free; static void pop_ctl_stack (void); /* LOOP. */ @@ -173,8 +166,6 @@ internal_cmd_loop (void) /* Name of indexing variable if applicable. */ char name[9]; - lex_match_id ("LOOP"); - /* Create and initialize transformations to facilitate error-handling. */ two = xmalloc (sizeof *two); @@ -207,7 +198,7 @@ internal_cmd_loop (void) assert (token == '='); lex_get (); - one->init = expr_parse (PXP_NUMERIC); + one->init = expr_parse (EXPR_NUMERIC); if (!one->init) return 0; @@ -216,7 +207,7 @@ internal_cmd_loop (void) expr_free (one->init); return 0; } - one->term = expr_parse (PXP_NUMERIC); + one->term = expr_parse (EXPR_NUMERIC); if (!one->term) { expr_free (one->init); @@ -225,7 +216,7 @@ internal_cmd_loop (void) if (lex_match (T_BY)) { - one->incr = expr_parse (PXP_NUMERIC); + one->incr = expr_parse (EXPR_NUMERIC); if (!one->incr) return 0; } @@ -238,7 +229,7 @@ internal_cmd_loop (void) { two->flags |= LPC_COND; - two->cond = expr_parse (PXP_BOOLEAN); + two->cond = expr_parse (EXPR_BOOLEAN); if (!two->cond) return 0; } @@ -322,7 +313,7 @@ internal_cmd_end_loop (void) /* Parse the expression if any. */ if (lex_match_id ("IF")) { - thr->cond = expr_parse (PXP_BOOLEAN); + thr->cond = expr_parse (EXPR_BOOLEAN); if (!thr->cond) return 0; } @@ -349,7 +340,8 @@ internal_cmd_end_loop (void) /* Performs transformation 1. */ static int -loop_1_trns_proc (struct trns_header * trns, struct ccase * c) +loop_1_trns_proc (struct trns_header * trns, struct ccase * c, + int case_num) { struct loop_1_trns *one = (struct loop_1_trns *) trns; struct loop_2_trns *two = one->two; @@ -359,20 +351,19 @@ loop_1_trns_proc (struct trns_header * trns, struct ccase * c) { union value t1, t2, t3; - expr_evaluate (one->init, c, &t1); + expr_evaluate (one->init, c, case_num, &t1); if (one->incr) - expr_evaluate (one->incr, c, &t2); + expr_evaluate (one->incr, c, case_num, &t2); else t2.f = 1.0; - expr_evaluate (one->term, c, &t3); + expr_evaluate (one->term, c, case_num, &t3); /* Even if the loop is never entered, force the index variable to assume the initial value. */ c->data[two->index->fv].f = t1.f; /* Throw out various pathological cases. */ - if (!finite (t1.f) || !finite (t2.f) || !finite (t3.f) - || approx_eq (t2.f, 0.0)) + if (!finite (t1.f) || !finite (t2.f) || !finite (t3.f) || t2.f == 0.0) return two->loop_term; debug_printf (("LOOP %s=%g TO %g BY %g.\n", two->index->name, t1.f, t3.f, t2.f)); @@ -382,7 +373,7 @@ loop_1_trns_proc (struct trns_header * trns, struct ccase * c) two->flags &= ~LPC_RINDEX; /* incr>0 but init>term */ - if (approx_gt (t1.f, t3.f)) + if (t1.f > t3.f) return two->loop_term; } else @@ -391,7 +382,7 @@ loop_1_trns_proc (struct trns_header * trns, struct ccase * c) two->flags |= LPC_RINDEX; /* incr<0 but initloop_term; } @@ -416,7 +407,8 @@ loop_1_trns_free (struct trns_header * trns) /* Performs transformation 2. */ static int -loop_2_trns_proc (struct trns_header * trns, struct ccase * c) +loop_2_trns_proc (struct trns_header * trns, struct ccase * c, + int case_num UNUSED) { struct loop_2_trns *two = (struct loop_2_trns *) trns; @@ -424,7 +416,7 @@ loop_2_trns_proc (struct trns_header * trns, struct ccase * c) if (two->flags == 0) { two->pass++; - if (two->pass > set_mxloops) + if (two->pass > get_mxloops() ) return two->loop_term; } @@ -432,7 +424,7 @@ loop_2_trns_proc (struct trns_header * trns, struct ccase * c) if (two->flags & LPC_RINDEX) { /* Test if we're at the end of the looping. */ - if (approx_lt (two->curr, two->term)) + if (two->curr < two->term) return two->loop_term; /* Set the current value into the case. */ @@ -445,7 +437,7 @@ loop_2_trns_proc (struct trns_header * trns, struct ccase * c) else if (two->flags & LPC_INDEX) { /* Test if we're at the end of the looping. */ - if (approx_gt (two->curr, two->term)) + if (two->curr > two->term) return two->loop_term; /* Set the current value into the case. */ @@ -457,7 +449,7 @@ loop_2_trns_proc (struct trns_header * trns, struct ccase * c) /* Conditional clause limiter. */ if ((two->flags & LPC_COND) - && expr_evaluate (two->cond, c, NULL) != 1.0) + && expr_evaluate (two->cond, c, case_num, NULL) != 1.0) return two->loop_term; return -1; @@ -474,13 +466,14 @@ loop_2_trns_free (struct trns_header * trns) /* Performs transformation 3. */ static int -loop_3_trns_proc (struct trns_header * trns, struct ccase * c) +loop_3_trns_proc (struct trns_header * trns, struct ccase * c, + int case_num) { struct loop_3_trns *thr = (struct loop_3_trns *) trns; /* Note that it breaks out of the loop if the expression is true *or missing*. This is conformant. */ - if (thr->cond && expr_evaluate (two->cond, c, NULL) != 0.0) + if (thr->cond && expr_evaluate (two->cond, c, case_num, NULL) != 0.0) return -1; return thr->loop_start; @@ -507,8 +500,6 @@ cmd_break (void) /* New transformation. */ struct break_trns *t; - lex_match_id ("BREAK"); - for (loop = ctl_stack; loop; loop = loop->down) if (loop->type == CST_LOOP) break; @@ -533,7 +524,8 @@ cmd_break (void) } static int -break_trns_proc (struct trns_header * trns, struct ccase * c UNUSED) +break_trns_proc (struct trns_header * trns, struct ccase * c UNUSED, + int case_num UNUSED) { return ((struct break_trns *) trns)->loop_term; }