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/data-in.h>
30 #include <data/dictionary.h>
31 #include <data/format.h>
32 #include <data/settings.h>
33 #include <data/variable.h>
34 #include <language/command.h>
35 #include <language/data-io/data-reader.h>
36 #include <language/data-io/file-handle.h>
37 #include <language/data-io/inpt-pgm.h>
38 #include <language/lexer/lexer.h>
39 #include <libpspp/alloc.h>
40 #include <libpspp/compiler.h>
41 #include <libpspp/message.h>
42 #include <libpspp/message.h>
43 #include <libpspp/misc.h>
44 #include <libpspp/str.h>
45 #include <output/table.h>
46 #include <procedure.h>
49 #define _(msgid) gettext (msgid)
51 /* Utility function. */
53 /* Describes how to parse one variable. */
56 struct dls_var_spec *next; /* Next specification in list. */
58 /* Both free and fixed formats. */
59 struct fmt_spec input; /* Input format of this field. */
60 struct variable *v; /* Associated variable. Used only in
61 parsing. Not safe later. */
62 int fv; /* First value in case. */
64 /* Fixed format only. */
65 int rec; /* Record number (1-based). */
66 int fc, lc; /* Column numbers in record. */
68 /* Free format only. */
69 char name[LONG_NAME_LEN + 1]; /* Name of variable. */
72 /* Constants for DATA LIST type. */
73 /* Must match table in cmd_data_list(). */
81 /* DATA LIST private data structure. */
84 struct dls_var_spec *first, *last; /* Variable parsing specifications. */
85 struct dfm_reader *reader; /* Data file reader. */
87 int type; /* A DLS_* constant. */
88 struct variable *end; /* Variable specified on END subcommand. */
89 int rec_cnt; /* Number of records. */
90 size_t case_size; /* Case size in bytes. */
91 char *delims; /* Delimiters if any; not null-terminated. */
92 size_t delim_cnt; /* Number of delimiter, or 0 for spaces. */
95 static const struct case_source_class data_list_source_class;
97 static int parse_fixed (struct data_list_pgm *);
98 static int parse_free (struct dls_var_spec **, struct dls_var_spec **);
99 static void dump_fixed_table (const struct dls_var_spec *,
100 const struct file_handle *, int rec_cnt);
101 static void dump_free_table (const struct data_list_pgm *,
102 const struct file_handle *);
103 static void destroy_dls_var_spec (struct dls_var_spec *);
104 static trns_free_func data_list_trns_free;
105 static trns_proc_func data_list_trns_proc;
110 struct data_list_pgm *dls;
111 int table = -1; /* Print table if nonzero, -1=undecided. */
112 struct file_handle *fh = fh_inline_file ();
114 if (!in_input_program ())
115 discard_variables ();
117 dls = xmalloc (sizeof *dls);
124 dls->first = dls->last = NULL;
128 if (lex_match_id ("FILE"))
131 fh = fh_parse (FH_REF_FILE | FH_REF_INLINE);
135 else if (lex_match_id ("RECORDS"))
139 if (!lex_force_int ())
141 dls->rec_cnt = lex_integer ();
145 else if (lex_match_id ("END"))
149 msg (SE, _("The END subcommand may only be specified once."));
154 if (!lex_force_id ())
156 dls->end = dict_lookup_var (default_dict, tokid);
158 dls->end = dict_create_var_assert (default_dict, tokid, 0);
161 else if (token == T_ID)
163 if (lex_match_id ("NOTABLE"))
165 else if (lex_match_id ("TABLE"))
170 if (lex_match_id ("FIXED"))
172 else if (lex_match_id ("FREE"))
174 else if (lex_match_id ("LIST"))
184 msg (SE, _("Only one of FIXED, FREE, or LIST may "
190 if ((dls->type == DLS_FREE || dls->type == DLS_LIST)
193 while (!lex_match (')'))
197 if (lex_match_id ("TAB"))
199 else if (token == T_STRING && tokstr.length == 1)
201 delim = tokstr.string[0];
210 dls->delims = xrealloc (dls->delims, dls->delim_cnt + 1);
211 dls->delims[dls->delim_cnt++] = delim;
225 dls->case_size = dict_get_case_size (default_dict);
226 fh_set_default_handle (fh);
229 dls->type = DLS_FIXED;
233 if (dls->type == DLS_FREE)
239 if (dls->type == DLS_FIXED)
241 if (!parse_fixed (dls))
244 dump_fixed_table (dls->first, fh, dls->rec_cnt);
248 if (!parse_free (&dls->first, &dls->last))
251 dump_free_table (dls, fh);
254 dls->reader = dfm_open_reader (fh);
255 if (dls->reader == NULL)
258 if (vfm_source != NULL)
259 add_transformation (data_list_trns_proc, data_list_trns_free, dls);
261 vfm_source = create_case_source (&data_list_source_class, dls);
266 data_list_trns_free (dls);
267 return CMD_CASCADING_FAILURE;
270 /* Adds SPEC to the linked list with head at FIRST and tail at
273 append_var_spec (struct dls_var_spec **first, struct dls_var_spec **last,
274 struct dls_var_spec *spec)
281 (*last)->next = spec;
285 /* Fixed-format parsing. */
287 /* Used for chaining together fortran-like format specifiers. */
290 struct fmt_list *next;
293 struct fmt_list *down;
296 /* State of parsing DATA LIST. */
297 struct fixed_parsing_state
299 char **name; /* Variable names. */
300 size_t name_cnt; /* Number of names. */
302 int recno; /* Index of current record. */
303 int sc; /* 1-based column number of starting column for
304 next field to output. */
307 static int fixed_parse_compatible (struct fixed_parsing_state *,
308 struct dls_var_spec **,
309 struct dls_var_spec **);
310 static int fixed_parse_fortran (struct fixed_parsing_state *,
311 struct dls_var_spec **,
312 struct dls_var_spec **);
314 /* Parses all the variable specifications for DATA LIST FIXED,
315 storing them into DLS. Returns nonzero if successful. */
317 parse_fixed (struct data_list_pgm *dls)
319 struct fixed_parsing_state fx;
327 while (lex_match ('/'))
330 if (lex_is_integer ())
332 if (lex_integer () < fx.recno)
334 msg (SE, _("The record number specified, %ld, is "
335 "before the previous record, %d. Data "
336 "fields must be listed in order of "
337 "increasing record number."),
338 lex_integer (), fx.recno - 1);
342 fx.recno = lex_integer ();
348 if (!parse_DATA_LIST_vars (&fx.name, &fx.name_cnt, PV_NONE))
351 if (lex_is_number ())
353 if (!fixed_parse_compatible (&fx, &dls->first, &dls->last))
356 else if (token == '(')
358 if (!fixed_parse_fortran (&fx, &dls->first, &dls->last))
363 msg (SE, _("SPSS-like or FORTRAN-like format "
364 "specification expected after variable names."));
368 for (i = 0; i < fx.name_cnt; i++)
372 if (dls->first == NULL)
374 msg (SE, _("At least one variable must be specified."));
377 if (dls->rec_cnt && dls->last->rec > dls->rec_cnt)
379 msg (SE, _("Variables are specified on records that "
380 "should not exist according to RECORDS subcommand."));
383 else if (!dls->rec_cnt)
384 dls->rec_cnt = dls->last->rec;
385 return lex_end_of_command () == CMD_SUCCESS;
388 for (i = 0; i < fx.name_cnt; i++)
394 /* Parses a variable specification in the form 1-10 (A) based on
395 FX and adds specifications to the linked list with head at
396 FIRST and tail at LAST. */
398 fixed_parse_compatible (struct fixed_parsing_state *fx,
399 struct dls_var_spec **first, struct dls_var_spec **last)
401 struct fmt_spec input;
407 if (!lex_force_int ())
412 msg (SE, _("Column positions for fields must be positive."));
418 lex_negative_to_dash ();
421 if (!lex_force_int ())
426 msg (SE, _("Column positions for fields must be positive."));
431 msg (SE, _("The ending column for a field must be "
432 "greater than the starting column."));
441 /* Divide columns evenly. */
442 input.w = (lc - fc + 1) / fx->name_cnt;
443 if ((lc - fc + 1) % fx->name_cnt)
445 msg (SE, _("The %d columns %d-%d "
446 "can't be evenly divided into %d fields."),
447 lc - fc + 1, fc, lc, fx->name_cnt);
451 /* Format specifier. */
454 struct fmt_desc *fdp;
460 input.type = parse_format_specifier_name (&cp, 0);
461 if (input.type == -1)
465 msg (SE, _("A format specifier on this line "
466 "has extra characters on the end."));
476 if (lex_is_integer ())
478 if (lex_integer () < 1)
480 msg (SE, _("The value for number of decimal places "
481 "must be at least 1."));
485 input.d = lex_integer ();
491 fdp = &formats[input.type];
492 if (fdp->n_args < 2 && input.d)
494 msg (SE, _("Input format %s doesn't accept decimal places."),
502 if (!lex_force_match (')'))
510 if (!check_input_specifier (&input, 1))
513 /* Start column for next specification. */
516 /* Width of variables to create. */
517 if (input.type == FMT_A || input.type == FMT_AHEX)
522 /* Create variables and var specs. */
523 for (i = 0; i < fx->name_cnt; i++)
525 struct dls_var_spec *spec;
528 v = dict_create_var (default_dict, fx->name[i], width);
531 convert_fmt_ItoO (&input, &v->print);
536 v = dict_lookup_var_assert (default_dict, fx->name[i]);
537 if (vfm_source == NULL)
539 msg (SE, _("%s is a duplicate variable name."), fx->name[i]);
542 if ((width != 0) != (v->width != 0))
544 msg (SE, _("There is already a variable %s of a "
549 if (width != 0 && width != v->width)
551 msg (SE, _("There is already a string variable %s of a "
552 "different width."), fx->name[i]);
557 spec = xmalloc (sizeof *spec);
561 spec->rec = fx->recno;
562 spec->fc = fc + input.w * i;
563 spec->lc = spec->fc + input.w - 1;
564 append_var_spec (first, last, spec);
569 /* Destroy format list F and, if RECURSE is nonzero, all its
572 destroy_fmt_list (struct fmt_list *f, int recurse)
574 struct fmt_list *next;
579 if (recurse && f->f.type == FMT_DESCEND)
580 destroy_fmt_list (f->down, 1);
585 /* Takes a hierarchically structured fmt_list F as constructed by
586 fixed_parse_fortran(), and flattens it, adding the variable
587 specifications to the linked list with head FIRST and tail
588 LAST. NAME_IDX is used to take values from the list of names
589 in FX; it should initially point to a value of 0. */
591 dump_fmt_list (struct fixed_parsing_state *fx, struct fmt_list *f,
592 struct dls_var_spec **first, struct dls_var_spec **last,
597 for (; f; f = f->next)
598 if (f->f.type == FMT_X)
600 else if (f->f.type == FMT_T)
602 else if (f->f.type == FMT_NEWREC)
604 fx->recno += f->count;
608 for (i = 0; i < f->count; i++)
609 if (f->f.type == FMT_DESCEND)
611 if (!dump_fmt_list (fx, f->down, first, last, name_idx))
616 struct dls_var_spec *spec;
620 if (formats[f->f.type].cat & FCAT_STRING)
624 if (*name_idx >= fx->name_cnt)
626 msg (SE, _("The number of format "
627 "specifications exceeds the given number of "
632 v = dict_create_var (default_dict, fx->name[(*name_idx)++], width);
635 msg (SE, _("%s is a duplicate variable name."), fx->name[i]);
639 spec = xmalloc (sizeof *spec);
643 spec->rec = fx->recno;
645 spec->lc = fx->sc + f->f.w - 1;
646 append_var_spec (first, last, spec);
648 convert_fmt_ItoO (&spec->input, &v->print);
656 /* Recursively parses a FORTRAN-like format specification into
657 the linked list with head FIRST and tail TAIL. LEVEL is the
658 level of recursion, starting from 0. Returns the parsed
659 specification if successful, or a null pointer on failure. */
660 static struct fmt_list *
661 fixed_parse_fortran_internal (struct fixed_parsing_state *fx,
662 struct dls_var_spec **first,
663 struct dls_var_spec **last)
665 struct fmt_list *head = NULL;
666 struct fmt_list *tail = NULL;
668 lex_force_match ('(');
672 struct fmt_list *new = xmalloc (sizeof *new);
675 /* Append new to list. */
683 if (lex_is_integer ())
685 new->count = lex_integer ();
691 /* Parse format specifier. */
694 new->f.type = FMT_DESCEND;
695 new->down = fixed_parse_fortran_internal (fx, first, last);
696 if (new->down == NULL)
699 else if (lex_match ('/'))
700 new->f.type = FMT_NEWREC;
701 else if (!parse_format_specifier (&new->f, FMTP_ALLOW_XT)
702 || !check_input_specifier (&new->f, 1))
707 lex_force_match (')');
712 destroy_fmt_list (head, 0);
717 /* Parses a FORTRAN-like format specification into the linked
718 list with head FIRST and tail LAST. Returns nonzero if
721 fixed_parse_fortran (struct fixed_parsing_state *fx,
722 struct dls_var_spec **first, struct dls_var_spec **last)
724 struct fmt_list *list;
727 list = fixed_parse_fortran_internal (fx, first, last);
732 dump_fmt_list (fx, list, first, last, &name_idx);
733 destroy_fmt_list (list, 1);
734 if (name_idx < fx->name_cnt)
736 msg (SE, _("There aren't enough format specifications "
737 "to match the number of variable names given."));
744 /* Displays a table giving information on fixed-format variable
745 parsing on DATA LIST. */
746 /* FIXME: The `Columns' column should be divided into three columns,
747 one for the starting column, one for the dash, one for the ending
748 column; then right-justify the starting column and left-justify the
751 dump_fixed_table (const struct dls_var_spec *specs,
752 const struct file_handle *fh, int rec_cnt)
754 const struct dls_var_spec *spec;
758 for (i = 0, spec = specs; spec; spec = spec->next)
760 t = tab_create (4, i + 1, 0);
761 tab_columns (t, TAB_COL_DOWN, 1);
762 tab_headers (t, 0, 0, 1, 0);
763 tab_text (t, 0, 0, TAB_CENTER | TAT_TITLE, _("Variable"));
764 tab_text (t, 1, 0, TAB_CENTER | TAT_TITLE, _("Record"));
765 tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("Columns"));
766 tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("Format"));
767 tab_box (t, TAL_1, TAL_1, TAL_0, TAL_1, 0, 0, 3, i);
768 tab_hline (t, TAL_2, 0, 3, 1);
769 tab_dim (t, tab_natural_dimensions);
771 for (i = 1, spec = specs; spec; spec = spec->next, i++)
773 tab_text (t, 0, i, TAB_LEFT, spec->v->name);
774 tab_text (t, 1, i, TAT_PRINTF, "%d", spec->rec);
775 tab_text (t, 2, i, TAT_PRINTF, "%3d-%3d",
777 tab_text (t, 3, i, TAB_LEFT | TAB_FIX,
778 fmt_to_string (&spec->input));
781 tab_title (t, ngettext ("Reading %d record from %s.",
782 "Reading %d records from %s.", rec_cnt),
783 rec_cnt, fh_get_name (fh));
787 /* Free-format parsing. */
789 /* Parses variable specifications for DATA LIST FREE and adds
790 them to the linked list with head FIRST and tail LAST.
791 Returns nonzero only if successful. */
793 parse_free (struct dls_var_spec **first, struct dls_var_spec **last)
798 struct fmt_spec input, output;
804 if (!parse_DATA_LIST_vars (&name, &name_cnt, PV_NONE))
809 if (!parse_format_specifier (&input, 0)
810 || !check_input_specifier (&input, 1)
811 || !lex_force_match (')'))
813 for (i = 0; i < name_cnt; i++)
818 convert_fmt_ItoO (&input, &output);
823 input = make_input_format (FMT_F, 8, 0);
824 output = *get_format ();
827 if (input.type == FMT_A || input.type == FMT_AHEX)
831 for (i = 0; i < name_cnt; i++)
833 struct dls_var_spec *spec;
836 v = dict_create_var (default_dict, name[i], width);
840 msg (SE, _("%s is a duplicate variable name."), name[i]);
843 v->print = v->write = output;
845 spec = xmalloc (sizeof *spec);
849 str_copy_trunc (spec->name, sizeof spec->name, v->name);
850 append_var_spec (first, last, spec);
852 for (i = 0; i < name_cnt; i++)
857 return lex_end_of_command () == CMD_SUCCESS;
860 /* Displays a table giving information on free-format variable parsing
863 dump_free_table (const struct data_list_pgm *dls,
864 const struct file_handle *fh)
870 struct dls_var_spec *spec;
871 for (i = 0, spec = dls->first; spec; spec = spec->next)
875 t = tab_create (2, i + 1, 0);
876 tab_columns (t, TAB_COL_DOWN, 1);
877 tab_headers (t, 0, 0, 1, 0);
878 tab_text (t, 0, 0, TAB_CENTER | TAT_TITLE, _("Variable"));
879 tab_text (t, 1, 0, TAB_CENTER | TAT_TITLE, _("Format"));
880 tab_box (t, TAL_1, TAL_1, TAL_0, TAL_1, 0, 0, 1, i);
881 tab_hline (t, TAL_2, 0, 1, 1);
882 tab_dim (t, tab_natural_dimensions);
885 struct dls_var_spec *spec;
887 for (i = 1, spec = dls->first; spec; spec = spec->next, i++)
889 tab_text (t, 0, i, TAB_LEFT, spec->v->name);
890 tab_text (t, 1, i, TAB_LEFT | TAB_FIX, fmt_to_string (&spec->input));
894 tab_title (t, _("Reading free-form data from %s."), fh_get_name (fh));
899 /* Input procedure. */
901 /* Extracts a field from the current position in the current
902 record. Fields can be unquoted or quoted with single- or
903 double-quote characters. *FIELD is set to the field content.
904 After parsing the field, sets the current position in the
905 record to just past the field and any trailing delimiter.
906 END_BLANK is used internally; it should be initialized by the
907 caller to 0 and left alone afterward. Returns 0 on failure or
908 a 1-based column number indicating the beginning of the field
911 cut_field (const struct data_list_pgm *dls, struct fixed_string *field,
914 struct fixed_string line;
918 if (dfm_eof (dls->reader))
920 if (dls->delim_cnt == 0)
921 dfm_expand_tabs (dls->reader);
922 dfm_get_record (dls->reader, &line);
924 cp = ls_c_str (&line);
925 if (dls->delim_cnt == 0)
927 /* Skip leading whitespace. */
928 while (cp < ls_end (&line) && isspace ((unsigned char) *cp))
930 if (cp >= ls_end (&line))
933 /* Handle actual data, whether quoted or unquoted. */
934 if (*cp == '\'' || *cp == '"')
938 field->string = ++cp;
939 while (cp < ls_end (&line) && *cp != quote)
941 field->length = cp - field->string;
942 if (cp < ls_end (&line))
945 msg (SW, _("Quoted string missing terminating `%c'."), quote);
950 while (cp < ls_end (&line)
951 && !isspace ((unsigned char) *cp) && *cp != ',')
953 field->length = cp - field->string;
956 /* Skip trailing whitespace and a single comma if present. */
957 while (cp < ls_end (&line) && isspace ((unsigned char) *cp))
959 if (cp < ls_end (&line) && *cp == ',')
964 if (cp >= ls_end (&line))
966 int column = dfm_column_start (dls->reader);
967 /* A blank line or a line that ends in \t has a
968 trailing blank field. */
969 if (column == 1 || (column > 1 && cp[-1] == '\t'))
974 field->string = ls_end (&line);
976 dfm_forward_record (dls->reader);
991 while (cp < ls_end (&line)
992 && memchr (dls->delims, *cp, dls->delim_cnt) == NULL)
994 field->length = cp - field->string;
995 if (cp < ls_end (&line))
1000 dfm_forward_columns (dls->reader, field->string - line.string);
1001 column_start = dfm_column_start (dls->reader);
1003 dfm_forward_columns (dls->reader, cp - field->string);
1005 return column_start;
1008 static bool read_from_data_list_fixed (const struct data_list_pgm *,
1010 static bool read_from_data_list_free (const struct data_list_pgm *,
1012 static bool read_from_data_list_list (const struct data_list_pgm *,
1015 /* Reads a case from DLS into C.
1016 Returns true if successful, false at end of file or on I/O error. */
1018 read_from_data_list (const struct data_list_pgm *dls, struct ccase *c)
1022 dfm_push (dls->reader);
1026 retval = read_from_data_list_fixed (dls, c);
1029 retval = read_from_data_list_free (dls, c);
1032 retval = read_from_data_list_list (dls, c);
1037 dfm_pop (dls->reader);
1042 /* Reads a case from the data file into C, parsing it according
1043 to fixed-format syntax rules in DLS.
1044 Returns true if successful, false at end of file or on I/O error. */
1046 read_from_data_list_fixed (const struct data_list_pgm *dls, struct ccase *c)
1048 struct dls_var_spec *var_spec = dls->first;
1051 if (dfm_eof (dls->reader))
1053 for (i = 1; i <= dls->rec_cnt; i++)
1055 struct fixed_string line;
1057 if (dfm_eof (dls->reader))
1059 /* Note that this can't occur on the first record. */
1060 msg (SW, _("Partial case of %d of %d records discarded."),
1061 i - 1, dls->rec_cnt);
1064 dfm_expand_tabs (dls->reader);
1065 dfm_get_record (dls->reader, &line);
1067 for (; var_spec && i == var_spec->rec; var_spec = var_spec->next)
1071 data_in_finite_line (&di, ls_c_str (&line), ls_length (&line),
1072 var_spec->fc, var_spec->lc);
1073 di.v = case_data_rw (c, var_spec->fv);
1074 di.flags = DI_IMPLIED_DECIMALS;
1075 di.f1 = var_spec->fc;
1076 di.format = var_spec->input;
1081 dfm_forward_record (dls->reader);
1087 /* Reads a case from the data file into C, parsing it according
1088 to free-format syntax rules in DLS.
1089 Returns true if successful, false at end of file or on I/O error. */
1091 read_from_data_list_free (const struct data_list_pgm *dls, struct ccase *c)
1093 struct dls_var_spec *var_spec;
1096 for (var_spec = dls->first; var_spec; var_spec = var_spec->next)
1098 struct fixed_string field;
1101 /* Cut out a field and read in a new record if necessary. */
1104 column = cut_field (dls, &field, &end_blank);
1108 if (!dfm_eof (dls->reader))
1109 dfm_forward_record (dls->reader);
1110 if (dfm_eof (dls->reader))
1112 if (var_spec != dls->first)
1113 msg (SW, _("Partial case discarded. The first variable "
1114 "missing was %s."), var_spec->name);
1122 di.s = ls_c_str (&field);
1123 di.e = ls_end (&field);
1124 di.v = case_data_rw (c, var_spec->fv);
1127 di.format = var_spec->input;
1134 /* Reads a case from the data file and parses it according to
1135 list-format syntax rules.
1136 Returns true if successful, false at end of file or on I/O error. */
1138 read_from_data_list_list (const struct data_list_pgm *dls, struct ccase *c)
1140 struct dls_var_spec *var_spec;
1143 if (dfm_eof (dls->reader))
1146 for (var_spec = dls->first; var_spec; var_spec = var_spec->next)
1148 struct fixed_string field;
1151 /* Cut out a field and check for end-of-line. */
1152 column = cut_field (dls, &field, &end_blank);
1155 if (get_undefined ())
1156 msg (SW, _("Missing value(s) for all variables from %s onward. "
1157 "These will be filled with the system-missing value "
1158 "or blanks, as appropriate."),
1160 for (; var_spec; var_spec = var_spec->next)
1162 int width = get_format_var_width (&var_spec->input);
1164 case_data_rw (c, var_spec->fv)->f = SYSMIS;
1166 memset (case_data_rw (c, var_spec->fv)->s, ' ', width);
1174 di.s = ls_c_str (&field);
1175 di.e = ls_end (&field);
1176 di.v = case_data_rw (c, var_spec->fv);
1179 di.format = var_spec->input;
1184 dfm_forward_record (dls->reader);
1188 /* Destroys SPEC. */
1190 destroy_dls_var_spec (struct dls_var_spec *spec)
1192 struct dls_var_spec *next;
1194 while (spec != NULL)
1202 /* Destroys DATA LIST transformation DLS.
1203 Returns true if successful, false if an I/O error occurred. */
1205 data_list_trns_free (void *dls_)
1207 struct data_list_pgm *dls = dls_;
1209 destroy_dls_var_spec (dls->first);
1210 dfm_close_reader (dls->reader);
1215 /* Handle DATA LIST transformation DLS, parsing data into C. */
1217 data_list_trns_proc (void *dls_, struct ccase *c, int case_num UNUSED)
1219 struct data_list_pgm *dls = dls_;
1222 if (read_from_data_list (dls, c))
1223 retval = TRNS_CONTINUE;
1224 else if (dfm_reader_error (dls->reader) || dfm_eof (dls->reader) > 1)
1226 /* An I/O error, or encountering end of file for a second
1227 time, should be escalated into a more serious error. */
1228 retval = TRNS_ERROR;
1231 retval = TRNS_DROP_CASE;
1233 /* If there was an END subcommand handle it. */
1234 if (dls->end != NULL)
1236 double *end = &case_data_rw (c, dls->end->fv)->f;
1237 if (retval == TRNS_DROP_CASE)
1240 retval = TRNS_CONTINUE;
1249 /* Reads all the records from the data file and passes them to
1251 Returns true if successful, false if an I/O error occurred. */
1253 data_list_source_read (struct case_source *source,
1255 write_case_func *write_case, write_case_data wc_data)
1257 struct data_list_pgm *dls = source->aux;
1263 if (!read_from_data_list (dls, c))
1264 return !dfm_reader_error (dls->reader);
1266 dfm_push (dls->reader);
1267 ok = write_case (wc_data);
1268 dfm_pop (dls->reader);
1274 /* Destroys the source's internal data. */
1276 data_list_source_destroy (struct case_source *source)
1278 data_list_trns_free (source->aux);
1281 static const struct case_source_class data_list_source_class =
1285 data_list_source_read,
1286 data_list_source_destroy,