1 /* PSPP - computes sample statistics.
2 Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
3 Written by Ben Pfaff <blp@gnu.org>.
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27 #include <data/case-source.h>
28 #include <data/case.h>
29 #include <data/case-source.h>
30 #include <data/data-in.h>
31 #include <data/dictionary.h>
32 #include <data/format.h>
33 #include <data/procedure.h>
34 #include <data/settings.h>
35 #include <data/transformations.h>
36 #include <data/variable.h>
37 #include <language/command.h>
38 #include <language/data-io/data-reader.h>
39 #include <language/data-io/file-handle.h>
40 #include <language/data-io/inpt-pgm.h>
41 #include <language/lexer/lexer.h>
42 #include <libpspp/alloc.h>
43 #include <libpspp/compiler.h>
44 #include <libpspp/message.h>
45 #include <libpspp/message.h>
46 #include <libpspp/misc.h>
47 #include <libpspp/str.h>
48 #include <output/table.h>
53 #define _(msgid) gettext (msgid)
55 /* Utility function. */
57 /* Describes how to parse one variable. */
60 struct dls_var_spec *next; /* Next specification in list. */
62 /* Both free and fixed formats. */
63 struct fmt_spec input; /* Input format of this field. */
64 struct variable *v; /* Associated variable. Used only in
65 parsing. Not safe later. */
66 int fv; /* First value in case. */
68 /* Fixed format only. */
69 int rec; /* Record number (1-based). */
70 int fc, lc; /* Column numbers in record. */
72 /* Free format only. */
73 char name[LONG_NAME_LEN + 1]; /* Name of variable. */
76 /* Constants for DATA LIST type. */
77 /* Must match table in cmd_data_list(). */
85 /* DATA LIST private data structure. */
88 struct dls_var_spec *first, *last; /* Variable parsing specifications. */
89 struct dfm_reader *reader; /* Data file reader. */
91 int type; /* A DLS_* constant. */
92 struct variable *end; /* Variable specified on END subcommand. */
93 int rec_cnt; /* Number of records. */
94 size_t case_size; /* Case size in bytes. */
95 struct string delims; /* Field delimiters. */
98 static const struct case_source_class data_list_source_class;
100 static int parse_fixed (struct data_list_pgm *);
101 static int parse_free (struct dls_var_spec **, struct dls_var_spec **);
102 static void dump_fixed_table (const struct dls_var_spec *,
103 const struct file_handle *, int rec_cnt);
104 static void dump_free_table (const struct data_list_pgm *,
105 const struct file_handle *);
106 static void destroy_dls_var_spec (struct dls_var_spec *);
108 static trns_free_func data_list_trns_free;
109 static trns_proc_func data_list_trns_proc;
114 struct data_list_pgm *dls;
115 int table = -1; /* Print table if nonzero, -1=undecided. */
116 struct file_handle *fh = fh_inline_file ();
118 if (!in_input_program ())
119 discard_variables ();
121 dls = xmalloc (sizeof *dls);
126 ds_init_empty (&dls->delims);
127 dls->first = dls->last = NULL;
131 if (lex_match_id ("FILE"))
134 fh = fh_parse (FH_REF_FILE | FH_REF_INLINE);
138 else if (lex_match_id ("RECORDS"))
142 if (!lex_force_int ())
144 dls->rec_cnt = lex_integer ();
148 else if (lex_match_id ("END"))
152 msg (SE, _("The END subcommand may only be specified once."));
157 if (!lex_force_id ())
159 dls->end = dict_lookup_var (default_dict, tokid);
161 dls->end = dict_create_var_assert (default_dict, tokid, 0);
164 else if (token == T_ID)
166 if (lex_match_id ("NOTABLE"))
168 else if (lex_match_id ("TABLE"))
173 if (lex_match_id ("FIXED"))
175 else if (lex_match_id ("FREE"))
177 else if (lex_match_id ("LIST"))
187 msg (SE, _("Only one of FIXED, FREE, or LIST may "
193 if ((dls->type == DLS_FREE || dls->type == DLS_LIST)
196 while (!lex_match (')'))
200 if (lex_match_id ("TAB"))
202 else if (token == T_STRING && ds_length (&tokstr) == 1)
204 delim = ds_first (&tokstr);
213 ds_put_char (&dls->delims, delim);
227 dls->case_size = dict_get_case_size (default_dict);
228 fh_set_default_handle (fh);
231 dls->type = DLS_FIXED;
235 if (dls->type == DLS_FREE)
241 if (dls->type == DLS_FIXED)
243 if (!parse_fixed (dls))
246 dump_fixed_table (dls->first, fh, dls->rec_cnt);
250 if (!parse_free (&dls->first, &dls->last))
253 dump_free_table (dls, fh);
256 dls->reader = dfm_open_reader (fh);
257 if (dls->reader == NULL)
260 if (in_input_program ())
261 add_transformation (data_list_trns_proc, data_list_trns_free, dls);
263 proc_set_source (create_case_source (&data_list_source_class, dls));
268 data_list_trns_free (dls);
269 return CMD_CASCADING_FAILURE;
272 /* Adds SPEC to the linked list with head at FIRST and tail at
275 append_var_spec (struct dls_var_spec **first, struct dls_var_spec **last,
276 struct dls_var_spec *spec)
283 (*last)->next = spec;
287 /* Fixed-format parsing. */
289 /* Used for chaining together fortran-like format specifiers. */
292 struct fmt_list *next;
295 struct fmt_list *down;
298 /* State of parsing DATA LIST. */
299 struct fixed_parsing_state
301 char **name; /* Variable names. */
302 size_t name_cnt; /* Number of names. */
304 int recno; /* Index of current record. */
305 int sc; /* 1-based column number of starting column for
306 next field to output. */
309 static int fixed_parse_compatible (struct fixed_parsing_state *,
310 struct dls_var_spec **,
311 struct dls_var_spec **);
312 static int fixed_parse_fortran (struct fixed_parsing_state *,
313 struct dls_var_spec **,
314 struct dls_var_spec **);
316 /* Parses all the variable specifications for DATA LIST FIXED,
317 storing them into DLS. Returns nonzero if successful. */
319 parse_fixed (struct data_list_pgm *dls)
321 struct fixed_parsing_state fx;
329 while (lex_match ('/'))
332 if (lex_is_integer ())
334 if (lex_integer () < fx.recno)
336 msg (SE, _("The record number specified, %ld, is "
337 "before the previous record, %d. Data "
338 "fields must be listed in order of "
339 "increasing record number."),
340 lex_integer (), fx.recno - 1);
344 fx.recno = lex_integer ();
350 if (!parse_DATA_LIST_vars (&fx.name, &fx.name_cnt, PV_NONE))
353 if (lex_is_number ())
355 if (!fixed_parse_compatible (&fx, &dls->first, &dls->last))
358 else if (token == '(')
360 if (!fixed_parse_fortran (&fx, &dls->first, &dls->last))
365 msg (SE, _("SPSS-like or FORTRAN-like format "
366 "specification expected after variable names."));
370 for (i = 0; i < fx.name_cnt; i++)
374 if (dls->first == NULL)
376 msg (SE, _("At least one variable must be specified."));
379 if (dls->rec_cnt && dls->last->rec > dls->rec_cnt)
381 msg (SE, _("Variables are specified on records that "
382 "should not exist according to RECORDS subcommand."));
385 else if (!dls->rec_cnt)
386 dls->rec_cnt = dls->last->rec;
387 return lex_end_of_command () == CMD_SUCCESS;
390 for (i = 0; i < fx.name_cnt; i++)
396 /* Parses a variable specification in the form 1-10 (A) based on
397 FX and adds specifications to the linked list with head at
398 FIRST and tail at LAST. */
400 fixed_parse_compatible (struct fixed_parsing_state *fx,
401 struct dls_var_spec **first, struct dls_var_spec **last)
403 struct fmt_spec input;
409 if (!lex_force_int ())
414 msg (SE, _("Column positions for fields must be positive."));
420 lex_negative_to_dash ();
423 if (!lex_force_int ())
428 msg (SE, _("Column positions for fields must be positive."));
433 msg (SE, _("The ending column for a field must be "
434 "greater than the starting column."));
443 /* Divide columns evenly. */
444 input.w = (lc - fc + 1) / fx->name_cnt;
445 if ((lc - fc + 1) % fx->name_cnt)
447 msg (SE, _("The %d columns %d-%d "
448 "can't be evenly divided into %d fields."),
449 lc - fc + 1, fc, lc, fx->name_cnt);
453 /* Format specifier. */
456 struct fmt_desc *fdp;
462 input.type = parse_format_specifier_name (&cp, 0);
463 if (input.type == -1)
467 msg (SE, _("A format specifier on this line "
468 "has extra characters on the end."));
478 if (lex_is_integer ())
480 if (lex_integer () < 1)
482 msg (SE, _("The value for number of decimal places "
483 "must be at least 1."));
487 input.d = lex_integer ();
493 fdp = &formats[input.type];
494 if (fdp->n_args < 2 && input.d)
496 msg (SE, _("Input format %s doesn't accept decimal places."),
504 if (!lex_force_match (')'))
512 if (!check_input_specifier (&input, 1))
515 /* Start column for next specification. */
518 /* Width of variables to create. */
519 if (input.type == FMT_A || input.type == FMT_AHEX)
524 /* Create variables and var specs. */
525 for (i = 0; i < fx->name_cnt; i++)
527 struct dls_var_spec *spec;
530 v = dict_create_var (default_dict, fx->name[i], width);
533 convert_fmt_ItoO (&input, &v->print);
538 v = dict_lookup_var_assert (default_dict, fx->name[i]);
539 if (!in_input_program ())
541 msg (SE, _("%s is a duplicate variable name."), fx->name[i]);
544 if ((width != 0) != (v->width != 0))
546 msg (SE, _("There is already a variable %s of a "
551 if (width != 0 && width != v->width)
553 msg (SE, _("There is already a string variable %s of a "
554 "different width."), fx->name[i]);
559 spec = xmalloc (sizeof *spec);
563 spec->rec = fx->recno;
564 spec->fc = fc + input.w * i;
565 spec->lc = spec->fc + input.w - 1;
566 append_var_spec (first, last, spec);
571 /* Destroy format list F and, if RECURSE is nonzero, all its
574 destroy_fmt_list (struct fmt_list *f, int recurse)
576 struct fmt_list *next;
581 if (recurse && f->f.type == FMT_DESCEND)
582 destroy_fmt_list (f->down, 1);
587 /* Takes a hierarchically structured fmt_list F as constructed by
588 fixed_parse_fortran(), and flattens it, adding the variable
589 specifications to the linked list with head FIRST and tail
590 LAST. NAME_IDX is used to take values from the list of names
591 in FX; it should initially point to a value of 0. */
593 dump_fmt_list (struct fixed_parsing_state *fx, struct fmt_list *f,
594 struct dls_var_spec **first, struct dls_var_spec **last,
599 for (; f; f = f->next)
600 if (f->f.type == FMT_X)
602 else if (f->f.type == FMT_T)
604 else if (f->f.type == FMT_NEWREC)
606 fx->recno += f->count;
610 for (i = 0; i < f->count; i++)
611 if (f->f.type == FMT_DESCEND)
613 if (!dump_fmt_list (fx, f->down, first, last, name_idx))
618 struct dls_var_spec *spec;
622 if (formats[f->f.type].cat & FCAT_STRING)
626 if (*name_idx >= fx->name_cnt)
628 msg (SE, _("The number of format "
629 "specifications exceeds the given number of "
634 v = dict_create_var (default_dict, fx->name[(*name_idx)++], width);
637 msg (SE, _("%s is a duplicate variable name."), fx->name[i]);
641 spec = xmalloc (sizeof *spec);
645 spec->rec = fx->recno;
647 spec->lc = fx->sc + f->f.w - 1;
648 append_var_spec (first, last, spec);
650 convert_fmt_ItoO (&spec->input, &v->print);
658 /* Recursively parses a FORTRAN-like format specification into
659 the linked list with head FIRST and tail TAIL. LEVEL is the
660 level of recursion, starting from 0. Returns the parsed
661 specification if successful, or a null pointer on failure. */
662 static struct fmt_list *
663 fixed_parse_fortran_internal (struct fixed_parsing_state *fx,
664 struct dls_var_spec **first,
665 struct dls_var_spec **last)
667 struct fmt_list *head = NULL;
668 struct fmt_list *tail = NULL;
670 lex_force_match ('(');
674 struct fmt_list *new = xmalloc (sizeof *new);
677 /* Append new to list. */
685 if (lex_is_integer ())
687 new->count = lex_integer ();
693 /* Parse format specifier. */
696 new->f.type = FMT_DESCEND;
697 new->down = fixed_parse_fortran_internal (fx, first, last);
698 if (new->down == NULL)
701 else if (lex_match ('/'))
702 new->f.type = FMT_NEWREC;
703 else if (!parse_format_specifier (&new->f, FMTP_ALLOW_XT)
704 || !check_input_specifier (&new->f, 1))
709 lex_force_match (')');
714 destroy_fmt_list (head, 0);
719 /* Parses a FORTRAN-like format specification into the linked
720 list with head FIRST and tail LAST. Returns nonzero if
723 fixed_parse_fortran (struct fixed_parsing_state *fx,
724 struct dls_var_spec **first, struct dls_var_spec **last)
726 struct fmt_list *list;
729 list = fixed_parse_fortran_internal (fx, first, last);
734 dump_fmt_list (fx, list, first, last, &name_idx);
735 destroy_fmt_list (list, 1);
736 if (name_idx < fx->name_cnt)
738 msg (SE, _("There aren't enough format specifications "
739 "to match the number of variable names given."));
746 /* Displays a table giving information on fixed-format variable
747 parsing on DATA LIST. */
748 /* FIXME: The `Columns' column should be divided into three columns,
749 one for the starting column, one for the dash, one for the ending
750 column; then right-justify the starting column and left-justify the
753 dump_fixed_table (const struct dls_var_spec *specs,
754 const struct file_handle *fh, int rec_cnt)
756 const struct dls_var_spec *spec;
760 for (i = 0, spec = specs; spec; spec = spec->next)
762 t = tab_create (4, i + 1, 0);
763 tab_columns (t, TAB_COL_DOWN, 1);
764 tab_headers (t, 0, 0, 1, 0);
765 tab_text (t, 0, 0, TAB_CENTER | TAT_TITLE, _("Variable"));
766 tab_text (t, 1, 0, TAB_CENTER | TAT_TITLE, _("Record"));
767 tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("Columns"));
768 tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("Format"));
769 tab_box (t, TAL_1, TAL_1, TAL_0, TAL_1, 0, 0, 3, i);
770 tab_hline (t, TAL_2, 0, 3, 1);
771 tab_dim (t, tab_natural_dimensions);
773 for (i = 1, spec = specs; spec; spec = spec->next, i++)
775 tab_text (t, 0, i, TAB_LEFT, spec->v->name);
776 tab_text (t, 1, i, TAT_PRINTF, "%d", spec->rec);
777 tab_text (t, 2, i, TAT_PRINTF, "%3d-%3d",
779 tab_text (t, 3, i, TAB_LEFT | TAB_FIX,
780 fmt_to_string (&spec->input));
783 tab_title (t, ngettext ("Reading %d record from %s.",
784 "Reading %d records from %s.", rec_cnt),
785 rec_cnt, fh_get_name (fh));
789 /* Free-format parsing. */
791 /* Parses variable specifications for DATA LIST FREE and adds
792 them to the linked list with head FIRST and tail LAST.
793 Returns nonzero only if successful. */
795 parse_free (struct dls_var_spec **first, struct dls_var_spec **last)
800 struct fmt_spec input, output;
806 if (!parse_DATA_LIST_vars (&name, &name_cnt, PV_NONE))
811 if (!parse_format_specifier (&input, 0)
812 || !check_input_specifier (&input, 1)
813 || !lex_force_match (')'))
815 for (i = 0; i < name_cnt; i++)
820 convert_fmt_ItoO (&input, &output);
825 input = make_input_format (FMT_F, 8, 0);
826 output = *get_format ();
829 if (input.type == FMT_A || input.type == FMT_AHEX)
833 for (i = 0; i < name_cnt; i++)
835 struct dls_var_spec *spec;
838 v = dict_create_var (default_dict, name[i], width);
842 msg (SE, _("%s is a duplicate variable name."), name[i]);
845 v->print = v->write = output;
847 spec = xmalloc (sizeof *spec);
851 str_copy_trunc (spec->name, sizeof spec->name, v->name);
852 append_var_spec (first, last, spec);
854 for (i = 0; i < name_cnt; i++)
859 return lex_end_of_command () == CMD_SUCCESS;
862 /* Displays a table giving information on free-format variable parsing
865 dump_free_table (const struct data_list_pgm *dls,
866 const struct file_handle *fh)
872 struct dls_var_spec *spec;
873 for (i = 0, spec = dls->first; spec; spec = spec->next)
877 t = tab_create (2, i + 1, 0);
878 tab_columns (t, TAB_COL_DOWN, 1);
879 tab_headers (t, 0, 0, 1, 0);
880 tab_text (t, 0, 0, TAB_CENTER | TAT_TITLE, _("Variable"));
881 tab_text (t, 1, 0, TAB_CENTER | TAT_TITLE, _("Format"));
882 tab_box (t, TAL_1, TAL_1, TAL_0, TAL_1, 0, 0, 1, i);
883 tab_hline (t, TAL_2, 0, 1, 1);
884 tab_dim (t, tab_natural_dimensions);
887 struct dls_var_spec *spec;
889 for (i = 1, spec = dls->first; spec; spec = spec->next, i++)
891 tab_text (t, 0, i, TAB_LEFT, spec->v->name);
892 tab_text (t, 1, i, TAB_LEFT | TAB_FIX, fmt_to_string (&spec->input));
896 tab_title (t, _("Reading free-form data from %s."), fh_get_name (fh));
901 /* Input procedure. */
903 /* Extracts a field from the current position in the current
904 record. Fields can be unquoted or quoted with single- or
905 double-quote characters.
907 *FIELD is set to the field content. The caller must not
908 or destroy this constant string.
910 After parsing the field, sets the current position in the
911 record to just past the field and any trailing delimiter.
912 Returns 0 on failure or a 1-based column number indicating the
913 beginning of the field on success. */
915 cut_field (const struct data_list_pgm *dls, struct substring *field)
917 struct substring line, p;
919 if (dfm_eof (dls->reader))
921 if (ds_is_empty (&dls->delims))
922 dfm_expand_tabs (dls->reader);
923 line = p = dfm_get_record (dls->reader);
925 if (ds_is_empty (&dls->delims))
927 bool missing_quote = false;
929 /* Skip leading whitespace. */
930 ss_ltrim (&p, ss_cstr (CC_SPACES));
934 /* Handle actual data, whether quoted or unquoted. */
935 if (ss_match_char (&p, '\''))
936 missing_quote = !ss_get_until (&p, '\'', field);
937 else if (ss_match_char (&p, '"'))
938 missing_quote = !ss_get_until (&p, '"', field);
940 ss_get_chars (&p, ss_cspan (p, ss_cstr ("," CC_SPACES)), field);
942 msg (SW, _("Quoted string extends beyond end of line."));
944 /* Skip trailing whitespace and a single comma if present. */
945 ss_ltrim (&p, ss_cstr (CC_SPACES));
946 ss_match_char (&p, ',');
948 dfm_forward_columns (dls->reader, ss_length (line) - ss_length (p));
952 if (!ss_is_empty (p))
953 ss_get_chars (&p, ss_cspan (p, ds_ss (&dls->delims)), field);
954 else if (dfm_columns_past_end (dls->reader) == 0)
956 /* A blank line or a line that ends in a delimiter has a
957 trailing blank field. */
963 /* Advance past the field.
965 Also advance past a trailing delimiter, regardless of
966 whether one actually existed. If we "skip" a delimiter
967 that was not actually there, then we will return
968 end-of-line on our next call, which is what we want. */
969 dfm_forward_columns (dls->reader, ss_length (line) - ss_length (p) + 1);
974 static bool read_from_data_list_fixed (const struct data_list_pgm *,
976 static bool read_from_data_list_free (const struct data_list_pgm *,
978 static bool read_from_data_list_list (const struct data_list_pgm *,
981 /* Reads a case from DLS into C.
982 Returns true if successful, false at end of file or on I/O error. */
984 read_from_data_list (const struct data_list_pgm *dls, struct ccase *c)
988 dfm_push (dls->reader);
992 retval = read_from_data_list_fixed (dls, c);
995 retval = read_from_data_list_free (dls, c);
998 retval = read_from_data_list_list (dls, c);
1003 dfm_pop (dls->reader);
1008 /* Reads a case from the data file into C, parsing it according
1009 to fixed-format syntax rules in DLS.
1010 Returns true if successful, false at end of file or on I/O error. */
1012 read_from_data_list_fixed (const struct data_list_pgm *dls, struct ccase *c)
1014 struct dls_var_spec *var_spec = dls->first;
1017 if (dfm_eof (dls->reader))
1019 for (i = 1; i <= dls->rec_cnt; i++)
1021 struct substring line;
1023 if (dfm_eof (dls->reader))
1025 /* Note that this can't occur on the first record. */
1026 msg (SW, _("Partial case of %d of %d records discarded."),
1027 i - 1, dls->rec_cnt);
1030 dfm_expand_tabs (dls->reader);
1031 line = dfm_get_record (dls->reader);
1033 for (; var_spec && i == var_spec->rec; var_spec = var_spec->next)
1037 data_in_finite_line (&di, ss_data (line), ss_length (line),
1038 var_spec->fc, var_spec->lc);
1039 di.v = case_data_rw (c, var_spec->fv);
1040 di.flags = DI_IMPLIED_DECIMALS;
1041 di.f1 = var_spec->fc;
1042 di.format = var_spec->input;
1047 dfm_forward_record (dls->reader);
1053 /* Reads a case from the data file into C, parsing it according
1054 to free-format syntax rules in DLS.
1055 Returns true if successful, false at end of file or on I/O error. */
1057 read_from_data_list_free (const struct data_list_pgm *dls, struct ccase *c)
1059 struct dls_var_spec *var_spec;
1061 for (var_spec = dls->first; var_spec; var_spec = var_spec->next)
1063 struct substring field;
1066 /* Cut out a field and read in a new record if necessary. */
1067 while (!cut_field (dls, &field))
1069 if (!dfm_eof (dls->reader))
1070 dfm_forward_record (dls->reader);
1071 if (dfm_eof (dls->reader))
1073 if (var_spec != dls->first)
1074 msg (SW, _("Partial case discarded. The first variable "
1075 "missing was %s."), var_spec->name);
1080 di.s = ss_data (field);
1081 di.e = ss_end (field);
1082 di.v = case_data_rw (c, var_spec->fv);
1084 di.f1 = dfm_get_column (dls->reader, ss_data (field));
1085 di.format = var_spec->input;
1091 /* Reads a case from the data file and parses it according to
1092 list-format syntax rules.
1093 Returns true if successful, false at end of file or on I/O error. */
1095 read_from_data_list_list (const struct data_list_pgm *dls, struct ccase *c)
1097 struct dls_var_spec *var_spec;
1099 if (dfm_eof (dls->reader))
1102 for (var_spec = dls->first; var_spec; var_spec = var_spec->next)
1104 struct substring field;
1107 if (!cut_field (dls, &field))
1109 if (get_undefined ())
1110 msg (SW, _("Missing value(s) for all variables from %s onward. "
1111 "These will be filled with the system-missing value "
1112 "or blanks, as appropriate."),
1114 for (; var_spec; var_spec = var_spec->next)
1116 int width = get_format_var_width (&var_spec->input);
1118 case_data_rw (c, var_spec->fv)->f = SYSMIS;
1120 memset (case_data_rw (c, var_spec->fv)->s, ' ', width);
1125 di.s = ss_data (field);
1126 di.e = ss_end (field);
1127 di.v = case_data_rw (c, var_spec->fv);
1129 di.f1 = dfm_get_column (dls->reader, ss_data (field));
1130 di.format = var_spec->input;
1134 dfm_forward_record (dls->reader);
1138 /* Destroys SPEC. */
1140 destroy_dls_var_spec (struct dls_var_spec *spec)
1142 struct dls_var_spec *next;
1144 while (spec != NULL)
1152 /* Destroys DATA LIST transformation DLS.
1153 Returns true if successful, false if an I/O error occurred. */
1155 data_list_trns_free (void *dls_)
1157 struct data_list_pgm *dls = dls_;
1158 ds_destroy (&dls->delims);
1159 destroy_dls_var_spec (dls->first);
1160 dfm_close_reader (dls->reader);
1165 /* Handle DATA LIST transformation DLS, parsing data into C. */
1167 data_list_trns_proc (void *dls_, struct ccase *c, int case_num UNUSED)
1169 struct data_list_pgm *dls = dls_;
1172 if (read_from_data_list (dls, c))
1173 retval = TRNS_CONTINUE;
1174 else if (dfm_reader_error (dls->reader) || dfm_eof (dls->reader) > 1)
1176 /* An I/O error, or encountering end of file for a second
1177 time, should be escalated into a more serious error. */
1178 retval = TRNS_ERROR;
1181 retval = TRNS_END_FILE;
1183 /* If there was an END subcommand handle it. */
1184 if (dls->end != NULL)
1186 double *end = &case_data_rw (c, dls->end->fv)->f;
1187 if (retval == TRNS_DROP_CASE)
1190 retval = TRNS_END_FILE;
1199 /* Reads all the records from the data file and passes them to
1201 Returns true if successful, false if an I/O error occurred. */
1203 data_list_source_read (struct case_source *source,
1205 write_case_func *write_case, write_case_data wc_data)
1207 struct data_list_pgm *dls = source->aux;
1213 if (!read_from_data_list (dls, c))
1214 return !dfm_reader_error (dls->reader);
1216 dfm_push (dls->reader);
1217 ok = write_case (wc_data);
1218 dfm_pop (dls->reader);
1224 /* Destroys the source's internal data. */
1226 data_list_source_destroy (struct case_source *source)
1228 data_list_trns_free (source->aux);
1231 static const struct case_source_class data_list_source_class =
1235 data_list_source_read,
1236 data_list_source_destroy,