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 eof_cnt; /* # 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
dfm_close_reader(struct dfm_reader * r)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 *
dfm_open_reader(struct file_handle * fh,struct lexer * lexer,const char * encoding)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->eof_cnt = 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
dfm_reader_error(const struct dfm_reader * r)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
read_inline_record(struct dfm_reader * r)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_id (r->lexer, "BEGIN")
220 || !lex_force_match_id (r->lexer, "DATA"))
221 return false;
222
223 lex_match (r->lexer, T_ENDCMD);
224 }
225
226 if (r->flags & DFM_CONSUME)
227 lex_get (r->lexer);
228
229 if (!lex_is_string (r->lexer))
230 {
231 if (!lex_match_id (r->lexer, "END") || !lex_match_id (r->lexer, "DATA"))
232 {
233 msg (SE, _("Missing %s while reading inline data. "
234 "This probably indicates a missing or incorrectly "
235 "formatted %s command. %s must appear "
236 "by itself on a single line with exactly one space "
237 "between words."), "END DATA", "END DATA", "END DATA");
238 lex_discard_rest_of_command (r->lexer);
239 }
240 return false;
241 }
242
243 ds_assign_substring (&r->line, lex_tokss (r->lexer));
244 r->flags |= DFM_CONSUME;
245
246 return true;
247 }
248
249 /* Report a read error on R. */
250 static void
read_error(struct dfm_reader * r)251 read_error (struct dfm_reader *r)
252 {
253 msg (ME, _("Error reading file %s: %s."),
254 fh_get_name (r->fh), strerror (errno));
255 }
256
257 /* Report a partial read at end of file reading R. */
258 static void
partial_record(struct dfm_reader * r)259 partial_record (struct dfm_reader *r)
260 {
261 msg (ME, _("Unexpected end of file in partial record reading %s."),
262 fh_get_name (r->fh));
263 }
264
265 /* Tries to read SIZE bytes from R into BUFFER. Returns 1 if
266 successful, 0 if end of file was reached before any bytes
267 could be read, and -1 if some bytes were read but fewer than
268 SIZE due to end of file or an error mid-read. In the latter
269 case, reports an error. */
270 static int
try_to_read_fully(struct dfm_reader * r,void * buffer,size_t size)271 try_to_read_fully (struct dfm_reader *r, void *buffer, size_t size)
272 {
273 size_t bytes_read = fread (buffer, 1, size, r->file);
274 if (bytes_read == size)
275 return 1;
276 else if (bytes_read == 0)
277 return 0;
278 else
279 {
280 partial_record (r);
281 return -1;
282 }
283 }
284
285 /* Type of a descriptor word. */
286 enum descriptor_type
287 {
288 BLOCK,
289 RECORD
290 };
291
292 /* Reads a block descriptor word or record descriptor word
293 (according to TYPE) from R. Returns 1 if successful, 0 if
294 end of file was reached before any bytes could be read, -1 if
295 an error occurred. Reports an error in the latter case.
296
297 If successful, stores the number of remaining bytes in the
298 block or record (that is, the block or record length, minus
299 the 4 bytes in the BDW or RDW itself) into *REMAINING_SIZE.
300 If SEGMENT is nonnull, also stores the segment control
301 character (SCC) into *SEGMENT. */
302 static int
read_descriptor_word(struct dfm_reader * r,enum descriptor_type type,size_t * remaining_size,int * segment)303 read_descriptor_word (struct dfm_reader *r, enum descriptor_type type,
304 size_t *remaining_size, int *segment)
305 {
306 uint8_t raw_descriptor[4];
307 int status;
308
309 status = try_to_read_fully (r, raw_descriptor, sizeof raw_descriptor);
310 if (status <= 0)
311 return status;
312
313 *remaining_size = (raw_descriptor[0] << 8) | raw_descriptor[1];
314 if (segment != NULL)
315 *segment = raw_descriptor[2];
316
317 if (*remaining_size < 4)
318 {
319 msg (ME,
320 (type == BLOCK
321 ? _("Corrupt block descriptor word at offset 0x%lx in %s.")
322 : _("Corrupt record descriptor word at offset 0x%lx in %s.")),
323 (long) ftello (r->file) - 4, fh_get_name (r->fh));
324 return -1;
325 }
326
327 *remaining_size -= 4;
328 return 1;
329 }
330
331 /* Reports that reader R has read a corrupt record size. */
332 static void
corrupt_size(struct dfm_reader * r)333 corrupt_size (struct dfm_reader *r)
334 {
335 msg (ME, _("Corrupt record size at offset 0x%lx in %s."),
336 (long) ftello (r->file) - 4, fh_get_name (r->fh));
337 }
338
339 /* Reads a 32-byte little-endian signed number from R and stores
340 its value into *SIZE_OUT. Returns 1 if successful, 0 if end
341 of file was reached before any bytes could be read, -1 if an
342 error occurred. Reports an error in the latter case. Numbers
343 less than 0 are considered errors. */
344 static int
read_size(struct dfm_reader * r,size_t * size_out)345 read_size (struct dfm_reader *r, size_t *size_out)
346 {
347 int32_t size;
348 int status;
349
350 status = try_to_read_fully (r, &size, sizeof size);
351 if (status <= 0)
352 return status;
353
354 integer_convert (INTEGER_LSB_FIRST, &size, INTEGER_NATIVE, &size,
355 sizeof size);
356 if (size < 0)
357 {
358 corrupt_size (r);
359 return -1;
360 }
361
362 *size_out = size;
363 return 1;
364 }
365
366 static bool
read_text_record(struct dfm_reader * r)367 read_text_record (struct dfm_reader *r)
368 {
369 bool is_auto;
370 bool ok;
371
372 /* Read a line. If the line reader's encoding changes, update r->encoding to
373 match. */
374 is_auto = line_reader_is_auto (r->line_reader);
375 ok = line_reader_read (r->line_reader, &r->line, SIZE_MAX);
376 if (is_auto && !line_reader_is_auto (r->line_reader))
377 {
378 free (r->encoding);
379 r->encoding = xstrdup (line_reader_get_encoding (r->line_reader));
380 }
381
382 /* Detect and report read error. */
383 if (!ok)
384 {
385 int error = line_reader_error (r->line_reader);
386 if (error != 0)
387 msg (ME, _("Error reading file %s: %s."),
388 fh_get_name (r->fh), strerror (error));
389 }
390
391 return ok;
392 }
393
394 /* Reads a record from a disk file into R.
395 Returns true if successful, false on error or at end of file. */
396 static bool
read_file_record(struct dfm_reader * r)397 read_file_record (struct dfm_reader *r)
398 {
399 assert (r->fh != fh_inline_file ());
400
401 ds_clear (&r->line);
402 switch (fh_get_mode (r->fh))
403 {
404 case FH_MODE_TEXT:
405 return read_text_record (r);
406
407 case FH_MODE_FIXED:
408 if (ds_read_stream (&r->line, 1, fh_get_record_width (r->fh), r->file))
409 return true;
410 else
411 {
412 if (ferror (r->file))
413 read_error (r);
414 else if (!ds_is_empty (&r->line))
415 partial_record (r);
416 return false;
417 }
418
419 case FH_MODE_VARIABLE:
420 {
421 size_t leading_size;
422 size_t trailing_size;
423 int status;
424
425 /* Read leading record size. */
426 status = read_size (r, &leading_size);
427 if (status <= 0)
428 return false;
429
430 /* Read record data. */
431 if (!ds_read_stream (&r->line, leading_size, 1, r->file))
432 {
433 if (ferror (r->file))
434 read_error (r);
435 else
436 partial_record (r);
437 return false;
438 }
439
440 /* Read trailing record size and check that it's the same
441 as the leading record size. */
442 status = read_size (r, &trailing_size);
443 if (status <= 0)
444 {
445 if (status == 0)
446 partial_record (r);
447 return false;
448 }
449 if (leading_size != trailing_size)
450 {
451 corrupt_size (r);
452 return false;
453 }
454
455 return true;
456 }
457
458 case FH_MODE_360_VARIABLE:
459 case FH_MODE_360_SPANNED:
460 for (;;)
461 {
462 size_t record_size;
463 int segment;
464 int status;
465
466 /* If we've exhausted our current block, start another
467 one by reading the new block descriptor word. */
468 if (r->block_left == 0)
469 {
470 status = read_descriptor_word (r, BLOCK, &r->block_left, NULL);
471 if (status < 0)
472 return false;
473 else if (status == 0)
474 return !ds_is_empty (&r->line);
475 }
476
477 /* Read record descriptor. */
478 if (r->block_left < 4)
479 {
480 partial_record (r);
481 return false;
482 }
483 r->block_left -= 4;
484 status = read_descriptor_word (r, RECORD, &record_size, &segment);
485 if (status <= 0)
486 {
487 if (status == 0)
488 partial_record (r);
489 return false;
490 }
491 if (record_size > r->block_left)
492 {
493 msg (ME, _("Record exceeds remaining block length."));
494 return false;
495 }
496
497 /* Read record data. */
498 if (!ds_read_stream (&r->line, record_size, 1, r->file))
499 {
500 if (ferror (r->file))
501 read_error (r);
502 else
503 partial_record (r);
504 return false;
505 }
506 r->block_left -= record_size;
507
508 /* In variable mode, read only a single record.
509 In spanned mode, a segment value of 0 should
510 designate a whole record without spanning, 1 the
511 first segment in a record, 2 the last segment in a
512 record, and 3 an intermediate segment in a record.
513 For compatibility, though, we actually pay attention
514 only to whether the segment value is even or odd. */
515 if (fh_get_mode (r->fh) == FH_MODE_360_VARIABLE
516 || (segment & 1) == 0)
517 return true;
518 }
519 }
520
521 NOT_REACHED ();
522 }
523
524 /* Reads a record from R, setting the current position to the
525 start of the line. If an error occurs or end-of-file is
526 encountered, the current line is set to null. */
527 static bool
read_record(struct dfm_reader * r)528 read_record (struct dfm_reader *r)
529 {
530 if (fh_get_referent (r->fh) == FH_REF_FILE)
531 {
532 bool ok = read_file_record (r);
533 if (ok)
534 r->line_number++;
535 return ok;
536 }
537 else
538 return read_inline_record (r);
539 }
540
541 /* Returns the number of attempts, thus far, to advance past
542 end-of-file in reader R. Reads forward in HANDLE's file, if
543 necessary, to find out.
544
545 Normally, the user stops attempting to read from the file the
546 first time EOF is reached (a return value of 1). If the user
547 tries to read past EOF again (a return value of 2 or more),
548 an error message is issued, and the caller should more
549 forcibly abort to avoid an infinite loop. */
550 unsigned
dfm_eof(struct dfm_reader * r)551 dfm_eof (struct dfm_reader *r)
552 {
553 if (r->flags & DFM_ADVANCE)
554 {
555 r->flags &= ~DFM_ADVANCE;
556
557 if (r->eof_cnt == 0 && read_record (r))
558 {
559 r->pos = 0;
560 return 0;
561 }
562
563 r->eof_cnt++;
564 if (r->eof_cnt == 2)
565 {
566 if (r->fh != fh_inline_file ())
567 msg (ME, _("Attempt to read beyond end-of-file on file %s."),
568 fh_get_name (r->fh));
569 else
570 msg (ME, _("Attempt to read beyond %s."), "END DATA");
571 }
572 }
573
574 return r->eof_cnt;
575 }
576
577 /* Returns the current record in the file corresponding to
578 HANDLE. Aborts if reading from the file is necessary or at
579 end of file, so call dfm_eof() first. */
580 struct substring
dfm_get_record(struct dfm_reader * r)581 dfm_get_record (struct dfm_reader *r)
582 {
583 assert ((r->flags & DFM_ADVANCE) == 0);
584 assert (r->eof_cnt == 0);
585
586 return ds_substr (&r->line, r->pos, SIZE_MAX);
587 }
588
589 /* Expands tabs in the current line into the equivalent number of
590 spaces, if appropriate for this kind of file. Aborts if
591 reading from the file is necessary or at end of file, so call
592 dfm_eof() first.*/
593 void
dfm_expand_tabs(struct dfm_reader * r)594 dfm_expand_tabs (struct dfm_reader *r)
595 {
596 size_t ofs, new_pos, tab_width;
597
598 assert ((r->flags & DFM_ADVANCE) == 0);
599 assert (r->eof_cnt == 0);
600
601 if (r->flags & DFM_TABS_EXPANDED)
602 return;
603 r->flags |= DFM_TABS_EXPANDED;
604
605 if (r->fh != fh_inline_file ()
606 && (fh_get_mode (r->fh) != FH_MODE_TEXT
607 || fh_get_tab_width (r->fh) == 0
608 || ds_find_byte (&r->line, '\t') == SIZE_MAX))
609 return;
610
611 /* Expand tabs from r->line into r->scratch, and figure out
612 new value for r->pos. */
613 tab_width = fh_get_tab_width (r->fh);
614 ds_clear (&r->scratch);
615 new_pos = SIZE_MAX;
616 for (ofs = 0; ofs < ds_length (&r->line); ofs++)
617 {
618 unsigned char c;
619
620 if (ofs == r->pos)
621 new_pos = ds_length (&r->scratch);
622
623 c = ds_data (&r->line)[ofs];
624 if (c != '\t')
625 ds_put_byte (&r->scratch, c);
626 else
627 {
628 do
629 ds_put_byte (&r->scratch, ' ');
630 while (ds_length (&r->scratch) % tab_width != 0);
631 }
632 }
633 if (new_pos == SIZE_MAX)
634 {
635 /* Maintain the same relationship between position and line
636 length that we had before. DATA LIST uses a
637 beyond-the-end position to deal with an empty field at
638 the end of the line. */
639 assert (r->pos >= ds_length (&r->line));
640 new_pos = (r->pos - ds_length (&r->line)) + ds_length (&r->scratch);
641 }
642
643 /* Swap r->line and r->scratch and set new r->pos. */
644 ds_swap (&r->line, &r->scratch);
645 r->pos = new_pos;
646 }
647
648 /* Returns the character encoding of data read from READER. */
649 const char *
dfm_reader_get_encoding(const struct dfm_reader * reader)650 dfm_reader_get_encoding (const struct dfm_reader *reader)
651 {
652 return reader->encoding;
653 }
654
655 /* Causes dfm_get_record() or dfm_get_whole_record() to read in
656 the next record the next time it is executed on file
657 HANDLE. */
658 void
dfm_forward_record(struct dfm_reader * r)659 dfm_forward_record (struct dfm_reader *r)
660 {
661 r->flags |= DFM_ADVANCE;
662 }
663
664 /* Cancels the effect of any previous dfm_fwd_record() executed
665 on file HANDLE. Sets the current line to begin in the 1-based
666 column COLUMN. */
667 void
dfm_reread_record(struct dfm_reader * r,size_t column)668 dfm_reread_record (struct dfm_reader *r, size_t column)
669 {
670 r->flags &= ~DFM_ADVANCE;
671 r->pos = MAX (column, 1) - 1;
672 }
673
674 /* Sets the current line to begin COLUMNS characters following
675 the current start. */
676 void
dfm_forward_columns(struct dfm_reader * r,size_t columns)677 dfm_forward_columns (struct dfm_reader *r, size_t columns)
678 {
679 dfm_reread_record (r, (r->pos + 1) + columns);
680 }
681
682 /* Returns the 1-based column to which the line pointer in HANDLE
683 is set. Unless dfm_reread_record() or dfm_forward_columns()
684 have been called, this is 1. */
685 size_t
dfm_column_start(const struct dfm_reader * r)686 dfm_column_start (const struct dfm_reader *r)
687 {
688 return r->pos + 1;
689 }
690
691 /* Returns the number of columns we are currently beyond the end
692 of the line. At or before end-of-line, this is 0; one column
693 after end-of-line, this is 1; and so on. */
694 size_t
dfm_columns_past_end(const struct dfm_reader * r)695 dfm_columns_past_end (const struct dfm_reader *r)
696 {
697 return r->pos < ds_length (&r->line) ? 0 : ds_length (&r->line) - r->pos;
698 }
699
700 /* Returns the 1-based column within the current line that P
701 designates. */
702 size_t
dfm_get_column(const struct dfm_reader * r,const char * p)703 dfm_get_column (const struct dfm_reader *r, const char *p)
704 {
705 return ds_pointer_to_position (&r->line, p) + 1;
706 }
707
708 const char *
dfm_get_file_name(const struct dfm_reader * r)709 dfm_get_file_name (const struct dfm_reader *r)
710 {
711 return (fh_get_referent (r->fh) == FH_REF_FILE
712 ? fh_get_file_name (r->fh)
713 : NULL);
714 }
715
716 int
dfm_get_line_number(const struct dfm_reader * r)717 dfm_get_line_number (const struct dfm_reader *r)
718 {
719 return fh_get_referent (r->fh) == FH_REF_FILE ? r->line_number : -1;
720 }
721
722 /* BEGIN DATA...END DATA procedure. */
723
724 /* Perform BEGIN DATA...END DATA as a procedure in itself. */
725 int
cmd_begin_data(struct lexer * lexer,struct dataset * ds)726 cmd_begin_data (struct lexer *lexer, struct dataset *ds)
727 {
728 struct dfm_reader *r;
729 bool ok;
730
731 if (!fh_is_locked (fh_inline_file (), FH_ACC_READ))
732 {
733 msg (SE, _("This command is not valid here since the current "
734 "input program does not access the inline file."));
735 return CMD_CASCADING_FAILURE;
736 }
737 lex_match (lexer, T_ENDCMD);
738
739 /* Open inline file. */
740 r = dfm_open_reader (fh_inline_file (), lexer, NULL);
741 r->flags |= DFM_SAW_BEGIN_DATA;
742 r->flags &= ~DFM_CONSUME;
743
744 /* Input procedure reads from inline file. */
745 casereader_destroy (proc_open (ds));
746 ok = proc_commit (ds);
747 dfm_close_reader (r);
748
749 return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE;
750 }
751