- dict_compactor_destroy (compactor);
- dict_compact_values (default_dict);
- compactor = NULL;
- }
-
- /* Free data source. */
- free_case_source (vfm_source);
- vfm_source = NULL;
-
- /* Old data sink becomes new data source. */
- if (vfm_sink->class->make_source != NULL)
- vfm_source = vfm_sink->class->make_source (vfm_sink);
- free_case_sink (vfm_sink);
- vfm_sink = NULL;
-
- /* Cancel TEMPORARY, PROCESS IF, FILTER, N OF CASES, vectors,
- and get rid of all the transformations. */
- dict_clear_vectors (default_dict);
- permanent_dict = NULL;
- return proc_cancel_all_transformations ();
-}
-\f
-/* Returns a pointer to the lagged case from N_BEFORE cases before the
- current one, or NULL if there haven't been that many cases yet. */
-struct ccase *
-lagged_case (int n_before)
-{
- assert (n_before >= 1 );
- assert (n_before <= n_lag);
-
- if (n_before <= lag_count)
- {
- int index = lag_head - n_before;
- if (index < 0)
- index += n_lag;
- return &lag_queue[index];
- }
- else
- return NULL;
-}
-\f
-/* Procedure that separates the data into SPLIT FILE groups. */
-
-/* Represents auxiliary data for handling SPLIT FILE. */
-struct split_aux_data
- {
- size_t case_count; /* Number of cases so far. */
- struct ccase prev_case; /* Data in previous case. */
-
- /* Callback functions. */
- void (*begin_func) (const struct ccase *, void *);
- bool (*proc_func) (const struct ccase *, void *);
- void (*end_func) (void *);
- void *func_aux;
- };
-
-static int equal_splits (const struct ccase *, const struct ccase *);
-static bool split_procedure_case_func (const struct ccase *c, void *);
-static bool split_procedure_end_func (void *);
-
-/* Like procedure(), but it automatically breaks the case stream
- into SPLIT FILE break groups. Before each group of cases with
- identical SPLIT FILE variable values, BEGIN_FUNC is called
- with the first case in the group.
- Then PROC_FUNC is called for each case in the group (including
- the first).
- END_FUNC is called when the group is finished. FUNC_AUX is
- passed to each of the functions as auxiliary data.
-
- If the active file is empty, none of BEGIN_FUNC, PROC_FUNC,
- and END_FUNC will be called at all.
-
- If SPLIT FILE is not in effect, then there is one break group
- (if the active file is nonempty), and BEGIN_FUNC and END_FUNC
- will be called once.
-
- Returns true if successful, false if an I/O error occurred. */
-bool
-procedure_with_splits (void (*begin_func) (const struct ccase *, void *aux),
- bool (*proc_func) (const struct ccase *, void *aux),
- void (*end_func) (void *aux),
- void *func_aux)
-{
- struct split_aux_data split_aux;
- bool ok;
-
- split_aux.case_count = 0;
- case_nullify (&split_aux.prev_case);
- split_aux.begin_func = begin_func;
- split_aux.proc_func = proc_func;
- split_aux.end_func = end_func;
- split_aux.func_aux = func_aux;
-
- ok = internal_procedure (split_procedure_case_func,
- split_procedure_end_func, &split_aux);
-
- case_destroy (&split_aux.prev_case);
-
- return ok;
-}
+ casenumber case_nr;
+
+ assert (retval == TRNS_DROP_CASE || retval == TRNS_ERROR);
+ if (retval == TRNS_ERROR)
+ ds->ok = false;
+ if (!ds->ok)
+ return NULL;
+
+ /* Read a case from source. */
+ c = casereader_read (ds->source);
+ if (c == NULL)
+ return NULL;
+ c = case_unshare_and_resize (c, dict_get_next_value_idx (ds->dict));
+ caseinit_init_vars (ds->caseinit, c);
+
+ /* Execute permanent transformations. */
+ case_nr = ds->cases_written + 1;
+ retval = trns_chain_execute (ds->permanent_trns_chain, TRNS_CONTINUE,
+ &c, case_nr);
+ caseinit_update_left_vars (ds->caseinit, c);
+ if (retval != TRNS_CONTINUE)
+ continue;