eb7d99fa264da30e161644ff35c5bc0a5f9d33fd
[pspp-builds.git] / src / ui / terminal / command-line.c
1 /* PSPP - computes sample statistics.
2    Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
3    Written by Ben Pfaff <blp@gnu.org>.
4
5    This program is free software; you can redistribute it and/or
6    modify it under the terms of the GNU General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18    02110-1301, USA. */
19
20 #include <config.h>
21 #include "command-line.h"
22 #include "msg-ui.h"
23 #include <libpspp/message.h>
24 #include <ctype.h>
25 #include <stdio.h>
26 #include <errno.h>
27 #include <getopt.h>
28 #include <stdlib.h>
29 #include <libpspp/alloc.h>
30 #include <libpspp/assertion.h>
31 #include <libpspp/copyleft.h>
32 #include <libpspp/message.h>
33 #include <language/syntax-file.h>
34 #include "progname.h"
35 #include <data/settings.h>
36 #include <output/output.h>
37 #include <data/file-name.h>
38 #include <libpspp/getl.h>
39 #include <libpspp/str.h>
40 #include <libpspp/version.h>
41 #include <libpspp/verbose-msg.h>
42 #include "read-line.h"
43
44 #include "gettext.h"
45 #define _(msgid) gettext (msgid)
46 #define N_(msgid) msgid
47
48 void welcome (void);
49 static void usage (void);
50
51 char *subst_vars (char *);
52
53
54 /* Parses the command line specified by ARGC and ARGV as received by
55    main().  Returns true if normal execution should proceed,
56    false if the command-line indicates that PSPP should exit. */
57 bool
58 parse_command_line (int argc, char **argv, struct source_stream *ss)
59 {
60   static struct option long_options[] =
61   {
62     {"algorithm", required_argument, NULL, 'a'},
63     {"command", required_argument, NULL, 'c'},
64     {"config-directory", required_argument, NULL, 'B'},
65     {"device", required_argument, NULL, 'o'},
66     {"dry-run", no_argument, NULL, 'n'},
67     {"edit", no_argument, NULL, 'n'},
68     {"error-file", required_argument, NULL, 'e'},
69     {"help", no_argument, NULL, 'h'},
70     {"include-directory", required_argument, NULL, 'I'},
71     {"interactive", no_argument, NULL, 'i'},
72     {"just-print", no_argument, NULL, 'n'},
73     {"list", no_argument, NULL, 'l'},
74     {"no-include", no_argument, NULL, 'I'},
75     {"no-statrc", no_argument, NULL, 'r'},
76     {"out-file", required_argument, NULL, 'f'},
77     {"pipe", no_argument, NULL, 'p'},
78     {"recon", no_argument, NULL, 'n'},
79     {"safer", no_argument, NULL, 's'},
80     {"syntax", required_argument, NULL, 'x'},
81     {"testing-mode", no_argument, NULL, 'T'},
82     {"verbose", no_argument, NULL, 'v'},
83     {"version", no_argument, NULL, 'V'},
84     {0, 0, 0, 0},
85   };
86
87   int c, i;
88
89   bool cleared_device_defaults = false;
90   bool process_statrc = true;
91   bool interactive_mode = false;
92   int syntax_files = 0;
93
94   for (;;)
95     {
96       c = getopt_long (argc, argv, "a:x:B:c:e:f:hiI:lno:prsvV", long_options, NULL);
97       if (c == -1)
98         break;
99
100       switch (c)
101         {
102           /* Compatibility options */
103         case 'a':
104           if ( 0 == strcmp(optarg,"compatible") )
105               set_algorithm(COMPATIBLE);
106           else if ( 0 == strcmp(optarg,"enhanced"))
107               set_algorithm(ENHANCED);
108           else
109             {
110               usage ();
111               return false;
112             }
113           break;
114
115         case 'x':         
116           if ( 0 == strcmp(optarg,"compatible") )
117             set_syntax(COMPATIBLE);
118           else if ( 0 == strcmp(optarg,"enhanced"))
119             set_syntax(ENHANCED);
120           else
121             {
122               usage ();
123               return false;
124             }
125           break;
126         case 'e':
127           msg_ui_set_error_file (optarg);
128           break;
129         case 'B':
130           config_path = optarg;
131           break;
132         case 'f':
133           printf (_("%s is not yet implemented."), "-f");
134           putchar('\n');
135           break;
136         case 'h':
137           usage ();
138           return false;
139         case 'i':
140           interactive_mode = true;
141           break;
142         case 'I':
143           if (optarg == NULL || !strcmp (optarg, "-"))
144             getl_clear_include_path (ss);
145           else
146             getl_add_include_dir (ss, optarg);
147           break;
148         case 'l':
149           outp_list_classes ();
150           return false;
151         case 'n':
152           printf (_("%s is not yet implemented."),"-n");
153           putchar('\n');
154           break;
155         case 'o':
156           if (!cleared_device_defaults)
157             {
158               outp_configure_clear ();
159               cleared_device_defaults = true;
160             }
161           outp_configure_add (optarg);
162           break;
163         case 'p':
164           printf (_("%s is not yet implemented."),"-p");
165           putchar('\n');
166           break;
167         case 'r':
168           process_statrc = false;
169           break;
170         case 's':
171           set_safer_mode ();
172           break;
173         case 'v':
174           verbose_increment_level ();
175           break;
176         case 'V':
177           puts (version);
178           puts (legal);
179           return false;
180         case 'T':
181           force_long_view ();
182           set_testing_mode (true);
183           break;
184         case '?':
185           usage ();
186           return false;
187         case 0:
188           break;
189         default:
190           NOT_REACHED ();
191         }
192     }
193
194   if (process_statrc)
195     {
196       char *pspprc_fn = fn_search_path ("rc", config_path);
197       if (pspprc_fn != NULL) 
198         {
199           getl_append_source (ss, create_syntax_file_source (pspprc_fn));
200
201           free (pspprc_fn); 
202         }
203     }
204
205   for (i = optind; i < argc; i++)
206     if (strchr (argv[i], '='))
207       outp_configure_macro (argv[i]);
208     else 
209       {
210         getl_append_source (ss, create_syntax_file_source (argv[i]));
211         syntax_files++;
212       }
213
214   if (!syntax_files || interactive_mode)
215     getl_append_source (ss, create_readln_source () );
216
217   return true;
218 }
219
220 /* Message that describes PSPP command-line syntax. */
221 static const char pre_syntax_message[] =
222 N_("PSPP, a program for statistical analysis of sample data.\n"
223 "\nUsage: %s [OPTION]... FILE...\n"
224 "\nIf a long option shows an argument as mandatory, then it is mandatory\n"
225 "for the equivalent short option also.  Similarly for optional arguments.\n"
226 "\nConfiguration:\n"
227 "  -a, --algorithm={compatible|enhanced}\n"
228 "                            set to `compatible' if you want output\n"
229 "                            calculated from broken algorithms\n"
230 "  -B, --config-dir=DIR      set configuration directory to DIR\n"
231 "  -o, --device=DEVICE       select output driver DEVICE and disable defaults\n"
232 "\nInput and output:\n"
233 "  -e, --error-file=FILE     send error messages to FILE (appended)\n"
234 "  -f, --out-file=FILE       send output to FILE (overwritten)\n"
235 "  -p, --pipe                read syntax from stdin, send output to stdout\n"
236 "  -I-, --no-include         clear include path\n"
237 "  -I, --include=DIR         append DIR to include path\n"
238 "\nLanguage modifiers:\n"
239 "  -i, --interactive         interpret syntax in interactive mode\n"
240 "  -n, --edit                just check syntax; don't actually run the code\n"
241 "  -r, --no-statrc           disable execution of .pspp/rc at startup\n"
242 "  -s, --safer               don't allow some unsafe operations\n"
243 "  -x, --syntax={compatible|enhanced}\n"
244 "                            set to `compatible' if you want only to accept\n"
245 "                            spss compatible syntax\n"
246 "\nInformative output:\n"
247 "  -h, --help                print this help, then exit\n"
248 "  -l, --list                print a list of known driver classes, then exit\n"
249 "  -V, --version             show PSPP version, then exit\n"
250 "  -v, --verbose             increments verbosity level\n"
251 "\nNon-option arguments:\n"
252 " FILE                       syntax file to execute\n"
253 " KEY=VALUE                  overrides macros in output initialization file\n"
254 "\n");
255
256 /* Message that describes PSPP command-line syntax, continued. */
257 static const char post_syntax_message[] = N_("\nReport bugs to <%s>.\n");
258
259 /* Writes a syntax description to stdout. */
260 static void
261 usage (void)
262 {
263   printf (gettext (pre_syntax_message), program_name);
264   outp_list_classes ();
265   printf (gettext (post_syntax_message), PACKAGE_BUGREPORT);
266 }