Change enum legacy_encoding to const char *.
[pspp-builds.git] / src / language / data-io / data-parser.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2007, 2009 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include <language/data-io/data-parser.h>
20
21 #include <stdint.h>
22 #include <stdlib.h>
23
24 #include <data/casereader-provider.h>
25 #include <data/data-in.h>
26 #include <data/dictionary.h>
27 #include <data/format.h>
28 #include <data/file-handle-def.h>
29 #include <data/procedure.h>
30 #include <data/settings.h>
31 #include <language/data-io/data-reader.h>
32 #include <libpspp/message.h>
33 #include <libpspp/str.h>
34 #include <output/table.h>
35
36 #include "xalloc.h"
37
38 #include "gettext.h"
39 #define _(msgid) gettext (msgid)
40
41 /* Data parser for textual data like that read by DATA LIST. */
42 struct data_parser
43   {
44     enum data_parser_type type; /* Type of data to parse. */
45     int skip_records;           /* Records to skip before first real data. */
46     casenumber max_cases;       /* Max number of cases to read. */
47     int percent_cases;          /* Approximate percent of cases to read. */
48
49     struct field *fields;       /* Fields to parse. */
50     size_t field_cnt;           /* Number of fields. */
51     size_t field_allocated;     /* Number of fields spaced allocated for. */
52
53     /* DP_DELIMITED parsers only. */
54     bool span;                  /* May cases span multiple records? */
55     bool empty_line_has_field;  /* Does an empty line have an (empty) field? */
56     struct substring quotes;    /* Characters that can quote separators. */
57     bool quote_escape;          /* Doubled quote acts as escape? */
58     struct substring soft_seps; /* Two soft separators act like just one. */
59     struct substring hard_seps; /* Two hard separators yield empty fields. */
60     struct string any_sep;      /* Concatenation of soft_seps and hard_seps. */
61
62     /* DP_FIXED parsers only. */
63     int records_per_case;       /* Number of records in each case. */
64   };
65
66 /* How to parse one variable. */
67 struct field
68   {
69     struct fmt_spec format;     /* Input format of this field. */
70     int case_idx;               /* First value in case. */
71     char *name;                 /* Var name for error messages and tables. */
72
73     /* DP_FIXED only. */
74     int record;                 /* Record number (1-based). */
75     int first_column;           /* First column in record (1-based). */
76   };
77
78 static void set_any_sep (struct data_parser *parser);
79
80 /* Creates and returns a new data parser. */
81 struct data_parser *
82 data_parser_create (void)
83 {
84   struct data_parser *parser = xmalloc (sizeof *parser);
85
86   parser->type = DP_FIXED;
87   parser->skip_records = 0;
88   parser->max_cases = -1;
89   parser->percent_cases = 100;
90
91   parser->fields = NULL;
92   parser->field_cnt = 0;
93   parser->field_allocated = 0;
94
95   parser->span = true;
96   parser->empty_line_has_field = false;
97   ss_alloc_substring (&parser->quotes, ss_cstr ("\"'"));
98   parser->quote_escape = false;
99   ss_alloc_substring (&parser->soft_seps, ss_cstr (CC_SPACES));
100   ss_alloc_substring (&parser->hard_seps, ss_cstr (","));
101   ds_init_empty (&parser->any_sep);
102   set_any_sep (parser);
103
104   parser->records_per_case = 0;
105
106   return parser;
107 }
108
109 /* Destroys PARSER. */
110 void
111 data_parser_destroy (struct data_parser *parser)
112 {
113   if (parser != NULL)
114     {
115       size_t i;
116
117       for (i = 0; i < parser->field_cnt; i++)
118         free (parser->fields[i].name);
119       free (parser->fields);
120       ss_dealloc (&parser->quotes);
121       ss_dealloc (&parser->soft_seps);
122       ss_dealloc (&parser->hard_seps);
123       ds_destroy (&parser->any_sep);
124       free (parser);
125     }
126 }
127
128 /* Returns the type of PARSER (either DP_DELIMITED or DP_FIXED). */
129 enum data_parser_type
130 data_parser_get_type (const struct data_parser *parser)
131 {
132   return parser->type;
133 }
134
135 /* Sets the type of PARSER to TYPE (either DP_DELIMITED or
136    DP_FIXED). */
137 void
138 data_parser_set_type (struct data_parser *parser, enum data_parser_type type)
139 {
140   assert (parser->field_cnt == 0);
141   assert (type == DP_FIXED || type == DP_DELIMITED);
142   parser->type = type;
143 }
144
145 /* Configures PARSER to skip the specified number of
146    INITIAL_RECORDS_TO_SKIP before parsing any data.  By default,
147    no records are skipped. */
148 void
149 data_parser_set_skip (struct data_parser *parser, int initial_records_to_skip)
150 {
151   assert (initial_records_to_skip >= 0);
152   parser->skip_records = initial_records_to_skip;
153 }
154
155 /* Sets the maximum number of cases parsed by PARSER to
156    MAX_CASES.  The default is -1, meaning no limit. */
157 void
158 data_parser_set_case_limit (struct data_parser *parser, casenumber max_cases)
159 {
160   parser->max_cases = max_cases;
161 }
162
163 /* Sets the percentage of cases that PARSER should read from the
164    input file to PERCENT_CASES.  By default, all cases are
165    read. */
166 void
167 data_parser_set_case_percent (struct data_parser *parser, int percent_cases)
168 {
169   assert (percent_cases >= 0 && percent_cases <= 100);
170   parser->percent_cases = percent_cases;
171 }
172
173 /* Returns true if PARSER is configured to allow cases to span
174    multiple records. */
175 bool
176 data_parser_get_span (const struct data_parser *parser)
177 {
178   return parser->span;
179 }
180
181 /* If MAY_CASES_SPAN_RECORDS is true, configures PARSER to allow
182    a single case to span multiple records and multiple cases to
183    occupy a single record.  If MAY_CASES_SPAN_RECORDS is false,
184    configures PARSER to require each record to contain exactly
185    one case.
186
187    This setting affects parsing of DP_DELIMITED files only. */
188 void
189 data_parser_set_span (struct data_parser *parser, bool may_cases_span_records)
190 {
191   parser->span = may_cases_span_records;
192 }
193
194 /* If EMPTY_LINE_HAS_FIELD is true, configures PARSER to parse an
195    empty line as an empty field and to treat a hard delimiter
196    followed by end-of-line as an empty field.  If
197    EMPTY_LINE_HAS_FIELD is false, PARSER will skip empty lines
198    and hard delimiters at the end of lines without emitting empty
199    fields.
200
201    This setting affects parsing of DP_DELIMITED files only. */
202 void
203 data_parser_set_empty_line_has_field (struct data_parser *parser,
204                                       bool empty_line_has_field)
205 {
206   parser->empty_line_has_field = empty_line_has_field;
207 }
208
209 /* Sets the characters that may be used for quoting field
210    contents to QUOTES.  If QUOTES is empty, quoting will be
211    disabled.
212
213    The caller retains ownership of QUOTES.
214
215    This setting affects parsing of DP_DELIMITED files only. */
216 void
217 data_parser_set_quotes (struct data_parser *parser, struct substring quotes)
218 {
219   ss_dealloc (&parser->quotes);
220   ss_alloc_substring (&parser->quotes, quotes);
221 }
222
223 /* If ESCAPE is false (the default setting), a character used for
224    quoting cannot itself be embedded within a quoted field.  If
225    ESCAPE is true, then a quote character can be embedded within
226    a quoted field by doubling it.
227
228    This setting affects parsing of DP_DELIMITED files only, and
229    only when at least one quote character has been set (with
230    data_parser_set_quotes). */
231 void
232 data_parser_set_quote_escape (struct data_parser *parser, bool escape)
233 {
234   parser->quote_escape = escape;
235 }
236
237 /* Sets PARSER's soft delimiters to DELIMITERS.  Soft delimiters
238    separate fields, but consecutive soft delimiters do not yield
239    empty fields.  (Ordinarily, only white space characters are
240    appropriate soft delimiters.)
241
242    The caller retains ownership of DELIMITERS.
243
244    This setting affects parsing of DP_DELIMITED files only. */
245 void
246 data_parser_set_soft_delimiters (struct data_parser *parser,
247                                  struct substring delimiters)
248 {
249   ss_dealloc (&parser->soft_seps);
250   ss_alloc_substring (&parser->soft_seps, delimiters);
251   set_any_sep (parser);
252 }
253
254 /* Sets PARSER's hard delimiters to DELIMITERS.  Hard delimiters
255    separate fields.  A consecutive pair of hard delimiters yield
256    an empty field.
257
258    The caller retains ownership of DELIMITERS.
259
260    This setting affects parsing of DP_DELIMITED files only. */
261 void
262 data_parser_set_hard_delimiters (struct data_parser *parser,
263                                  struct substring delimiters)
264 {
265   ss_dealloc (&parser->hard_seps);
266   ss_alloc_substring (&parser->hard_seps, delimiters);
267   set_any_sep (parser);
268 }
269
270 /* Returns the number of records per case. */
271 int
272 data_parser_get_records (const struct data_parser *parser)
273 {
274   return parser->records_per_case;
275 }
276
277 /* Sets the number of records per case to RECORDS_PER_CASE.
278
279    This setting affects parsing of DP_FIXED files only. */
280 void
281 data_parser_set_records (struct data_parser *parser, int records_per_case)
282 {
283   assert (records_per_case >= 0);
284   assert (records_per_case >= parser->records_per_case);
285   parser->records_per_case = records_per_case;
286 }
287
288 static void
289 add_field (struct data_parser *p, const struct fmt_spec *format, int case_idx,
290            const char *name, int record, int first_column)
291 {
292   struct field *field;
293
294   if (p->field_cnt == p->field_allocated)
295     p->fields = x2nrealloc (p->fields, &p->field_allocated, sizeof *p->fields);
296   field = &p->fields[p->field_cnt++];
297   field->format = *format;
298   field->case_idx = case_idx;
299   field->name = xstrdup (name);
300   field->record = record;
301   field->first_column = first_column;
302 }
303
304 /* Adds a delimited field to the field parsed by PARSER, which
305    must be configured as a DP_DELIMITED parser.  The field is
306    parsed as input format FORMAT.  Its data will be stored into case
307    index CASE_INDEX.  Errors in input data will be reported
308    against variable NAME. */
309 void
310 data_parser_add_delimited_field (struct data_parser *parser,
311                                  const struct fmt_spec *format, int case_idx,
312                                  const char *name)
313 {
314   assert (parser->type == DP_DELIMITED);
315   add_field (parser, format, case_idx, name, 0, 0);
316 }
317
318 /* Adds a fixed field to the field parsed by PARSER, which
319    must be configured as a DP_FIXED parser.  The field is
320    parsed as input format FORMAT.  Its data will be stored into case
321    index CASE_INDEX.  Errors in input data will be reported
322    against variable NAME.  The field will be drawn from the
323    FORMAT->w columns in 1-based RECORD starting at 1-based
324    column FIRST_COLUMN.
325
326    RECORD must be at least as great as that of any field already
327    added; that is, fields must be added in increasing order of
328    record number.  If RECORD is greater than the current number
329    of records per case, the number of records per case are
330    increased as needed.  */
331 void
332 data_parser_add_fixed_field (struct data_parser *parser,
333                              const struct fmt_spec *format, int case_idx,
334                              const char *name,
335                              int record, int first_column)
336 {
337   assert (parser->type == DP_FIXED);
338   assert (parser->field_cnt == 0
339           || record >= parser->fields[parser->field_cnt - 1].record);
340   if (record > parser->records_per_case)
341     parser->records_per_case = record;
342   add_field (parser, format, case_idx, name, record, first_column);
343 }
344
345 /* Returns true if any fields have been added to PARSER, false
346    otherwise. */
347 bool
348 data_parser_any_fields (const struct data_parser *parser)
349 {
350   return parser->field_cnt > 0;
351 }
352
353 static void
354 set_any_sep (struct data_parser *parser)
355 {
356   ds_assign_substring (&parser->any_sep, parser->soft_seps);
357   ds_put_substring (&parser->any_sep, parser->hard_seps);
358 }
359 \f
360 static bool parse_delimited_span (const struct data_parser *,
361                                   struct dfm_reader *, struct ccase *);
362 static bool parse_delimited_no_span (const struct data_parser *,
363                                      struct dfm_reader *, struct ccase *);
364 static bool parse_fixed (const struct data_parser *,
365                          struct dfm_reader *, struct ccase *);
366
367 /* Reads a case from DFM into C, parsing it with PARSER.  Returns
368    true if successful, false at end of file or on I/O error.
369
370    Case C must not be shared. */
371 bool
372 data_parser_parse (struct data_parser *parser, struct dfm_reader *reader,
373                    struct ccase *c)
374 {
375   bool retval;
376
377   assert (!case_is_shared (c));
378   assert (data_parser_any_fields (parser));
379
380   /* Skip the requested number of records before reading the
381      first case. */
382   for (; parser->skip_records > 0; parser->skip_records--)
383     {
384       if (dfm_eof (reader))
385         return false;
386       dfm_forward_record (reader);
387     }
388
389   /* Limit cases. */
390   if (parser->max_cases != -1 && parser->max_cases-- == 0)
391     return false;
392   if (parser->percent_cases < 100
393       && dfm_get_percent_read (reader) >= parser->percent_cases)
394     return false;
395
396   dfm_push (reader);
397   if (parser->type == DP_DELIMITED)
398     {
399       if (parser->span)
400         retval = parse_delimited_span (parser, reader, c);
401       else
402         retval = parse_delimited_no_span (parser, reader, c);
403     }
404   else
405     retval = parse_fixed (parser, reader, c);
406   dfm_pop (reader);
407
408   return retval;
409 }
410
411 /* Extracts a delimited field from the current position in the
412    current record according to PARSER, reading data from READER.
413
414    *FIELD is set to the field content.  The caller must not or
415    destroy this constant string.
416
417    After parsing the field, sets the current position in the
418    record to just past the field and any trailing delimiter.
419    Returns 0 on failure or a 1-based column number indicating the
420    beginning of the field on success. */
421 static bool
422 cut_field (const struct data_parser *parser, struct dfm_reader *reader,
423            int *first_column, int *last_column, struct string *tmp,
424            struct substring *field)
425 {
426   struct substring line, p;
427
428   if (dfm_eof (reader))
429     return false;
430   if (ss_is_empty (parser->hard_seps))
431     dfm_expand_tabs (reader);
432   line = p = dfm_get_record (reader);
433
434   /* Skip leading soft separators. */
435   ss_ltrim (&p, parser->soft_seps);
436
437   /* Handle empty or completely consumed lines. */
438   if (ss_is_empty (p))
439     {
440       if (!parser->empty_line_has_field || dfm_columns_past_end (reader) > 0)
441         return false;
442       else
443         {
444           *field = p;
445           *first_column = dfm_column_start (reader);
446           *last_column = *first_column + 1;
447           dfm_forward_columns (reader, 1);
448           return true;
449         }
450     }
451
452   *first_column = dfm_column_start (reader);
453   if (ss_find_char (parser->quotes, ss_first (p)) != SIZE_MAX)
454     {
455       /* Quoted field. */
456       int quote = ss_get_char (&p);
457       if (!ss_get_until (&p, quote, field))
458         msg (SW, _("Quoted string extends beyond end of line."));
459       if (parser->quote_escape && ss_first (p) == quote)
460         {
461           ds_assign_substring (tmp, *field);
462           while (ss_match_char (&p, quote))
463             {
464               struct substring ss;
465               ds_put_char (tmp, quote);
466               if (!ss_get_until (&p, quote, &ss))
467                 msg (SW, _("Quoted string extends beyond end of line."));
468               ds_put_substring (tmp, ss);
469             }
470           *field = ds_ss (tmp);
471         }
472       *last_column = dfm_column_start (reader);
473
474       /* Skip trailing soft separator and a single hard separator
475          if present. */
476       ss_ltrim (&p, parser->soft_seps);
477       if (!ss_is_empty (p)
478           && ss_find_char (parser->hard_seps, ss_first (p)) != SIZE_MAX)
479         ss_advance (&p, 1);
480     }
481   else
482     {
483       /* Regular field. */
484       ss_get_chars (&p, ss_cspan (p, ds_ss (&parser->any_sep)), field);
485       *last_column = dfm_column_start (reader);
486       if (!ss_ltrim (&p, parser->soft_seps) || ss_is_empty (p))
487         {
488           /* Advance past a trailing hard separator,
489              regardless of whether one actually existed.  If
490              we "skip" a delimiter that was not actually
491              there, then we will return end-of-line on our
492              next call, which is what we want. */
493           dfm_forward_columns (reader, 1);
494         }
495     }
496   dfm_forward_columns (reader, ss_length (line) - ss_length (p));
497
498   return true;
499 }
500
501 /* Reads a case from READER into C, parsing it according to
502    fixed-format syntax rules in PARSER.
503    Returns true if successful, false at end of file or on I/O error. */
504 static bool
505 parse_fixed (const struct data_parser *parser, struct dfm_reader *reader,
506              struct ccase *c)
507 {
508   const char *encoding = dfm_reader_get_legacy_encoding (reader);
509   struct field *f;
510   int row;
511
512   if (dfm_eof (reader))
513     return false;
514
515   f = parser->fields;
516   for (row = 1; row <= parser->records_per_case; row++)
517     {
518       struct substring line;
519
520       if (dfm_eof (reader))
521         {
522           msg (SW, _("Partial case of %d of %d records discarded."),
523                row - 1, parser->records_per_case);
524           return false;
525         }
526       dfm_expand_tabs (reader);
527       line = dfm_get_record (reader);
528
529       for (; f < &parser->fields[parser->field_cnt] && f->record == row; f++)
530         data_in (ss_substr (line, f->first_column - 1,
531                             f->format.w),
532                  encoding, f->format.type, f->format.d,
533                  f->first_column, f->first_column + f->format.w,
534                  case_data_rw_idx (c, f->case_idx),
535                  fmt_var_width (&f->format));
536
537       dfm_forward_record (reader);
538     }
539
540   return true;
541 }
542
543 /* Reads a case from READER into C, parsing it according to
544    free-format syntax rules in PARSER.
545    Returns true if successful, false at end of file or on I/O error. */
546 static bool
547 parse_delimited_span (const struct data_parser *parser,
548                       struct dfm_reader *reader, struct ccase *c)
549 {
550   const char *encoding = dfm_reader_get_legacy_encoding (reader);
551   struct string tmp = DS_EMPTY_INITIALIZER;
552   struct field *f;
553
554   for (f = parser->fields; f < &parser->fields[parser->field_cnt]; f++)
555     {
556       struct substring s;
557       int first_column, last_column;
558
559       /* Cut out a field and read in a new record if necessary. */
560       while (!cut_field (parser, reader,
561                          &first_column, &last_column, &tmp, &s))
562         {
563           if (!dfm_eof (reader))
564             dfm_forward_record (reader);
565           if (dfm_eof (reader))
566             {
567               if (f > parser->fields)
568                 msg (SW, _("Partial case discarded.  The first variable "
569                            "missing was %s."), f->name);
570               ds_destroy (&tmp);
571               return false;
572             }
573         }
574
575       data_in (s, encoding, f->format.type, 0,
576                first_column, last_column,
577                case_data_rw_idx (c, f->case_idx),
578                fmt_var_width (&f->format));
579     }
580   ds_destroy (&tmp);
581   return true;
582 }
583
584 /* Reads a case from READER into C, parsing it according to
585    delimited syntax rules with one case per record in PARSER.
586    Returns true if successful, false at end of file or on I/O error. */
587 static bool
588 parse_delimited_no_span (const struct data_parser *parser,
589                          struct dfm_reader *reader, struct ccase *c)
590 {
591   const char *encoding = dfm_reader_get_legacy_encoding (reader);
592   struct string tmp = DS_EMPTY_INITIALIZER;
593   struct substring s;
594   struct field *f;
595
596   if (dfm_eof (reader))
597     return false;
598
599   for (f = parser->fields; f < &parser->fields[parser->field_cnt]; f++)
600     {
601       int first_column, last_column;
602       if (!cut_field (parser, reader, &first_column, &last_column, &tmp, &s))
603         {
604           if (settings_get_undefined ())
605             msg (SW, _("Missing value(s) for all variables from %s onward.  "
606                        "These will be filled with the system-missing value "
607                        "or blanks, as appropriate."),
608                  f->name);
609           for (; f < &parser->fields[parser->field_cnt]; f++)
610             value_set_missing (case_data_rw_idx (c, f->case_idx),
611                                fmt_var_width (&f->format));
612           goto exit;
613         }
614
615       data_in (s, encoding, f->format.type, 0,
616                first_column, last_column,
617                case_data_rw_idx (c, f->case_idx),
618                fmt_var_width (&f->format));
619     }
620
621   s = dfm_get_record (reader);
622   ss_ltrim (&s, parser->soft_seps);
623   if (!ss_is_empty (s))
624     msg (SW, _("Record ends in data not part of any field."));
625
626 exit:
627   dfm_forward_record (reader);
628   ds_destroy (&tmp);
629   return true;
630 }
631 \f
632 /* Displays a table giving information on fixed-format variable
633    parsing on DATA LIST. */
634 static void
635 dump_fixed_table (const struct data_parser *parser,
636                   const struct file_handle *fh)
637 {
638   struct tab_table *t;
639   size_t i;
640
641   t = tab_create (4, parser->field_cnt + 1, 0);
642   tab_columns (t, TAB_COL_DOWN, 1);
643   tab_headers (t, 0, 0, 1, 0);
644   tab_text (t, 0, 0, TAB_CENTER | TAT_TITLE, _("Variable"));
645   tab_text (t, 1, 0, TAB_CENTER | TAT_TITLE, _("Record"));
646   tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("Columns"));
647   tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("Format"));
648   tab_box (t, TAL_1, TAL_1, TAL_0, TAL_1, 0, 0, 3, parser->field_cnt);
649   tab_hline (t, TAL_2, 0, 3, 1);
650   tab_dim (t, tab_natural_dimensions, NULL);
651
652   for (i = 0; i < parser->field_cnt; i++)
653     {
654       struct field *f = &parser->fields[i];
655       char fmt_string[FMT_STRING_LEN_MAX + 1];
656       int row = i + 1;
657
658       tab_text (t, 0, row, TAB_LEFT, f->name);
659       tab_text (t, 1, row, TAT_PRINTF, "%d", f->record);
660       tab_text (t, 2, row, TAT_PRINTF, "%3d-%3d",
661                 f->first_column, f->first_column + f->format.w - 1);
662       tab_text (t, 3, row, TAB_LEFT | TAB_FIX,
663                 fmt_to_string (&f->format, fmt_string));
664     }
665
666   tab_title (t, ngettext ("Reading %d record from %s.",
667                           "Reading %d records from %s.",
668                           parser->records_per_case),
669              parser->records_per_case, fh_get_name (fh));
670   tab_submit (t);
671 }
672
673 /* Displays a table giving information on free-format variable parsing
674    on DATA LIST. */
675 static void
676 dump_delimited_table (const struct data_parser *parser,
677                       const struct file_handle *fh)
678 {
679   struct tab_table *t;
680   size_t i;
681
682   t = tab_create (2, parser->field_cnt + 1, 0);
683   tab_columns (t, TAB_COL_DOWN, 1);
684   tab_headers (t, 0, 0, 1, 0);
685   tab_text (t, 0, 0, TAB_CENTER | TAT_TITLE, _("Variable"));
686   tab_text (t, 1, 0, TAB_CENTER | TAT_TITLE, _("Format"));
687   tab_box (t, TAL_1, TAL_1, TAL_0, TAL_1, 0, 0, 1, parser->field_cnt);
688   tab_hline (t, TAL_2, 0, 1, 1);
689   tab_dim (t, tab_natural_dimensions, NULL);
690
691   for (i = 0; i < parser->field_cnt; i++)
692     {
693       struct field *f = &parser->fields[i];
694       char str[FMT_STRING_LEN_MAX + 1];
695       int row = i + 1;
696
697       tab_text (t, 0, row, TAB_LEFT, f->name);
698       tab_text (t, 1, row, TAB_LEFT | TAB_FIX,
699                 fmt_to_string (&f->format, str));
700     }
701
702   tab_title (t, _("Reading free-form data from %s."), fh_get_name (fh));
703
704   tab_submit (t);
705 }
706
707 /* Displays a table giving information on how PARSER will read
708    data from FH. */
709 void
710 data_parser_output_description (struct data_parser *parser,
711                                 const struct file_handle *fh)
712 {
713   if (parser->type == DP_FIXED)
714     dump_fixed_table (parser, fh);
715   else
716     dump_delimited_table (parser, fh);
717 }
718 \f
719 /* Data parser input program. */
720 struct data_parser_casereader
721   {
722     struct data_parser *parser; /* Parser. */
723     struct dfm_reader *reader;  /* Data file reader. */
724     struct caseproto *proto;    /* Format of cases. */
725   };
726
727 static const struct casereader_class data_parser_casereader_class;
728
729 /* Replaces DS's active file by an input program that reads data
730    from READER according to the rules in PARSER, using DICT as
731    the underlying dictionary.  Ownership of PARSER and READER is
732    transferred to the input program, and ownership of DICT is
733    transferred to the dataset. */
734 void
735 data_parser_make_active_file (struct data_parser *parser, struct dataset *ds,
736                               struct dfm_reader *reader,
737                               struct dictionary *dict)
738 {
739   struct data_parser_casereader *r;
740   struct casereader *casereader;
741
742   r = xmalloc (sizeof *r);
743   r->parser = parser;
744   r->reader = reader;
745   r->proto = caseproto_ref (dict_get_proto (dict));
746   casereader = casereader_create_sequential (NULL, r->proto,
747                                              CASENUMBER_MAX,
748                                              &data_parser_casereader_class, r);
749   proc_set_active_file (ds, casereader, dict);
750 }
751
752 static struct ccase *
753 data_parser_casereader_read (struct casereader *reader UNUSED, void *r_)
754 {
755   struct data_parser_casereader *r = r_;
756   struct ccase *c = case_create (r->proto);
757   if (data_parser_parse (r->parser, r->reader, c))
758     return c;
759   else
760     {
761       case_unref (c);
762       return NULL;
763     }
764 }
765
766 static void
767 data_parser_casereader_destroy (struct casereader *reader UNUSED, void *r_)
768 {
769   struct data_parser_casereader *r = r_;
770   if (dfm_reader_error (r->reader))
771     casereader_force_error (reader);
772   data_parser_destroy (r->parser);
773   dfm_close_reader (r->reader);
774   caseproto_unref (r->proto);
775   free (r);
776 }
777
778 static const struct casereader_class data_parser_casereader_class =
779   {
780     data_parser_casereader_read,
781     data_parser_casereader_destroy,
782     NULL,
783     NULL,
784   };