pspp-convert: Use null encoding rather than "Auto" by default.
[pspp] / utilities / pspp-convert.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2013 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 <getopt.h>
20 #include <limits.h>
21 #include <stdlib.h>
22
23 #include "data/any-reader.h"
24 #include "data/casereader.h"
25 #include "data/casewriter.h"
26 #include "data/csv-file-writer.h"
27 #include "data/por-file-writer.h"
28 #include "data/settings.h"
29 #include "data/sys-file-writer.h"
30 #include "data/file-handle-def.h"
31 #include "libpspp/assertion.h"
32 #include "libpspp/cast.h"
33 #include "libpspp/i18n.h"
34
35 #include "gl/error.h"
36 #include "gl/progname.h"
37 #include "gl/version-etc.h"
38
39 #include "gettext.h"
40 #define _(msgid) gettext (msgid)
41
42 static void usage (void);
43
44 int
45 main (int argc, char *argv[])
46 {
47   const char *input_filename;
48   const char *output_filename;
49
50   long long int max_cases = LLONG_MAX;
51   struct dictionary *dict;
52   struct casereader *reader;
53   struct file_handle *input_fh;
54   const char *encoding = NULL;
55
56   const char *output_format = NULL;
57   struct file_handle *output_fh;
58   struct casewriter *writer;
59
60   long long int i;
61
62   set_program_name (argv[0]);
63   i18n_init ();
64   fh_init ();
65   settings_init ();
66
67   for (;;)
68     {
69       static const struct option long_options[] =
70         {
71           { "cases",    required_argument, NULL, 'c' },
72           { "encoding", required_argument, NULL, 'e' },
73
74           { "output-format", required_argument, NULL, 'O' },
75
76           { "help",    no_argument,       NULL, 'h' },
77           { "version", no_argument,       NULL, 'v' },
78           { NULL,      0,                 NULL, 0 },
79         };
80
81       int c;
82
83       c = getopt_long (argc, argv, "c:e:O:hv", long_options, NULL);
84       if (c == -1)
85         break;
86
87       switch (c)
88         {
89         case 'c':
90           max_cases = strtoull (optarg, NULL, 0);
91           break;
92
93         case 'e':
94           encoding = optarg;
95           break;
96
97         case 'O':
98           output_format = optarg;
99           break;
100
101         case 'v':
102           version_etc (stdout, "pspp-convert", PACKAGE_NAME, PACKAGE_VERSION,
103                        "Ben Pfaff", "John Darrington", NULL_SENTINEL);
104           exit (EXIT_SUCCESS);
105
106         case 'h':
107           usage ();
108           exit (EXIT_SUCCESS);
109
110         default:
111           exit (EXIT_FAILURE);
112         }
113     }
114
115   if (optind + 2 != argc)
116     error (1, 0, _("exactly two non-option arguments are required; "
117                    "use --help for help"));
118
119   input_filename = argv[optind];
120   output_filename = argv[optind + 1];
121   if (output_format == NULL)
122     {
123       const char *dot = strrchr (output_filename, '.');
124       if (dot == NULL)
125         error (1, 0, _("%s: cannot guess output format (use -O option)"),
126                output_filename);
127
128       output_format = dot + 1;
129     }
130
131   input_fh = fh_create_file (NULL, input_filename, fh_default_properties ());
132   reader = any_reader_open (input_fh, encoding, &dict);
133   if (reader == NULL)
134     exit (1);
135
136   output_fh = fh_create_file (NULL, output_filename, fh_default_properties ());
137   if (!strcmp (output_format, "csv") || !strcmp (output_format, "txt"))
138     {
139       struct csv_writer_options options;
140
141       csv_writer_options_init (&options);
142       options.include_var_names = true;
143       writer = csv_writer_open (output_fh, dict, &options);
144     }
145   else if (!strcmp (output_format, "sav") || !strcmp (output_format, "sys"))
146     {
147       struct sfm_write_options options;
148
149       options = sfm_writer_default_options ();
150       writer = sfm_open_writer (output_fh, dict, options);
151     }
152   else if (!strcmp (output_format, "por"))
153     {
154       struct pfm_write_options options;
155
156       options = pfm_writer_default_options ();
157       writer = pfm_open_writer (output_fh, dict, options);
158     }
159   else
160     {
161       error (1, 0, _("%s: unknown output format (use -O option)"),
162              output_filename);
163       NOT_REACHED ();
164     }
165
166   for (i = 0; i < max_cases; i++)
167     {
168       struct ccase *c;
169
170       c = casereader_read (reader);
171       if (c == NULL)
172         break;
173
174       casewriter_write (writer, c);
175     }
176
177   if (!casereader_destroy (reader))
178     error (1, 0, _("%s: error reading input file"), input_filename);
179   if (!casewriter_destroy (writer))
180     error (1, 0, _("%s: error writing output file"), output_filename);
181
182   fh_done ();
183   i18n_done ();
184
185   return 0;
186 }
187
188 static void
189 usage (void)
190 {
191   printf ("\
192 %s, a utility for converting SPSS data files to other formats.\n\
193 Usage: %s [OPTION]... INPUT OUTPUT\n\
194 where INPUT is an SPSS system or portable file\n\
195   and OUTPUT is the name of the desired output file.\n\
196 \n\
197 The desired format of OUTPUT is by default inferred from its extension:\n\
198   csv txt             comma-separated value\n\
199   sav sys             SPSS system file\n\
200   por                 SPSS portable file\n\
201 \n\
202 Options:\n\
203   -O, --output-format=FORMAT  set specific output format, where FORMAT\n\
204                       is one of the extensions listed above\n\
205   -e, --encoding=CHARSET  override encoding of input data file\n\
206   -c MAXCASES         limit number of cases to copy (default is all cases)\n\
207   --help              display this help and exit\n\
208   --version           output version information and exit\n",
209           program_name, program_name);
210 }