Fixed bug reporting the significance of paired value t-test.
[pspp-builds.git] / src / language / data-io / data-list.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-9, 2000, 2006, 2007 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 <ctype.h>
20 #include <float.h>
21 #include <stdint.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24
25 #include <data/case.h>
26 #include <data/data-in.h>
27 #include <data/casereader.h>
28 #include <data/dictionary.h>
29 #include <data/format.h>
30 #include <data/procedure.h>
31 #include <data/settings.h>
32 #include <data/transformations.h>
33 #include <data/variable.h>
34 #include <language/command.h>
35 #include <language/data-io/data-parser.h>
36 #include <language/data-io/data-reader.h>
37 #include <language/data-io/file-handle.h>
38 #include <language/data-io/inpt-pgm.h>
39 #include <language/data-io/placement-parser.h>
40 #include <language/lexer/format-parser.h>
41 #include <language/lexer/lexer.h>
42 #include <language/lexer/variable-parser.h>
43 #include <libpspp/assertion.h>
44 #include <libpspp/compiler.h>
45 #include <libpspp/message.h>
46 #include <libpspp/misc.h>
47 #include <libpspp/pool.h>
48 #include <libpspp/str.h>
49
50 #include "xsize.h"
51 #include "xalloc.h"
52
53 #include "gettext.h"
54 #define _(msgid) gettext (msgid)
55 \f
56 /* DATA LIST transformation data. */
57 struct data_list_trns
58   {
59     struct data_parser *parser; /* Parser. */
60     struct dfm_reader *reader;  /* Data file reader. */
61     struct variable *end;       /* Variable specified on END subcommand. */
62   };
63
64 static bool parse_fixed (struct lexer *, struct dictionary *,
65                          struct pool *, struct data_parser *);
66 static bool parse_free (struct lexer *, struct dictionary *,
67                         struct pool *, struct data_parser *);
68
69 static trns_free_func data_list_trns_free;
70 static trns_proc_func data_list_trns_proc;
71
72 int
73 cmd_data_list (struct lexer *lexer, struct dataset *ds)
74 {
75   struct dictionary *dict;
76   struct data_parser *parser;
77   struct dfm_reader *reader;
78   struct variable *end;
79   struct file_handle *fh;
80
81   int table;
82   enum data_parser_type type;
83   bool has_type;
84   struct pool *tmp_pool;
85   bool ok;
86
87   dict = in_input_program () ? dataset_dict (ds) : dict_create ();
88   parser = data_parser_create ();
89   reader = NULL;
90   end = NULL;
91   fh = NULL;
92
93   table = -1;                /* Print table if nonzero, -1=undecided. */
94   has_type = false;
95
96   while (lex_token (lexer) != '/')
97     {
98       if (lex_match_id (lexer, "FILE"))
99         {
100           lex_match (lexer, '=');
101           fh_unref (fh);
102           fh = fh_parse (lexer, FH_REF_FILE | FH_REF_INLINE);
103           if (fh == NULL)
104             goto error;
105         }
106       else if (lex_match_id (lexer, "RECORDS"))
107         {
108           lex_match (lexer, '=');
109           lex_match (lexer, '(');
110           if (!lex_force_int (lexer))
111             goto error;
112           data_parser_set_records (parser, lex_integer (lexer));
113           lex_get (lexer);
114           lex_match (lexer, ')');
115         }
116       else if (lex_match_id (lexer, "SKIP"))
117         {
118           lex_match (lexer, '=');
119           if (!lex_force_int (lexer))
120             goto error;
121           data_parser_set_skip (parser, lex_integer (lexer));
122           lex_get (lexer);
123         }
124       else if (lex_match_id (lexer, "END"))
125         {
126           if (!in_input_program ())
127             {
128               msg (SE, _("The END subcommand may only be used within "
129                          "INPUT PROGRAM."));
130               goto error;
131             }
132           if (end)
133             {
134               msg (SE, _("The END subcommand may only be specified once."));
135               goto error;
136             }
137
138           lex_match (lexer, '=');
139           if (!lex_force_id (lexer))
140             goto error;
141           end = dict_lookup_var (dict, lex_tokid (lexer));
142           if (!end)
143             end = dict_create_var_assert (dict, lex_tokid (lexer), 0);
144           lex_get (lexer);
145         }
146       else if (lex_match_id (lexer, "NOTABLE"))
147         table = 0;
148       else if (lex_match_id (lexer, "TABLE"))
149         table = 1;
150       else if (lex_token (lexer) == T_ID)
151         {
152           if (lex_match_id (lexer, "FIXED"))
153             data_parser_set_type (parser, DP_FIXED);
154           else if (lex_match_id (lexer, "FREE"))
155             {
156               data_parser_set_type (parser, DP_DELIMITED);
157               data_parser_set_span (parser, true);
158             }
159           else if (lex_match_id (lexer, "LIST"))
160             {
161               data_parser_set_type (parser, DP_DELIMITED);
162               data_parser_set_span (parser, false);
163             }
164           else
165             {
166               lex_error (lexer, NULL);
167               goto error;
168             }
169
170           if (has_type)
171             {
172               msg (SE, _("Only one of FIXED, FREE, or LIST may "
173                          "be specified."));
174               goto error;
175             }
176           has_type = true;
177
178           if (data_parser_get_type (parser) == DP_DELIMITED)
179             {
180               if (lex_match (lexer, '('))
181                 {
182                   struct string delims = DS_EMPTY_INITIALIZER;
183
184                   while (!lex_match (lexer, ')'))
185                     {
186                       int delim;
187
188                       if (lex_match_id (lexer, "TAB"))
189                         delim = '\t';
190                       else if (lex_token (lexer) == T_STRING
191                                && ds_length (lex_tokstr (lexer)) == 1)
192                         {
193                           delim = ds_first (lex_tokstr (lexer));
194                           lex_get (lexer);
195                         }
196                       else
197                         {
198                           lex_error (lexer, NULL);
199                           ds_destroy (&delims);
200                           goto error;
201                         }
202                       ds_put_char (&delims, delim);
203
204                       lex_match (lexer, ',');
205                     }
206
207                   data_parser_set_empty_line_has_field (parser, true);
208                   data_parser_set_quotes (parser, ss_empty ());
209                   data_parser_set_soft_delimiters (parser, ss_empty ());
210                   data_parser_set_hard_delimiters (parser, ds_ss (&delims));
211                   ds_destroy (&delims);
212                 }
213               else
214                 {
215                   data_parser_set_empty_line_has_field (parser, false);
216                   data_parser_set_quotes (parser, ss_cstr ("'\""));
217                   data_parser_set_soft_delimiters (parser,
218                                                    ss_cstr (CC_SPACES));
219                   data_parser_set_hard_delimiters (parser, ss_cstr (","));
220                 }
221             }
222         }
223       else
224         {
225           lex_error (lexer, NULL);
226           goto error;
227         }
228     }
229   type = data_parser_get_type (parser);
230
231   if (fh == NULL)
232     fh = fh_inline_file ();
233   fh_set_default_handle (fh);
234
235   if (type != DP_FIXED && end != NULL)
236     {
237       msg (SE, _("The END subcommand may be used only with DATA LIST FIXED."));
238       goto error;
239     }
240
241   tmp_pool = pool_create ();
242   if (type == DP_FIXED)
243     ok = parse_fixed (lexer, dict, tmp_pool, parser);
244   else
245     ok = parse_free (lexer, dict, tmp_pool, parser);
246   pool_destroy (tmp_pool);
247   if (!ok)
248     goto error;
249
250   if (!data_parser_any_fields (parser))
251     {
252       msg (SE, _("At least one variable must be specified."));
253       goto error;
254     }
255
256   if (lex_end_of_command (lexer) != CMD_SUCCESS)
257     goto error;
258
259   if (table == -1)
260     table = type == DP_FIXED || !data_parser_get_span (parser);
261   if (table)
262     data_parser_output_description (parser, fh);
263
264   reader = dfm_open_reader (fh, lexer);
265   if (reader == NULL)
266     goto error;
267
268   if (in_input_program ())
269     {
270       struct data_list_trns *trns = xmalloc (sizeof *trns);
271       trns->parser = parser;
272       trns->reader = reader;
273       trns->end = end;
274       add_transformation (ds, data_list_trns_proc, data_list_trns_free, trns);
275     }
276   else
277     data_parser_make_active_file (parser, ds, reader, dict);
278
279   fh_unref (fh);
280
281   return CMD_SUCCESS;
282
283  error:
284   data_parser_destroy (parser);
285   if (!in_input_program ())
286     dict_destroy (dict);
287   fh_unref (fh);
288   return CMD_CASCADING_FAILURE;
289 }
290 \f
291 /* Fixed-format parsing. */
292
293 /* Parses all the variable specifications for DATA LIST FIXED,
294    storing them into DLS.  Uses TMP_POOL for temporary storage;
295    the caller may destroy it.  Returns true only if
296    successful. */
297 static bool
298 parse_fixed (struct lexer *lexer, struct dictionary *dict,
299              struct pool *tmp_pool, struct data_parser *parser)
300 {
301   int max_records = data_parser_get_records (parser);
302   int record = 0;
303   int column = 1;
304
305   while (lex_token (lexer) != '.')
306     {
307       char **names;
308       size_t name_cnt, name_idx;
309       struct fmt_spec *formats, *f;
310       size_t format_cnt;
311
312       /* Parse everything. */
313       if (!parse_record_placement (lexer, &record, &column)
314           || !parse_DATA_LIST_vars_pool (lexer, tmp_pool,
315                                          &names, &name_cnt, PV_NONE)
316           || !parse_var_placements (lexer, tmp_pool, name_cnt, true,
317                                     &formats, &format_cnt))
318         return false;
319
320       /* Create variables and var specs. */
321       name_idx = 0;
322       for (f = formats; f < &formats[format_cnt]; f++)
323         if (!execute_placement_format (f, &record, &column))
324           {
325             char *name;
326             int width;
327             struct variable *v;
328
329             name = names[name_idx++];
330
331             /* Create variable. */
332             width = fmt_var_width (f);
333             v = dict_create_var (dict, name, width);
334             if (v != NULL)
335               {
336                 /* Success. */
337                 struct fmt_spec output = fmt_for_output_from_input (f);
338                 var_set_both_formats (v, &output);
339               }
340             else
341               {
342                 /* Failure.
343                    This can be acceptable if we're in INPUT
344                    PROGRAM, but only if the existing variable has
345                    the same width as the one we would have
346                    created. */
347                 if (!in_input_program ())
348                   {
349                     msg (SE, _("%s is a duplicate variable name."), name);
350                     return false;
351                   }
352
353                 v = dict_lookup_var_assert (dict, name);
354                 if ((width != 0) != (var_get_width (v) != 0))
355                   {
356                     msg (SE, _("There is already a variable %s of a "
357                                "different type."),
358                          name);
359                     return false;
360                   }
361                 if (width != 0 && width != var_get_width (v))
362                   {
363                     msg (SE, _("There is already a string variable %s of a "
364                                "different width."), name);
365                     return false;
366                   }
367               }
368
369             if (max_records && record > max_records)
370               {
371                 msg (SE, _("Cannot place variable %s on record %d when "
372                            "RECORDS=%d is specified."),
373                      var_get_name (v), record,
374                      data_parser_get_records (parser));
375               }
376
377             data_parser_add_fixed_field (parser, f,
378                                          var_get_case_index (v),
379                                          var_get_name (v), record, column);
380
381             column += f->w;
382           }
383       assert (name_idx == name_cnt);
384     }
385
386   return true;
387 }
388 \f
389 /* Free-format parsing. */
390
391 /* Parses variable specifications for DATA LIST FREE and adds
392    them to DLS.  Uses TMP_POOL for temporary storage; the caller
393    may destroy it.  Returns true only if successful. */
394 static bool
395 parse_free (struct lexer *lexer, struct dictionary *dict,
396             struct pool *tmp_pool, struct data_parser *parser)
397 {
398   lex_get (lexer);
399   while (lex_token (lexer) != '.')
400     {
401       struct fmt_spec input, output;
402       char **name;
403       size_t name_cnt;
404       size_t i;
405
406       if (!parse_DATA_LIST_vars_pool (lexer, tmp_pool,
407                                       &name, &name_cnt, PV_NONE))
408         return false;
409
410       if (lex_match (lexer, '('))
411         {
412           if (!parse_format_specifier (lexer, &input)
413               || !fmt_check_input (&input)
414               || !lex_force_match (lexer, ')'))
415             return NULL;
416
417           /* As a special case, N format is treated as F format
418              for free-field input. */
419           if (input.type == FMT_N)
420             input.type = FMT_F;
421
422           output = fmt_for_output_from_input (&input);
423         }
424       else
425         {
426           lex_match (lexer, '*');
427           input = fmt_for_input (FMT_F, 8, 0);
428           output = *settings_get_format ();
429         }
430
431       for (i = 0; i < name_cnt; i++)
432         {
433           struct variable *v;
434
435           v = dict_create_var (dict, name[i], fmt_var_width (&input));
436           if (v == NULL)
437             {
438               msg (SE, _("%s is a duplicate variable name."), name[i]);
439               return false;
440             }
441           var_set_both_formats (v, &output);
442
443           data_parser_add_delimited_field (parser,
444                                            &input, var_get_case_index (v),
445                                            var_get_name (v));
446         }
447     }
448
449   return true;
450 }
451 \f
452 /* Input procedure. */
453
454 /* Destroys DATA LIST transformation TRNS.
455    Returns true if successful, false if an I/O error occurred. */
456 static bool
457 data_list_trns_free (void *trns_)
458 {
459   struct data_list_trns *trns = trns_;
460   data_parser_destroy (trns->parser);
461   dfm_close_reader (trns->reader);
462   free (trns);
463   return true;
464 }
465
466 /* Handle DATA LIST transformation TRNS, parsing data into C. */
467 static int
468 data_list_trns_proc (void *trns_, struct ccase *c, casenumber case_num UNUSED)
469 {
470   struct data_list_trns *trns = trns_;
471   int retval;
472
473   if (data_parser_parse (trns->parser, trns->reader, c))
474     retval = TRNS_CONTINUE;
475   else if (dfm_reader_error (trns->reader) || dfm_eof (trns->reader) > 1)
476     {
477       /* An I/O error, or encountering end of file for a second
478          time, should be escalated into a more serious error. */
479       retval = TRNS_ERROR;
480     }
481   else
482     retval = TRNS_END_FILE;
483
484   /* If there was an END subcommand handle it. */
485   if (trns->end != NULL)
486     {
487       double *end = &case_data_rw (c, trns->end)->f;
488       if (retval == TRNS_END_FILE)
489         {
490           *end = 1.0;
491           retval = TRNS_CONTINUE;
492         }
493       else
494         *end = 0.0;
495     }
496
497   return retval;
498 }
499 \f