Rename procedure.[ch] to dataset.[ch].
[pspp-builds.git] / src / language / data-io / get-data.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2007, 2008, 2009, 2010, 2011 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 <stdlib.h>
20
21 #include "data/dataset.h"
22 #include "data/dictionary.h"
23 #include "data/format.h"
24 #include "data/gnumeric-reader.h"
25 #include "data/psql-reader.h"
26 #include "data/settings.h"
27 #include "language/command.h"
28 #include "language/data-io/data-parser.h"
29 #include "language/data-io/data-reader.h"
30 #include "language/data-io/file-handle.h"
31 #include "language/data-io/placement-parser.h"
32 #include "language/lexer/format-parser.h"
33 #include "language/lexer/lexer.h"
34 #include "libpspp/i18n.h"
35 #include "libpspp/message.h"
36
37 #include "gl/xalloc.h"
38
39 #include "gettext.h"
40 #define _(msgid) gettext (msgid)
41 #define N_(msgid) (msgid)
42
43 static int parse_get_gnm (struct lexer *lexer, struct dataset *);
44 static int parse_get_txt (struct lexer *lexer, struct dataset *);
45 static int parse_get_psql (struct lexer *lexer, struct dataset *);
46
47 int
48 cmd_get_data (struct lexer *lexer, struct dataset *ds)
49 {
50   lex_force_match (lexer, T_SLASH);
51
52   if (!lex_force_match_id (lexer, "TYPE"))
53     return CMD_FAILURE;
54
55   lex_force_match (lexer, T_EQUALS);
56
57   if (lex_match_id (lexer, "GNM"))
58     return parse_get_gnm (lexer, ds);
59   else if (lex_match_id (lexer, "TXT"))
60     return parse_get_txt (lexer, ds);
61   else if (lex_match_id (lexer, "PSQL"))
62     return parse_get_psql (lexer, ds);
63
64   msg (SE, _("Unsupported TYPE %s."), lex_tokcstr (lexer));
65   return CMD_FAILURE;
66 }
67
68 static int
69 parse_get_psql (struct lexer *lexer, struct dataset *ds)
70 {
71   struct psql_read_info psql;
72   psql.allow_clear = false;
73   psql.conninfo = NULL;
74   psql.str_width = -1;
75   psql.bsize = -1;
76   ds_init_empty (&psql.sql);
77
78   lex_force_match (lexer, T_SLASH);
79
80   if (!lex_force_match_id (lexer, "CONNECT"))
81     goto error;
82
83   lex_force_match (lexer, T_EQUALS);
84
85   if (!lex_force_string (lexer))
86     goto error;
87
88   psql.conninfo = ss_xstrdup (lex_tokss (lexer));
89
90   lex_get (lexer);
91
92   while (lex_match (lexer, T_SLASH) )
93     {
94       if ( lex_match_id (lexer, "ASSUMEDSTRWIDTH"))
95         {
96           lex_match (lexer, T_EQUALS);
97           psql.str_width = lex_integer (lexer);
98           lex_get (lexer);
99         }
100       else if ( lex_match_id (lexer, "BSIZE"))
101         {
102           lex_match (lexer, T_EQUALS);
103           psql.bsize = lex_integer (lexer);
104           lex_get (lexer);
105         }
106       else if ( lex_match_id (lexer, "UNENCRYPTED"))
107         {
108           psql.allow_clear = true;
109         }
110       else if (lex_match_id (lexer, "SQL"))
111         {
112           lex_match (lexer, T_EQUALS);
113           if ( ! lex_force_string (lexer) )
114             goto error;
115
116           ds_put_substring (&psql.sql, lex_tokss (lexer));
117           lex_get (lexer);
118         }
119      }
120   {
121     struct dictionary *dict = NULL;
122     struct casereader *reader = psql_open_reader (&psql, &dict);
123
124     if ( reader )
125       proc_set_active_file (ds, reader, dict);
126   }
127
128   ds_destroy (&psql.sql);
129   free (psql.conninfo);
130
131   return CMD_SUCCESS;
132
133  error:
134
135   ds_destroy (&psql.sql);
136   free (psql.conninfo);
137
138   return CMD_FAILURE;
139 }
140
141 static int
142 parse_get_gnm (struct lexer *lexer, struct dataset *ds)
143 {
144   struct gnumeric_read_info gri  = {NULL, NULL, NULL, 1, true, -1};
145
146   lex_force_match (lexer, T_SLASH);
147
148   if (!lex_force_match_id (lexer, "FILE"))
149     goto error;
150
151   lex_force_match (lexer, T_EQUALS);
152
153   if (!lex_force_string (lexer))
154     goto error;
155
156   gri.file_name = utf8_to_filename (lex_tokcstr (lexer));
157
158   lex_get (lexer);
159
160   while (lex_match (lexer, T_SLASH) )
161     {
162       if ( lex_match_id (lexer, "ASSUMEDSTRWIDTH"))
163         {
164           lex_match (lexer, T_EQUALS);
165           gri.asw = lex_integer (lexer);
166           lex_get (lexer);
167         }
168       else if (lex_match_id (lexer, "SHEET"))
169         {
170           lex_match (lexer, T_EQUALS);
171           if (lex_match_id (lexer, "NAME"))
172             {
173               if ( ! lex_force_string (lexer) )
174                 goto error;
175
176               gri.sheet_name = ss_xstrdup (lex_tokss (lexer));
177               gri.sheet_index = -1;
178
179               lex_get (lexer);
180             }
181           else if (lex_match_id (lexer, "INDEX"))
182             {
183               gri.sheet_index = lex_integer (lexer);
184               lex_get (lexer);
185             }
186           else
187             goto error;
188         }
189       else if (lex_match_id (lexer, "CELLRANGE"))
190         {
191           lex_match (lexer, T_EQUALS);
192
193           if (lex_match_id (lexer, "FULL"))
194             {
195               gri.cell_range = NULL;
196             }
197           else if (lex_match_id (lexer, "RANGE"))
198             {
199               if ( ! lex_force_string (lexer) )
200                 goto error;
201
202               gri.cell_range = ss_xstrdup (lex_tokss (lexer));
203               lex_get (lexer);
204             }
205           else
206             goto error;
207         }
208       else if (lex_match_id (lexer, "READNAMES"))
209         {
210           lex_match (lexer, T_EQUALS);
211
212           if ( lex_match_id (lexer, "ON"))
213             {
214               gri.read_names = true;
215             }
216           else if (lex_match_id (lexer, "OFF"))
217             {
218               gri.read_names = false;
219             }
220           else
221             goto error;
222         }
223       else
224         {
225           lex_error (lexer, NULL);
226           goto error;
227         }
228     }
229
230   {
231     struct dictionary *dict = NULL;
232     struct casereader *reader = gnumeric_open_reader (&gri, &dict);
233
234     if ( reader )
235       proc_set_active_file (ds, reader, dict);
236   }
237
238   free (gri.file_name);
239   free (gri.sheet_name);
240   free (gri.cell_range);
241   return CMD_SUCCESS;
242
243  error:
244
245   free (gri.file_name);
246   free (gri.sheet_name);
247   free (gri.cell_range);
248   return CMD_FAILURE;
249 }
250
251 static bool
252 set_type (struct data_parser *parser, const char *subcommand,
253           enum data_parser_type type, bool *has_type)
254 {
255   if (!*has_type)
256     {
257       data_parser_set_type (parser, type);
258       *has_type = true;
259     }
260   else if (type != data_parser_get_type (parser))
261     {
262       msg (SE, _("%s is allowed only with %s arrangement, but %s arrangement "
263                  "was stated or implied earlier in this command."),
264            subcommand,
265            type == DP_FIXED ? "FIXED" : "DELIMITED",
266            type == DP_FIXED ? "DELIMITED" : "FIXED");
267       return false;
268     }
269   return true;
270 }
271
272 static int
273 parse_get_txt (struct lexer *lexer, struct dataset *ds)
274 {
275   struct data_parser *parser = NULL;
276   struct dictionary *dict = dict_create ();
277   struct file_handle *fh = NULL;
278   struct dfm_reader *reader = NULL;
279   char *name = NULL;
280
281   int record;
282   enum data_parser_type type;
283   bool has_type;
284
285   lex_force_match (lexer, T_SLASH);
286
287   if (!lex_force_match_id (lexer, "FILE"))
288     goto error;
289   lex_force_match (lexer, T_EQUALS);
290   fh = fh_parse (lexer, FH_REF_FILE | FH_REF_INLINE);
291   if (fh == NULL)
292     goto error;
293
294   parser = data_parser_create (dict);
295   has_type = false;
296   data_parser_set_type (parser, DP_DELIMITED);
297   data_parser_set_span (parser, false);
298   data_parser_set_quotes (parser, ss_empty ());
299   data_parser_set_empty_line_has_field (parser, true);
300
301   for (;;)
302     {
303       if (!lex_force_match (lexer, T_SLASH))
304         goto error;
305
306       if (lex_match_id (lexer, "ARRANGEMENT"))
307         {
308           bool ok;
309
310           lex_match (lexer, T_EQUALS);
311           if (lex_match_id (lexer, "FIXED"))
312             ok = set_type (parser, "ARRANGEMENT=FIXED", DP_FIXED, &has_type);
313           else if (lex_match_id (lexer, "DELIMITED"))
314             ok = set_type (parser, "ARRANGEMENT=DELIMITED",
315                            DP_DELIMITED, &has_type);
316           else
317             {
318               lex_error (lexer, _("expecting %s or %s"), "FIXED", "DELIMITED");
319               goto error;
320             }
321           if (!ok)
322             goto error;
323         }
324       else if (lex_match_id (lexer, "FIRSTCASE"))
325         {
326           lex_match (lexer, T_EQUALS);
327           if (!lex_force_int (lexer))
328             goto error;
329           if (lex_integer (lexer) < 1)
330             {
331               msg (SE, _("Value of FIRSTCASE must be 1 or greater."));
332               goto error;
333             }
334           data_parser_set_skip (parser, lex_integer (lexer) - 1);
335           lex_get (lexer);
336         }
337       else if (lex_match_id_n (lexer, "DELCASE", 4))
338         {
339           if (!set_type (parser, "DELCASE", DP_DELIMITED, &has_type))
340             goto error;
341           lex_match (lexer, T_EQUALS);
342           if (lex_match_id (lexer, "LINE"))
343             data_parser_set_span (parser, false);
344           else if (lex_match_id (lexer, "VARIABLES"))
345             {
346               data_parser_set_span (parser, true);
347
348               /* VARIABLES takes an integer argument, but for no
349                  good reason.  We just ignore it. */
350               if (!lex_force_int (lexer))
351                 goto error;
352               lex_get (lexer);
353             }
354           else
355             {
356               lex_error (lexer, _("expecting %s or %s"), "LINE", "VARIABLES");
357               goto error;
358             }
359         }
360       else if (lex_match_id (lexer, "FIXCASE"))
361         {
362           if (!set_type (parser, "FIXCASE", DP_FIXED, &has_type))
363             goto error;
364           lex_match (lexer, T_EQUALS);
365           if (!lex_force_int (lexer))
366             goto error;
367           if (lex_integer (lexer) < 1)
368             {
369               msg (SE, _("Value of FIXCASE must be at least 1."));
370               goto error;
371             }
372           data_parser_set_records (parser, lex_integer (lexer));
373           lex_get (lexer);
374         }
375       else if (lex_match_id (lexer, "IMPORTCASES"))
376         {
377           lex_match (lexer, T_EQUALS);
378           if (lex_match (lexer, T_ALL))
379             {
380               data_parser_set_case_limit (parser, -1);
381               data_parser_set_case_percent (parser, 100);
382             }
383           else if (lex_match_id (lexer, "FIRST"))
384             {
385               if (!lex_force_int (lexer))
386                 goto error;
387               if (lex_integer (lexer) < 1)
388                 {
389                   msg (SE, _("Value of FIRST must be at least 1."));
390                   goto error;
391                 }
392               data_parser_set_case_limit (parser, lex_integer (lexer));
393               lex_get (lexer);
394             }
395           else if (lex_match_id (lexer, "PERCENT"))
396             {
397               if (!lex_force_int (lexer))
398                 goto error;
399               if (lex_integer (lexer) < 1 || lex_integer (lexer) > 100)
400                 {
401                   msg (SE, _("Value of PERCENT must be between 1 and 100."));
402                   goto error;
403                 }
404               data_parser_set_case_percent (parser, lex_integer (lexer));
405               lex_get (lexer);
406             }
407         }
408       else if (lex_match_id_n (lexer, "DELIMITERS", 4))
409         {
410           struct string hard_seps = DS_EMPTY_INITIALIZER;
411           const char *soft_seps = "";
412           struct substring s;
413           int c;
414
415           if (!set_type (parser, "DELIMITERS", DP_DELIMITED, &has_type))
416             goto error;
417           lex_match (lexer, T_EQUALS);
418
419           if (!lex_force_string (lexer))
420             goto error;
421
422           /* XXX should support multibyte UTF-8 characters */
423           s = lex_tokss (lexer);
424           if (ss_match_string (&s, ss_cstr ("\\t")))
425             ds_put_cstr (&hard_seps, "\t");
426           if (ss_match_string (&s, ss_cstr ("\\\\")))
427             ds_put_cstr (&hard_seps, "\\");
428           while ((c = ss_get_byte (&s)) != EOF)
429             if (c == ' ')
430               soft_seps = " ";
431             else
432               ds_put_byte (&hard_seps, c);
433           data_parser_set_soft_delimiters (parser, ss_cstr (soft_seps));
434           data_parser_set_hard_delimiters (parser, ds_ss (&hard_seps));
435           ds_destroy (&hard_seps);
436
437           lex_get (lexer);
438         }
439       else if (lex_match_id (lexer, "QUALIFIERS"))
440         {
441           if (!set_type (parser, "QUALIFIERS", DP_DELIMITED, &has_type))
442             goto error;
443           lex_match (lexer, T_EQUALS);
444
445           if (!lex_force_string (lexer))
446             goto error;
447
448           /* XXX should support multibyte UTF-8 characters */
449           if (settings_get_syntax () == COMPATIBLE
450               && ss_length (lex_tokss (lexer)) != 1)
451             {
452               msg (SE, _("In compatible syntax mode, the QUALIFIER string "
453                          "must contain exactly one character."));
454               goto error;
455             }
456
457           data_parser_set_quotes (parser, lex_tokss (lexer));
458           lex_get (lexer);
459         }
460       else if (settings_get_syntax () == ENHANCED
461                && lex_match_id (lexer, "ESCAPE"))
462         data_parser_set_quote_escape (parser, true);
463       else if (lex_match_id (lexer, "VARIABLES"))
464         break;
465       else
466         {
467           lex_error (lexer, _("expecting %s"), "VARIABLES");
468           goto error;
469         }
470     }
471   lex_match (lexer, T_EQUALS);
472
473   record = 1;
474   type = data_parser_get_type (parser);
475   do
476     {
477       struct fmt_spec input, output;
478       struct variable *v;
479       int fc, lc;
480
481       while (type == DP_FIXED && lex_match (lexer, T_SLASH))
482         {
483           if (!lex_force_int (lexer))
484             goto error;
485           if (lex_integer (lexer) < record)
486             {
487               msg (SE, _("The record number specified, %ld, is at or "
488                          "before the previous record, %d.  Data "
489                          "fields must be listed in order of "
490                          "increasing record number."),
491                    lex_integer (lexer), record);
492               goto error;
493             }
494           if (lex_integer (lexer) > data_parser_get_records (parser))
495             {
496               msg (SE, _("The record number specified, %ld, exceeds "
497                          "the number of records per case specified "
498                          "on FIXCASE, %d."),
499                    lex_integer (lexer), data_parser_get_records (parser));
500               goto error;
501             }
502           record = lex_integer (lexer);
503           lex_get (lexer);
504         }
505
506       if (!lex_force_id (lexer)
507           || !dict_id_is_valid (dict, lex_tokcstr (lexer), true))
508         goto error;
509       name = xstrdup (lex_tokcstr (lexer));
510       lex_get (lexer);
511
512       if (type == DP_DELIMITED)
513         {
514           if (!parse_format_specifier (lexer, &input)
515               || !fmt_check_input (&input))
516             goto error;
517         }
518       else
519         {
520           if (!parse_column_range (lexer, 0, &fc, &lc, NULL))
521             goto error;
522           if (!parse_format_specifier_name (lexer, &input.type))
523             goto error;
524           input.w = lc - fc + 1;
525           input.d = 0;
526           if (!fmt_check_input (&input))
527             goto error;
528         }
529       output = fmt_for_output_from_input (&input);
530
531       v = dict_create_var (dict, name, fmt_var_width (&input));
532       if (v == NULL)
533         {
534           msg (SE, _("%s is a duplicate variable name."), name);
535           goto error;
536         }
537       var_set_both_formats (v, &output);
538
539       if (type == DP_DELIMITED)
540         data_parser_add_delimited_field (parser, &input,
541                                          var_get_case_index (v),
542                                          name);
543       else
544         data_parser_add_fixed_field (parser, &input, var_get_case_index (v),
545                                      name, record, fc);
546       free (name);
547       name = NULL;
548     }
549   while (lex_token (lexer) != T_ENDCMD);
550
551   reader = dfm_open_reader (fh, lexer);
552   if (reader == NULL)
553     goto error;
554
555   data_parser_make_active_file (parser, ds, reader, dict);
556   fh_unref (fh);
557   return CMD_SUCCESS;
558
559  error:
560   data_parser_destroy (parser);
561   dict_destroy (dict);
562   fh_unref (fh);
563   free (name);
564   return CMD_CASCADING_FAILURE;
565 }