From: Ben Pfaff Date: Sat, 18 May 2013 22:48:44 +0000 (-0700) Subject: work on making transformations use relative return values X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pspp;a=commitdiff_plain;h=765362af497f7b1f9c9a5ef387d40eac474fbbe3 work on making transformations use relative return values --- diff --git a/src/data/caseproto.c b/src/data/caseproto.c index 2b2fcb408d..c20806051b 100644 --- a/src/data/caseproto.c +++ b/src/data/caseproto.c @@ -55,6 +55,7 @@ caseproto_create (void) proto->ref_cnt = 1; proto->long_strings = NULL; proto->n_long_strings = 0; + proto->pxd = NULL; proto->n_widths = 0; proto->allocated_widths = N_ALLOCATE; return proto; diff --git a/src/data/transformations.c b/src/data/transformations.c index 700ed85e40..46241c8fc2 100644 --- a/src/data/transformations.c +++ b/src/data/transformations.c @@ -175,19 +175,34 @@ enum trns_result trns_chain_execute (const struct trns_chain *chain, enum trns_result start, struct ccase **c, casenumber case_nr) { - size_t i; + int i; assert (chain->finalized); for (i = start < 0 ? 0 : start; i < chain->trns_cnt; ) { struct transformation *trns = &chain->trns[i]; - int retval = trns->execute (trns->aux, c, case_nr); - if (retval == TRNS_CONTINUE) - i++; - else if (retval >= 0) - i = retval + trns->idx_ofs; - else - return retval == TRNS_END_CASE ? i + 1 : retval; + int retval; + + retval = trns->execute (trns->aux, c, case_nr); + switch (retval) + { + case TRNS_CONTINUE: + i++; + break; + + case TRNS_END_CASE: + return i + 1; + + case TRNS_DROP_CASE: + case TRNS_ERROR: + case TRNS_END_FILE: + return retval; + + default: + i += retval; + assert (i <= chain->trns_cnt); + break; + } } return TRNS_CONTINUE; diff --git a/src/data/transformations.h b/src/data/transformations.h index 5e1488323b..66ddb4e0fb 100644 --- a/src/data/transformations.h +++ b/src/data/transformations.h @@ -17,6 +17,7 @@ #ifndef TRANSFORMATIONS_H #define TRANSFORMATIONS_H 1 +#include #include #include #include "data/case.h" @@ -24,16 +25,26 @@ /* trns_proc_func return values. */ enum trns_result { - TRNS_CONTINUE = -1, /* Continue to next transformation. */ - TRNS_DROP_CASE = -2, /* Drop this case. */ - TRNS_ERROR = -3, /* A serious error, so stop the procedure. */ - TRNS_END_CASE = -4, /* Skip to next case. INPUT PROGRAM only. */ - TRNS_END_FILE = -5 /* End of input. INPUT PROGRAM only. */ + TRNS_CONTINUE = INT_MIN, /* Continue to next transformation. */ + TRNS_DROP_CASE, /* Drop this case. */ + TRNS_ERROR, /* A serious error, so stop the procedure. */ + TRNS_END_CASE, /* Skip to next case. INPUT PROGRAM only. */ + TRNS_END_FILE /* End of input. INPUT PROGRAM only. */ }; struct ccase; typedef int trns_proc_func (void *, struct ccase **, casenumber); typedef bool trns_free_func (void *); +typedef struct pxd_object *trns_save_func (void *, struct pxd *); +typedef void *trns_load_func (struct pxd_object *, const struct pxd *); + +#if 0 +struct trns_class + { + int (*execute) (struct trns_class *, struct ccase **, casenumber); + bool (*destroy) (struct ccase *); + }; +#endif /* Transformation chains. */ 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 = { diff --git a/src/language/control/loop.c b/src/language/control/loop.c index 34c6a1d363..2505d2ef29 100644 --- a/src/language/control/loop.c +++ b/src/language/control/loop.c @@ -326,10 +326,10 @@ loop_trns_proc (void *loop_, struct ccase **c, casenumber case_num) && expr_evaluate_num (loop->loop_condition, *c, case_num) != 1.0) goto zero_pass; - return loop->past_LOOP_index; + return TRNS_CONTINUE; zero_pass: - return loop->past_END_LOOP_index; + return loop->past_END_LOOP_index - loop->past_LOOP_index + 1; } /* Frees LOOP. */ @@ -371,10 +371,10 @@ end_loop_trns_proc (void *loop_, struct ccase **c, casenumber case_num UNUSED) && expr_evaluate_num (loop->loop_condition, *c, case_num) != 1.0) goto break_out; - return loop->past_LOOP_index; + return loop->past_LOOP_index - loop->past_END_LOOP_index; break_out: - return loop->past_END_LOOP_index; + return TRNS_CONTINUE; } /* Executes BREAK. */ diff --git a/tests/automake.mk b/tests/automake.mk index 4cb4283e9d..2c7a0d0650 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -47,7 +47,7 @@ tests_data_datasheet_test_CFLAGS = $(AM_CFLAGS) tests_data_sack_SOURCES = \ tests/data/sack.c -tests_data_sack_LDADD = src/libpspp-core.la +tests_data_sack_LDADD = src/libpspp-core.la src/libpspp-core.la tests_data_sack_CFLAGS = $(AM_CFLAGS) tests_libpspp_line_reader_test_SOURCES = tests/libpspp/line-reader-test.c diff --git a/tests/libpspp/hmapx-test.c b/tests/libpspp/hmapx-test.c index 93df1bfe53..89435ddb2e 100644 --- a/tests/libpspp/hmapx-test.c +++ b/tests/libpspp/hmapx-test.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007, 2008, 2009, 2010, 2015 Free Software Foundation, Inc. + Copyright (C) 2007, 2008, 2009, 2010, 2013, 2015 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by