for (size_t i = 0; i < chain->n; i++)
{
const struct transformation *trns = &chain->xforms[i];
- printf ("%s\n", trns->class->name);
int retval = trns->class->execute (trns->aux, c, case_nr);
if (retval != TRNS_CONTINUE)
return retval;
/* Command processing states. */
enum states
{
- S_INITIAL = 1 << 0, /* Allowed before active dataset defined. */
- S_DATA = 1 << 1, /* Allowed after active dataset defined. */
- S_INPUT_PROGRAM = 1 << 2, /* Allowed in INPUT PROGRAM. */
- S_FILE_TYPE = 1 << 3, /* Allowed in FILE TYPE. */
- S_NESTED = 1 << 4, /* Allowed in LOOP and DO IF. */
-
- S_ANY = S_INITIAL | S_DATA | S_INPUT_PROGRAM | S_FILE_TYPE | S_NESTED,
+ S_INITIAL = 1 << CMD_STATE_INITIAL,
+ S_DATA = 1 << CMD_STATE_DATA,
+ S_INPUT_PROGRAM = 1 << CMD_STATE_INPUT_PROGRAM,
+ S_FILE_TYPE = 1 << CMD_STATE_FILE_TYPE,
+ S_NESTED_DATA = 1 << CMD_STATE_NESTED_DATA,
+ S_NESTED_INPUT_PROGRAM = 1 << CMD_STATE_NESTED_INPUT_PROGRAM,
+
+ S_NESTED_ANY = S_NESTED_DATA | S_NESTED_INPUT_PROGRAM,
+ S_ANY = S_INITIAL | S_DATA | S_INPUT_PROGRAM | S_FILE_TYPE | S_NESTED_ANY,
};
/* Other command requirements. */
static bool
in_correct_state (const struct command *command, enum cmd_state state)
{
- switch (state)
- {
- case CMD_STATE_INITIAL:
- return command->states & S_INITIAL;
-
- case CMD_STATE_DATA:
- return command->states & S_DATA;
-
- case CMD_STATE_INPUT_PROGRAM:
- return command->states & S_INPUT_PROGRAM;
-
- case CMD_STATE_FILE_TYPE:
- return command->states & S_FILE_TYPE;
-
- case CMD_STATE_NESTED:
- return command->states & S_NESTED;
-
- default:
- NOT_REACHED ();
- }
+ return command->states & (1 << state);
}
/* Emits an appropriate error message for trying to invoke
msg (SE, _("%s is not allowed inside %s."), command->name, "FILE TYPE");
break;
- case CMD_STATE_NESTED:
- msg (SE, _("%s is not allowed inside DO IF or LOOP."), command->name);
+ case CMD_STATE_NESTED_DATA:
+ case CMD_STATE_NESTED_INPUT_PROGRAM:
+ switch ((int) command->states & S_NESTED_ANY)
+ {
+ case 0:
+ msg (SE, _("%s is not allowed inside DO IF or LOOP."), command->name);
+ break;
+
+ case S_NESTED_DATA:
+ msg (SE, _("In INPUT PROGRAM, "
+ "%s is not allowed inside DO IF or LOOP."), command->name);
+ break;
+
+ default:
+ NOT_REACHED ();
+ }
break;
}
}
DEF_CMD (S_INITIAL | S_DATA, 0, "DATASET DISPLAY", cmd_dataset_display)
/* Utilities that may appear after active file definition or within INPUT PROGRAM. */
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "ADD VALUE LABELS", cmd_add_value_labels)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "ADD DOCUMENT", cmd_add_documents)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "APPLY DICTIONARY", cmd_apply_dictionary)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "DATAFILE ATTRIBUTE", cmd_datafile_attribute)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "DISPLAY", cmd_display)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "DOCUMENT", cmd_document)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "DROP DOCUMENTS", cmd_drop_documents)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "FORMATS", cmd_formats)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "LEAVE", cmd_leave)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "MISSING VALUES", cmd_missing_values)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "MRSETS", cmd_mrsets)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "PRINT FORMATS", cmd_print_formats)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "SPLIT FILE", cmd_split_file)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "VALUE LABELS", cmd_value_labels)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "VARIABLE ALIGNMENT", cmd_variable_alignment)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "VARIABLE ATTRIBUTE", cmd_variable_attribute)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "VARIABLE LABELS", cmd_variable_labels)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "VARIABLE LEVEL", cmd_variable_level)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "VARIABLE ROLE", cmd_variable_role)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "VARIABLE WIDTH", cmd_variable_width)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "VECTOR", cmd_vector)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "WEIGHT", cmd_weight)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "WRITE FORMATS", cmd_write_formats)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "ADD VALUE LABELS", cmd_add_value_labels)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "ADD DOCUMENT", cmd_add_documents)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "APPLY DICTIONARY", cmd_apply_dictionary)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "DATAFILE ATTRIBUTE", cmd_datafile_attribute)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "DISPLAY", cmd_display)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "DOCUMENT", cmd_document)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "DROP DOCUMENTS", cmd_drop_documents)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "FORMATS", cmd_formats)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "LEAVE", cmd_leave)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "MISSING VALUES", cmd_missing_values)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "MRSETS", cmd_mrsets)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "PRINT FORMATS", cmd_print_formats)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "SPLIT FILE", cmd_split_file)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "VALUE LABELS", cmd_value_labels)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "VARIABLE ALIGNMENT", cmd_variable_alignment)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "VARIABLE ATTRIBUTE", cmd_variable_attribute)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "VARIABLE LABELS", cmd_variable_labels)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "VARIABLE LEVEL", cmd_variable_level)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "VARIABLE ROLE", cmd_variable_role)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "VARIABLE WIDTH", cmd_variable_width)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "VECTOR", cmd_vector)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "WEIGHT", cmd_weight)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "WRITE FORMATS", cmd_write_formats)
/* Transformations. */
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "BREAK", cmd_break)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "COMPUTE", cmd_compute)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "DO IF", cmd_do_if)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "IF", cmd_if)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "LOOP", cmd_loop)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "NUMERIC", cmd_numeric)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "PRINT EJECT", cmd_print_eject)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "PRINT SPACE", cmd_print_space)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "PRINT", cmd_print)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "RECODE", cmd_recode)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "SELECT IF", cmd_select_if)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "STRING", cmd_string)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "WRITE", cmd_write)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, F_ENHANCED, "XEXPORT", cmd_xexport)
-DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED, 0, "XSAVE", cmd_xsave)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "BREAK", cmd_break)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "COMPUTE", cmd_compute)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "DO IF", cmd_do_if)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "IF", cmd_if)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "LOOP", cmd_loop)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "NUMERIC", cmd_numeric)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "PRINT EJECT", cmd_print_eject)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "PRINT SPACE", cmd_print_space)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "PRINT", cmd_print)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "RECODE", cmd_recode)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "STRING", cmd_string)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "WRITE", cmd_write)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, F_ENHANCED, "XEXPORT", cmd_xexport)
+DEF_CMD (S_DATA | S_INPUT_PROGRAM | S_NESTED_ANY, 0, "XSAVE", cmd_xsave)
+
+/* Restricted transformations. */
+DEF_CMD (S_DATA | S_NESTED_DATA, 0, "SELECT IF", cmd_select_if)
/* Commands that may appear after active dataset definition. */
DEF_CMD (S_DATA, 0, "AGGREGATE", cmd_aggregate)
DEF_CMD (S_DATA, 0, "USE", cmd_use)
/* Commands valid only with INPUT PROGRAM. */
-DEF_CMD (S_INPUT_PROGRAM | S_NESTED, 0, "END CASE", cmd_end_case)
-DEF_CMD (S_INPUT_PROGRAM | S_NESTED, 0, "END FILE", cmd_end_file)
-DEF_CMD (S_INPUT_PROGRAM | S_NESTED, 0, "REREAD", cmd_reread)
+DEF_CMD (S_INPUT_PROGRAM | S_NESTED_INPUT_PROGRAM, 0, "END CASE", cmd_end_case)
+DEF_CMD (S_INPUT_PROGRAM | S_NESTED_INPUT_PROGRAM, 0, "END FILE", cmd_end_file)
+DEF_CMD (S_INPUT_PROGRAM | S_NESTED_INPUT_PROGRAM, 0, "REREAD", cmd_reread)
/* Commands for testing PSPP. */
DEF_CMD (S_ANY, F_TESTING, "DEBUG EXPAND", cmd_debug_expand)
CMD_STATE_DATA, /* Active dataset has been defined. */
CMD_STATE_INPUT_PROGRAM, /* Inside INPUT PROGRAM. */
CMD_STATE_FILE_TYPE, /* Inside FILE TYPE. */
- CMD_STATE_NESTED, /* Inside LOOP or DO IF. */
+
+ /* Inside LOOP or DO IF... */
+ CMD_STATE_NESTED_DATA, /* ...in CMD_STATE_DATA. */
+ CMD_STATE_NESTED_INPUT_PROGRAM, /* ...in CMD_STATE_INPUT_PROGRAM. */
};
struct dataset;
#include "data/dataset.h"
#include "data/transformations.h"
#include "language/command.h"
+#include "language/data-io/inpt-pgm.h"
#include "language/expressions/public.h"
#include "language/lexer/lexer.h"
#include "libpspp/compiler.h"
{
struct clause *clauses; /* Clauses. */
size_t n_clauses; /* Number of clauses. */
+
+ const struct trns_chain *resume;
+ size_t ofs;
};
static const struct trns_class do_if_trns_class;
start_clause (lexer, ds, false, do_if, &allocated_clauses, &ok);
}
else
- cmd_parse_in_state (lexer, ds, CMD_STATE_NESTED);
+ cmd_parse_in_state (lexer, ds,
+ (in_input_program ()
+ ? CMD_STATE_NESTED_INPUT_PROGRAM
+ : CMD_STATE_NESTED_DATA));
}
finish_clause (ds, do_if);
return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE;
}
-/* DO IF transformation procedure.
- Checks each clause and jumps to the appropriate
- transformation. */
+static const struct trns_chain *
+do_if_find_clause (const struct do_if_trns *do_if,
+ struct ccase *c, casenumber case_num)
+{
+ for (size_t i = 0; i < do_if->n_clauses; i++)
+ {
+ const struct clause *clause = &do_if->clauses[i];
+ if (!clause->condition)
+ return &clause->xforms;
+
+ double boolean = expr_evaluate_num (clause->condition, c, case_num);
+ if (boolean != 0.0)
+ return boolean == SYSMIS ? NULL : &clause->xforms;
+ }
+ return NULL;
+}
+
static enum trns_result
do_if_trns_proc (void *do_if_, struct ccase **c, casenumber case_num)
{
struct do_if_trns *do_if = do_if_;
- for (size_t i = 0; i < do_if->n_clauses; i++)
+ const struct trns_chain *chain;
+ size_t start;
+ if (do_if->resume)
{
- const struct clause *clause = &do_if->clauses[i];
- if (clause->condition != NULL)
+ chain = do_if->resume;
+ start = do_if->ofs;
+ do_if->resume = NULL;
+ do_if->ofs = 0;
+ }
+ else
+ {
+ chain = do_if_find_clause (do_if, *c, case_num);
+ if (!chain)
+ return TRNS_CONTINUE;
+ start = 0;
+ }
+
+ for (size_t i = start; i < chain->n; i++)
+ {
+ const struct transformation *trns = &chain->xforms[i];
+ enum trns_result r = trns->class->execute (trns->aux, c, case_num);
+ switch (r)
{
- double boolean = expr_evaluate_num (clause->condition, *c, case_num);
- if (boolean == 0.0)
- continue;
- else if (boolean == SYSMIS)
- return TRNS_CONTINUE;
- }
+ case TRNS_CONTINUE:
+ break;
- return trns_chain_execute (&clause->xforms, case_num, c);
+ case TRNS_BREAK:
+ case TRNS_DROP_CASE:
+ case TRNS_ERROR:
+ case TRNS_END_FILE:
+ return r;
+
+ case TRNS_END_CASE:
+ do_if->resume = chain;
+ do_if->ofs = i;
+ return r;
+ }
}
return TRNS_CONTINUE;
}
-/* Frees a DO IF transformation. */
static bool
do_if_trns_free (void *do_if_)
{
#include "data/transformations.h"
#include "data/variable.h"
#include "language/command.h"
+#include "language/data-io/inpt-pgm.h"
#include "language/expressions/public.h"
#include "language/lexer/lexer.h"
+#include "libpspp/assertion.h"
#include "libpspp/compiler.h"
#include "libpspp/message.h"
#include "libpspp/misc.h"
struct loop_trns
{
/* a=a TO b [BY c]. */
- struct variable *index_var; /* Index variable. */
- struct expression *first; /* Starting index. */
- struct expression *by; /* Index increment (or NULL). */
- struct expression *last; /* Terminal index. */
+ struct variable *index_var; /* Index variable. */
+ struct expression *first_expr; /* Starting index. */
+ struct expression *by_expr; /* Index increment (or NULL). */
+ struct expression *last_expr; /* Terminal index. */
/* IF condition for LOOP or END LOOP. */
struct expression *loop_condition;
/* Inner transformations. */
struct trns_chain xforms;
+
+ /* State. */
+ double cur, by, last; /* Index data. */
+ int iteration; /* For MXLOOPS. */
+ size_t resume_idx; /* For resuming after END CASE. */
};
static struct trns_class loop_trns_class;
cmd_loop (struct lexer *lexer, struct dataset *ds)
{
struct loop_trns *loop = xmalloc (sizeof *loop);
- *loop = (struct loop_trns) { .index_var = NULL };
+ *loop = (struct loop_trns) { .resume_idx = SIZE_MAX };
bool ok = true;
while (lex_token (lexer) != T_ENDCMD && ok)
break;
}
else
- cmd_parse_in_state (lexer, ds, CMD_STATE_NESTED);
+ cmd_parse_in_state (lexer, ds,
+ (in_input_program ()
+ ? CMD_STATE_NESTED_INPUT_PROGRAM
+ : CMD_STATE_NESTED_DATA));
}
in_loop--;
proc_pop_transformations (ds, &loop->xforms);
- printf ("%zu loop transvformations\n", loop->xforms.n);
add_transformation (ds, &loop_trns_class, loop);
if (!lex_force_match (lexer, T_EQUALS))
return false;
- loop->first = expr_parse (lexer, ds, VAL_NUMERIC);
- if (loop->first == NULL)
+ loop->first_expr = expr_parse (lexer, ds, VAL_NUMERIC);
+ if (loop->first_expr == NULL)
return false;
for (;;)
{
struct expression **e;
if (lex_match (lexer, T_TO))
- e = &loop->last;
+ e = &loop->last_expr;
else if (lex_match (lexer, T_BY))
- e = &loop->by;
+ e = &loop->by_expr;
else
break;
if (*e != NULL)
{
- lex_sbc_only_once (e == &loop->last ? "TO" : "BY");
+ lex_sbc_only_once (e == &loop->last_expr ? "TO" : "BY");
return false;
}
*e = expr_parse (lexer, ds, VAL_NUMERIC);
if (*e == NULL)
return false;
}
- if (loop->last == NULL)
+ if (loop->last_expr == NULL)
{
lex_sbc_missing ("TO");
return false;
{
struct loop_trns *loop = loop_;
- double cur, by, last;
+ size_t start_idx = loop->resume_idx;
+ loop->resume_idx = SIZE_MAX;
+ if (start_idx != SIZE_MAX)
+ goto resume;
+
if (loop->index_var)
{
/* Evaluate loop index expressions. */
- cur = expr_evaluate_num (loop->first, *c, case_num);
- by = loop->by ? expr_evaluate_num (loop->by, *c, case_num) : 1.0;
- last = expr_evaluate_num (loop->last, *c, case_num);
+ loop->cur = expr_evaluate_num (loop->first_expr, *c, case_num);
+ loop->by = (loop->by_expr
+ ? expr_evaluate_num (loop->by_expr, *c, case_num)
+ : 1.0);
+ loop->last = expr_evaluate_num (loop->last_expr, *c, case_num);
/* Even if the loop is never entered, set the index
variable to the initial value. */
*c = case_unshare (*c);
- *case_num_rw (*c, loop->index_var) = cur;
+ *case_num_rw (*c, loop->index_var) = loop->cur;
/* Throw out pathological cases. */
- if (!isfinite (cur) || !isfinite (by) || !isfinite (last)
- || by == 0.0
- || (by > 0.0 && cur > last)
- || (by < 0.0 && cur < last))
+ if (!isfinite (loop->cur)
+ || !isfinite (loop->by)
+ || !isfinite (loop->last)
+ || loop->by == 0.0
+ || (loop->by > 0.0 && loop->cur > loop->last)
+ || (loop->by < 0.0 && loop->cur < loop->last))
return TRNS_CONTINUE;
}
- else
- cur = by = last = 0.0;
- for (int i = 0; loop->index_var || i < settings_get_mxloops (); i++)
+ for (loop->iteration = 0;
+ loop->index_var || loop->iteration < settings_get_mxloops ();
+ loop->iteration++)
{
- printf ("loop %g %g %g\n", cur, by, last);
if (loop->loop_condition
&& expr_evaluate_num (loop->loop_condition, *c, case_num) != 1.0)
break;
- enum trns_result r = trns_chain_execute (&loop->xforms, case_num, c);
- if (r != TRNS_CONTINUE)
- return r == TRNS_BREAK ? TRNS_CONTINUE : r;
+ start_idx = 0;
+ resume:
+ for (size_t i = start_idx; i < loop->xforms.n; i++)
+ {
+ const struct transformation *trns = &loop->xforms.xforms[i];
+ enum trns_result r = trns->class->execute (trns->aux, c, case_num);
+ switch (r)
+ {
+ case TRNS_CONTINUE:
+ break;
+
+ case TRNS_BREAK:
+ return TRNS_CONTINUE;
+
+ case TRNS_END_CASE:
+ loop->resume_idx = i;
+ return TRNS_END_CASE;
+
+ case TRNS_ERROR:
+ case TRNS_END_FILE:
+ return r;
+
+ case TRNS_DROP_CASE:
+ NOT_REACHED ();
+ }
+ }
if (loop->end_loop_condition != NULL
&& expr_evaluate_num (loop->end_loop_condition, *c, case_num) != 0.0)
if (loop->index_var)
{
- cur += by;
- if (by > 0.0 ? cur > last : cur < last)
+ loop->cur += loop->by;
+ if (loop->by > 0.0 ? loop->cur > loop->last : loop->cur < loop->last)
break;
*c = case_unshare (*c);
- *case_num_rw (*c, loop->index_var) = cur;
+ *case_num_rw (*c, loop->index_var) = loop->cur;
}
}
return TRNS_CONTINUE;
{
struct loop_trns *loop = loop_;
- expr_free (loop->first);
- expr_free (loop->by);
- expr_free (loop->last);
+ expr_free (loop->first_expr);
+ expr_free (loop->by_expr);
+ expr_free (loop->last_expr);
expr_free (loop->loop_condition);
expr_free (loop->end_loop_condition);
static void
emit_END_CASE (struct dataset *ds)
{
- add_transformation (ds, &end_case_trns_class, NULL);
+ add_transformation (ds, &end_case_trns_class, xzalloc (sizeof (bool)));
}
int
struct ccase *c = case_create (inp->proto);
caseinit_init_vars (inp->init, c);
- printf ("%s:%d\n", __FILE__, __LINE__);
for (size_t i = inp->idx < inp->xforms.n ? inp->idx : 0; ; i++)
{
- printf ("%s:%d %zu\n", __FILE__, __LINE__, i);
if (i >= inp->xforms.n)
{
i = 0;
switch (trns->class->execute (trns->aux, &c, inp->case_nr))
{
case TRNS_END_CASE:
- printf ("END CASE\n");
inp->case_nr++;
- inp->idx = i + 1;
+ inp->idx = i;
return c;
case TRNS_ERROR:
- printf ("ERROR\n");
casereader_force_error (reader);
/* Fall through. */
case TRNS_END_FILE:
- printf ("END FILE\n");
inp->eof = true;
case_unref (c);
return NULL;
case TRNS_CONTINUE:
- printf ("CONTINUE\n");
break;
default:
/* Outputs the current case */
static enum trns_result
-end_case_trns_proc (void *aux UNUSED, struct ccase **c UNUSED,
+end_case_trns_proc (void *resume_, struct ccase **c UNUSED,
casenumber case_nr UNUSED)
{
- printf ("%s:%d\n", __FILE__, __LINE__);
- return TRNS_END_CASE;
+ bool *resume = resume_;
+ enum trns_result retval = *resume ? TRNS_CONTINUE : TRNS_END_CASE;
+ *resume = !*resume;
+ return retval;
+}
+
+static bool
+end_case_trns_free (void *resume)
+{
+ free (resume);
+ return true;
}
static const struct trns_class end_case_trns_class = {
.name = "END CASE",
.execute = end_case_trns_proc,
+ .destroy = end_case_trns_free,
};
/* REREAD transformation. */