Remove unneeded #includes.
[pspp] / src / language / data-io / data-reader.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-2004, 2006, 2010, 2011, 2012, 2016 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-reader.h"
20
21 #include <ctype.h>
22 #include <errno.h>
23 #include <stdint.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26
27 #include "data/casereader.h"
28 #include "data/dataset.h"
29 #include "data/file-handle-def.h"
30 #include "data/file-name.h"
31 #include "language/command.h"
32 #include "language/data-io/file-handle.h"
33 #include "language/lexer/lexer.h"
34 #include "libpspp/assertion.h"
35 #include "libpspp/cast.h"
36 #include "libpspp/encoding-guesser.h"
37 #include "libpspp/integer-format.h"
38 #include "libpspp/line-reader.h"
39 #include "libpspp/message.h"
40 #include "libpspp/str.h"
41
42 #include "gl/minmax.h"
43 #include "gl/xalloc.h"
44
45 #include "gettext.h"
46 #define _(msgid) gettext (msgid)
47 #define N_(msgid) (msgid)
48
49 /* Flags for DFM readers. */
50 enum dfm_reader_flags
51   {
52     DFM_ADVANCE = 002,          /* Read next line on dfm_get_record() call? */
53     DFM_SAW_BEGIN_DATA = 004,   /* For inline_file only, whether we've
54                                    already read a BEGIN DATA line. */
55     DFM_TABS_EXPANDED = 010,    /* Tabs have been expanded. */
56     DFM_CONSUME = 020           /* read_inline_record() should get a token? */
57   };
58
59 /* Data file reader. */
60 struct dfm_reader
61   {
62     struct file_handle *fh;     /* File handle. */
63     struct fh_lock *lock;       /* Mutual exclusion lock for file. */
64     int line_number;            /* Current line or record number. */
65     struct string line;         /* Current line. */
66     struct string scratch;      /* Extra line buffer. */
67     enum dfm_reader_flags flags; /* Zero or more of DFM_*. */
68     FILE *file;                 /* Associated file. */
69     size_t pos;                 /* Offset in line of current character. */
70     unsigned n_eofs;            /* # of attempts to advance past EOF. */
71     struct lexer *lexer;        /* The lexer reading the file */
72     char *encoding;             /* Current encoding. */
73
74     /* For FH_MODE_TEXT only. */
75     struct line_reader *line_reader;
76
77     /* For FH_MODE_360_VARIABLE and FH_MODE_360_SPANNED files only. */
78     size_t block_left;          /* Bytes left in current block. */
79   };
80
81 /* Closes reader R opened by dfm_open_reader(). */
82 void
83 dfm_close_reader (struct dfm_reader *r)
84 {
85   if (r == NULL)
86     return;
87
88   if (fh_unlock (r->lock))
89     {
90       /* File is still locked by another client. */
91       return;
92     }
93
94   /* This was the last client, so close the underlying file. */
95   if (fh_get_referent (r->fh) != FH_REF_INLINE)
96     fn_close (r->fh, r->file);
97   else
98     {
99       /* Skip any remaining data on the inline file. */
100       if (r->flags & DFM_SAW_BEGIN_DATA)
101         {
102           dfm_reread_record (r, 0);
103           while (!dfm_eof (r))
104             dfm_forward_record (r);
105         }
106     }
107
108   line_reader_free (r->line_reader);
109   free (r->encoding);
110   fh_unref (r->fh);
111   ds_destroy (&r->line);
112   ds_destroy (&r->scratch);
113   free (r);
114 }
115
116 /* Opens the file designated by file handle FH for reading as a data file.
117    Returns a reader if successful, or a null pointer otherwise.
118
119    If FH is fh_inline_file() then the new reader reads data included inline in
120    the command file between BEGIN FILE and END FILE, obtaining data from LEXER.
121    LEXER must remain valid as long as the new reader is in use.  ENCODING is
122    ignored.
123
124    If FH is not fh_inline_file(), then the encoding of the file read is by
125    default that of FH itself.  If ENCODING is nonnull, then it overrides the
126    default encoding.  LEXER is ignored. */
127 struct dfm_reader *
128 dfm_open_reader (struct file_handle *fh, struct lexer *lexer,
129                  const char *encoding)
130 {
131   struct dfm_reader *r;
132   struct fh_lock *lock;
133
134   /* TRANSLATORS: this fragment will be interpolated into
135      messages in fh_lock() that identify types of files. */
136   lock = fh_lock (fh, FH_REF_FILE | FH_REF_INLINE, N_("data file"),
137                   FH_ACC_READ, false);
138   if (lock == NULL)
139     return NULL;
140
141   r = fh_lock_get_aux (lock);
142   if (r != NULL)
143     return r;
144
145   r = xmalloc (sizeof *r);
146   r->fh = fh_ref (fh);
147   r->lock = lock;
148   r->lexer = lexer;
149   ds_init_empty (&r->line);
150   ds_init_empty (&r->scratch);
151   r->flags = DFM_ADVANCE;
152   r->n_eofs = 0;
153   r->block_left = 0;
154   if (fh_get_referent (fh) != FH_REF_INLINE)
155     {
156       r->line_number = 0;
157       r->file = fn_open (fh, "rb");
158       if (r->file == NULL)
159         {
160           msg (ME, _("Could not open `%s' for reading as a data file: %s."),
161                fh_get_file_name (r->fh), strerror (errno));
162           goto error;
163         }
164     }
165   fh_lock_set_aux (lock, r);
166
167   if (encoding == NULL)
168     encoding = fh_get_encoding (fh);
169   if (fh_get_referent (fh) == FH_REF_FILE && fh_get_mode (fh) == FH_MODE_TEXT)
170     {
171       r->line_reader = line_reader_for_fd (encoding, fileno (r->file));
172       if (r->line_reader == NULL)
173         {
174           msg (ME, _("Could not read `%s' as a text file with encoding `%s': "
175                      "%s."),
176                fh_get_file_name (r->fh), encoding, strerror (errno));
177           goto error;
178         }
179       r->encoding = xstrdup (line_reader_get_encoding (r->line_reader));
180     }
181   else
182     {
183       r->line_reader = NULL;
184       r->encoding = xstrdup (encoding_guess_parse_encoding (encoding));
185     }
186
187   return r;
188
189 error:
190   fh_unlock (r->lock);
191   fh_unref (fh);
192   free (r);
193   return NULL;
194 }
195
196 /* Returns true if an I/O error occurred on READER, false otherwise. */
197 bool
198 dfm_reader_error (const struct dfm_reader *r)
199 {
200   return (fh_get_referent (r->fh) == FH_REF_FILE
201           && (r->line_reader != NULL
202               ? line_reader_error (r->line_reader) != 0
203               : ferror (r->file)));
204 }
205
206 /* Reads a record from the inline file into R.
207    Returns true if successful, false on failure. */
208 static bool
209 read_inline_record (struct dfm_reader *r)
210 {
211   if ((r->flags & DFM_SAW_BEGIN_DATA) == 0)
212     {
213       r->flags |= DFM_SAW_BEGIN_DATA;
214       r->flags &= ~DFM_CONSUME;
215
216       while (lex_token (r->lexer) == T_ENDCMD)
217         lex_get (r->lexer);
218
219       if (!lex_force_match_phrase (r->lexer, "BEGIN DATA"))
220         return false;
221
222       lex_match (r->lexer, T_ENDCMD);
223     }
224
225   if (r->flags & DFM_CONSUME)
226     lex_get (r->lexer);
227
228   if (!lex_is_string (r->lexer))
229     {
230       if (!lex_match_id (r->lexer, "END") || !lex_match_id (r->lexer, "DATA"))
231         {
232           msg (SE, _("Missing %s while reading inline data.  "
233                      "This probably indicates a missing or incorrectly "
234                      "formatted %s command.  %s must appear "
235                      "by itself on a single line with exactly one space "
236                      "between words."), "END DATA", "END DATA", "END DATA");
237           lex_discard_rest_of_command (r->lexer);
238         }
239       return false;
240     }
241
242   ds_assign_substring (&r->line, lex_tokss (r->lexer));
243   r->flags |= DFM_CONSUME;
244
245   return true;
246 }
247
248 /* Report a read error on R. */
249 static void
250 read_error (struct dfm_reader *r)
251 {
252   msg (ME, _("Error reading file %s: %s."),
253        fh_get_name (r->fh), strerror (errno));
254 }
255
256 /* Report a partial read at end of file reading R. */
257 static void
258 partial_record (struct dfm_reader *r)
259 {
260   msg (ME, _("Unexpected end of file in partial record reading %s."),
261        fh_get_name (r->fh));
262 }
263
264 /* Tries to read SIZE bytes from R into BUFFER.  Returns 1 if
265    successful, 0 if end of file was reached before any bytes
266    could be read, and -1 if some bytes were read but fewer than
267    SIZE due to end of file or an error mid-read.  In the latter
268    case, reports an error. */
269 static int
270 try_to_read_fully (struct dfm_reader *r, void *buffer, size_t size)
271 {
272   size_t bytes_read = fread (buffer, 1, size, r->file);
273   if (bytes_read == size)
274     return 1;
275   else if (bytes_read == 0)
276     return 0;
277   else
278     {
279       partial_record (r);
280       return -1;
281     }
282 }
283
284 /* Type of a descriptor word. */
285 enum descriptor_type
286   {
287     BLOCK,
288     RECORD
289   };
290
291 /* Reads a block descriptor word or record descriptor word
292    (according to TYPE) from R.  Returns 1 if successful, 0 if
293    end of file was reached before any bytes could be read, -1 if
294    an error occurred.  Reports an error in the latter case.
295
296    If successful, stores the number of remaining bytes in the
297    block or record (that is, the block or record length, minus
298    the 4 bytes in the BDW or RDW itself) into *REMAINING_SIZE.
299    If SEGMENT is nonnull, also stores the segment control
300    character (SCC) into *SEGMENT. */
301 static int
302 read_descriptor_word (struct dfm_reader *r, enum descriptor_type type,
303                       size_t *remaining_size, int *segment)
304 {
305   uint8_t raw_descriptor[4];
306   int status;
307
308   status = try_to_read_fully (r, raw_descriptor, sizeof raw_descriptor);
309   if (status <= 0)
310     return status;
311
312   *remaining_size = (raw_descriptor[0] << 8) | raw_descriptor[1];
313   if (segment != NULL)
314     *segment = raw_descriptor[2];
315
316   if (*remaining_size < 4)
317     {
318       msg (ME,
319            (type == BLOCK
320             ? _("Corrupt block descriptor word at offset 0x%lx in %s.")
321             : _("Corrupt record descriptor word at offset 0x%lx in %s.")),
322            (long) ftello (r->file) - 4, fh_get_name (r->fh));
323       return -1;
324     }
325
326   *remaining_size -= 4;
327   return 1;
328 }
329
330 /* Reports that reader R has read a corrupt record size. */
331 static void
332 corrupt_size (struct dfm_reader *r)
333 {
334   msg (ME, _("Corrupt record size at offset 0x%lx in %s."),
335        (long) ftello (r->file) - 4, fh_get_name (r->fh));
336 }
337
338 /* Reads a 32-byte little-endian signed number from R and stores
339    its value into *SIZE_OUT.  Returns 1 if successful, 0 if end
340    of file was reached before any bytes could be read, -1 if an
341    error occurred.  Reports an error in the latter case.  Numbers
342    less than 0 are considered errors. */
343 static int
344 read_size (struct dfm_reader *r, size_t *size_out)
345 {
346   int32_t size;
347   int status;
348
349   status = try_to_read_fully (r, &size, sizeof size);
350   if (status <= 0)
351     return status;
352
353   integer_convert (INTEGER_LSB_FIRST, &size, INTEGER_NATIVE, &size,
354                    sizeof size);
355   if (size < 0)
356     {
357       corrupt_size (r);
358       return -1;
359     }
360
361   *size_out = size;
362   return 1;
363 }
364
365 static bool
366 read_text_record (struct dfm_reader *r)
367 {
368   bool is_auto;
369   bool ok;
370
371   /* Read a line.  If the line reader's encoding changes, update r->encoding to
372      match. */
373   is_auto = line_reader_is_auto (r->line_reader);
374   ok = line_reader_read (r->line_reader, &r->line, SIZE_MAX);
375   if (is_auto && !line_reader_is_auto (r->line_reader))
376     {
377       free (r->encoding);
378       r->encoding = xstrdup (line_reader_get_encoding (r->line_reader));
379     }
380
381   /* Detect and report read error. */
382   if (!ok)
383     {
384       int error = line_reader_error (r->line_reader);
385       if (error != 0)
386         msg (ME, _("Error reading file %s: %s."),
387              fh_get_name (r->fh), strerror (error));
388     }
389
390   return ok;
391 }
392
393 /* Reads a record from a disk file into R.
394    Returns true if successful, false on error or at end of file. */
395 static bool
396 read_file_record (struct dfm_reader *r)
397 {
398   assert (r->fh != fh_inline_file ());
399
400   ds_clear (&r->line);
401   switch (fh_get_mode (r->fh))
402     {
403     case FH_MODE_TEXT:
404       return read_text_record (r);
405
406     case FH_MODE_FIXED:
407       if (ds_read_stream (&r->line, 1, fh_get_record_width (r->fh), r->file))
408         return true;
409       else
410         {
411           if (ferror (r->file))
412             read_error (r);
413           else if (!ds_is_empty (&r->line))
414             partial_record (r);
415           return false;
416         }
417
418     case FH_MODE_VARIABLE:
419       {
420         size_t leading_size;
421         size_t trailing_size;
422         int status;
423
424         /* Read leading record size. */
425         status = read_size (r, &leading_size);
426         if (status <= 0)
427           return false;
428
429         /* Read record data. */
430         if (!ds_read_stream (&r->line, leading_size, 1, r->file))
431           {
432             if (ferror (r->file))
433               read_error (r);
434             else
435               partial_record (r);
436             return false;
437           }
438
439         /* Read trailing record size and check that it's the same
440            as the leading record size. */
441         status = read_size (r, &trailing_size);
442         if (status <= 0)
443           {
444             if (status == 0)
445               partial_record (r);
446             return false;
447           }
448         if (leading_size != trailing_size)
449           {
450             corrupt_size (r);
451             return false;
452           }
453
454         return true;
455       }
456
457     case FH_MODE_360_VARIABLE:
458     case FH_MODE_360_SPANNED:
459       for (;;)
460         {
461           size_t record_size;
462           int segment;
463           int status;
464
465           /* If we've exhausted our current block, start another
466              one by reading the new block descriptor word. */
467           if (r->block_left == 0)
468             {
469               status = read_descriptor_word (r, BLOCK, &r->block_left, NULL);
470               if (status < 0)
471                 return false;
472               else if (status == 0)
473                 return !ds_is_empty (&r->line);
474             }
475
476           /* Read record descriptor. */
477           if (r->block_left < 4)
478             {
479               partial_record (r);
480               return false;
481             }
482           r->block_left -= 4;
483           status = read_descriptor_word (r, RECORD, &record_size, &segment);
484           if (status <= 0)
485             {
486               if (status == 0)
487                 partial_record (r);
488               return false;
489             }
490           if (record_size > r->block_left)
491             {
492               msg (ME, _("Record exceeds remaining block length."));
493               return false;
494             }
495
496           /* Read record data. */
497           if (!ds_read_stream (&r->line, record_size, 1, r->file))
498             {
499               if (ferror (r->file))
500                 read_error (r);
501               else
502                 partial_record (r);
503               return false;
504             }
505           r->block_left -= record_size;
506
507           /* In variable mode, read only a single record.
508              In spanned mode, a segment value of 0 should
509              designate a whole record without spanning, 1 the
510              first segment in a record, 2 the last segment in a
511              record, and 3 an intermediate segment in a record.
512              For compatibility, though, we actually pay attention
513              only to whether the segment value is even or odd. */
514           if (fh_get_mode (r->fh) == FH_MODE_360_VARIABLE
515               || (segment & 1) == 0)
516             return true;
517         }
518     }
519
520   NOT_REACHED ();
521 }
522
523 /* Reads a record from R, setting the current position to the
524    start of the line.  If an error occurs or end-of-file is
525    encountered, the current line is set to null. */
526 static bool
527 read_record (struct dfm_reader *r)
528 {
529   if (fh_get_referent (r->fh) == FH_REF_FILE)
530     {
531       bool ok = read_file_record (r);
532       if (ok)
533         r->line_number++;
534       return ok;
535     }
536   else
537     return read_inline_record (r);
538 }
539
540 /* Returns the number of attempts, thus far, to advance past
541    end-of-file in reader R.  Reads forward in HANDLE's file, if
542    necessary, to find out.
543
544    Normally, the user stops attempting to read from the file the
545    first time EOF is reached (a return value of 1).  If the user
546    tries to read past EOF again (a return value of 2 or more),
547    an error message is issued, and the caller should more
548    forcibly abort to avoid an infinite loop. */
549 unsigned
550 dfm_eof (struct dfm_reader *r)
551 {
552   if (r->flags & DFM_ADVANCE)
553     {
554       r->flags &= ~DFM_ADVANCE;
555
556       if (r->n_eofs == 0 && read_record (r))
557         {
558           r->pos = 0;
559           return 0;
560         }
561
562       r->n_eofs++;
563       if (r->n_eofs == 2)
564         {
565           if (r->fh != fh_inline_file ())
566             msg (ME, _("Attempt to read beyond end-of-file on file %s."),
567                  fh_get_name (r->fh));
568           else
569             msg (ME, _("Attempt to read beyond %s."), "END DATA");
570         }
571     }
572
573   return r->n_eofs;
574 }
575
576 /* Returns the current record in the file corresponding to
577    HANDLE.  Aborts if reading from the file is necessary or at
578    end of file, so call dfm_eof() first. */
579 struct substring
580 dfm_get_record (struct dfm_reader *r)
581 {
582   assert ((r->flags & DFM_ADVANCE) == 0);
583   assert (r->n_eofs == 0);
584
585   return ds_substr (&r->line, r->pos, SIZE_MAX);
586 }
587
588 /* Expands tabs in the current line into the equivalent number of
589    spaces, if appropriate for this kind of file.  Aborts if
590    reading from the file is necessary or at end of file, so call
591    dfm_eof() first.*/
592 void
593 dfm_expand_tabs (struct dfm_reader *r)
594 {
595   size_t ofs, new_pos, tab_width;
596
597   assert ((r->flags & DFM_ADVANCE) == 0);
598   assert (r->n_eofs == 0);
599
600   if (r->flags & DFM_TABS_EXPANDED)
601     return;
602   r->flags |= DFM_TABS_EXPANDED;
603
604   if (r->fh != fh_inline_file ()
605       && (fh_get_mode (r->fh) != FH_MODE_TEXT
606           || fh_get_tab_width (r->fh) == 0
607           || ds_find_byte (&r->line, '\t') == SIZE_MAX))
608     return;
609
610   /* Expand tabs from r->line into r->scratch, and figure out
611      new value for r->pos. */
612   tab_width = fh_get_tab_width (r->fh);
613   ds_clear (&r->scratch);
614   new_pos = SIZE_MAX;
615   for (ofs = 0; ofs < ds_length (&r->line); ofs++)
616     {
617       unsigned char c;
618
619       if (ofs == r->pos)
620         new_pos = ds_length (&r->scratch);
621
622       c = ds_data (&r->line)[ofs];
623       if (c != '\t')
624         ds_put_byte (&r->scratch, c);
625       else
626         {
627           do
628             ds_put_byte (&r->scratch, ' ');
629           while (ds_length (&r->scratch) % tab_width != 0);
630         }
631     }
632   if (new_pos == SIZE_MAX)
633     {
634       /* Maintain the same relationship between position and line
635          length that we had before.  DATA LIST uses a
636          beyond-the-end position to deal with an empty field at
637          the end of the line. */
638       assert (r->pos >= ds_length (&r->line));
639       new_pos = (r->pos - ds_length (&r->line)) + ds_length (&r->scratch);
640     }
641
642   /* Swap r->line and r->scratch and set new r->pos. */
643   ds_swap (&r->line, &r->scratch);
644   r->pos = new_pos;
645 }
646
647 /* Returns the character encoding of data read from READER. */
648 const char *
649 dfm_reader_get_encoding (const struct dfm_reader *reader)
650 {
651   return reader->encoding;
652 }
653
654 /* Causes dfm_get_record() or dfm_get_whole_record() to read in
655    the next record the next time it is executed on file
656    HANDLE. */
657 void
658 dfm_forward_record (struct dfm_reader *r)
659 {
660   r->flags |= DFM_ADVANCE;
661 }
662
663 /* Cancels the effect of any previous dfm_fwd_record() executed
664    on file HANDLE.  Sets the current line to begin in the 1-based
665    column COLUMN.  */
666 void
667 dfm_reread_record (struct dfm_reader *r, size_t column)
668 {
669   r->flags &= ~DFM_ADVANCE;
670   r->pos = MAX (column, 1) - 1;
671 }
672
673 /* Sets the current line to begin COLUMNS characters following
674    the current start. */
675 void
676 dfm_forward_columns (struct dfm_reader *r, size_t columns)
677 {
678   dfm_reread_record (r, (r->pos + 1) + columns);
679 }
680
681 /* Returns the 1-based column to which the line pointer in HANDLE
682    is set.  Unless dfm_reread_record() or dfm_forward_columns()
683    have been called, this is 1. */
684 size_t
685 dfm_column_start (const struct dfm_reader *r)
686 {
687   return r->pos + 1;
688 }
689
690 /* Returns the number of columns we are currently beyond the end
691    of the line.  At or before end-of-line, this is 0; one column
692    after end-of-line, this is 1; and so on. */
693 size_t
694 dfm_columns_past_end (const struct dfm_reader *r)
695 {
696   return r->pos < ds_length (&r->line) ? 0 : ds_length (&r->line) - r->pos;
697 }
698
699 /* Returns the 1-based column within the current line that P
700    designates. */
701 size_t
702 dfm_get_column (const struct dfm_reader *r, const char *p)
703 {
704   return ds_pointer_to_position (&r->line, p) + 1;
705 }
706
707 const char *
708 dfm_get_file_name (const struct dfm_reader *r)
709 {
710   enum fh_referent referent = fh_get_referent (r->fh);
711   return (referent == FH_REF_FILE ? fh_get_file_name (r->fh)
712           : referent == FH_REF_INLINE ? lex_get_file_name (r->lexer)
713           : NULL);
714 }
715
716 int
717 dfm_get_line_number (const struct dfm_reader *r)
718 {
719   switch (fh_get_referent (r->fh))
720     {
721     case FH_REF_FILE:
722       return r->line_number;
723
724     case FH_REF_INLINE:
725       return lex_ofs_start_point (r->lexer, lex_ofs (r->lexer)).line;
726
727     case FH_REF_DATASET:
728     default:
729       return -1;
730     }
731 }
732 \f
733 /* BEGIN DATA...END DATA procedure. */
734
735 /* Perform BEGIN DATA...END DATA as a procedure in itself. */
736 int
737 cmd_begin_data (struct lexer *lexer, struct dataset *ds)
738 {
739   struct dfm_reader *r;
740   bool ok;
741
742   if (!fh_is_locked (fh_inline_file (), FH_ACC_READ))
743     {
744       lex_ofs_error (lexer, 0, lex_ofs (lexer) - 1,
745                      _("This command is not valid here since the current "
746                        "input program does not access the inline file."));
747       return CMD_CASCADING_FAILURE;
748     }
749   lex_match (lexer, T_ENDCMD);
750
751   /* Open inline file. */
752   r = dfm_open_reader (fh_inline_file (), lexer, NULL);
753   r->flags |= DFM_SAW_BEGIN_DATA;
754   r->flags &= ~DFM_CONSUME;
755
756   /* Input procedure reads from inline file. */
757   casereader_destroy (proc_open (ds));
758   ok = proc_commit (ds);
759   dfm_close_reader (r);
760
761   return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE;
762 }