955a6b0e9c7fda53e2daa1a9b67e9b528f2189bd
[pspp-builds.git] / src / ui / terminal / terminal-opts.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2008  Free Software Foundation
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 "terminal-opts.h"
20
21 #include <argp.h>
22 #include <stdbool.h>
23 #include <xalloc.h>
24 #include <stdlib.h>
25
26 #include <data/settings.h>
27 #include <data/file-name.h>
28 #include <language/syntax-file.h>
29 #include <libpspp/getl.h>
30 #include <libpspp/llx.h>
31 #include <libpspp/string-map.h>
32 #include <libpspp/string-set.h>
33 #include <libpspp/verbose-msg.h>
34 #include <output/driver.h>
35 #include <ui/command-line.h>
36 #include <ui/terminal/msg-ui.h>
37 #include <ui/terminal/read-line.h>
38
39 #include "gl/error.h"
40
41 #include "gettext.h"
42 #define _(msgid) gettext (msgid)
43 #define N_(msgid) msgid
44
45 static const struct argp_option test_options [] =
46   {
47     {"verbose", 'v', 0, 0, N_("Increase diagnostic verbosity level"), 0},
48     {"testing-mode", 'T', 0, OPTION_HIDDEN, 0, 0},
49
50     { 0, 0, 0, 0, 0, 0 }
51   };
52
53 static error_t
54 parse_test_opts (int key, char *arg, struct argp_state *state)
55 {
56   switch (key)
57     {
58     case 'T':
59       settings_set_testing_mode (true);
60       break;
61     case 'v':
62       verbose_increment_level ();
63       break;
64     default:
65       return ARGP_ERR_UNKNOWN;
66     }
67
68   return 0;
69 }
70
71 static const struct argp_option io_options [] =
72   {
73     {"error-file", 'e', "FILE", 0,
74      N_("Send error messages to FILE (appended)"), 0},
75
76     {"device", 'o', "DEVICE", 0,
77      N_("Select output driver DEVICE and disable defaults"), 0},
78
79     {"list", 'l', 0, 0,
80      N_("Print a list of known driver classes, then exit"), 0},
81
82     {"interactive", 'i', 0, 0, N_("Start an interactive session"), 0},
83
84     { 0, 0, 0, 0, 0, 0 }
85   };
86
87
88 static error_t
89 parse_io_opts (int key, char *arg, struct argp_state *state)
90 {
91   struct source_init
92   {
93     struct llx_list file_list;
94     bool interactive;
95
96     /* Output devices. */
97     struct string_map macros;
98     struct string_set drivers;
99   };
100
101   struct fn_element {
102     struct ll ll;
103     const char *fn;
104   };
105
106   struct source_init *sip = state->hook;
107
108   struct source_stream *ss = state->input;
109
110   struct command_line_processor *clp = get_subject (state);
111
112   switch (key)
113     {
114     case ARGP_KEY_INIT:
115       state->hook = sip = xzalloc (sizeof (struct source_init));
116       llx_init (&sip->file_list);
117       string_map_init (&sip->macros);
118       string_set_init (&sip->drivers);
119       break;
120     case ARGP_KEY_ARG:
121       if (strchr (arg, '='))
122         {
123           if (!output_define_macro (arg, &sip->macros))
124             error (0, 0, _("\"%s\" is not a valid macro definition"), arg);
125         }
126       else
127         {
128           llx_push_tail (&sip->file_list, arg, &llx_malloc_mgr);
129         }
130       break;
131     case ARGP_KEY_SUCCESS:
132       {
133       struct llx *llx = llx_null (&sip->file_list);
134       while ((llx = llx_next (llx)) != llx_null (&sip->file_list))
135         {
136           const char *fn = llx_data (llx);
137           /* Assume it's a syntax file */
138           getl_append_source (ss,
139                               create_syntax_file_source (fn),
140                               GETL_BATCH,
141                               ERRMODE_CONTINUE
142                               );
143
144         }
145
146       if (sip->interactive || llx_is_empty (&sip->file_list))
147         {
148           getl_append_source (ss, create_readln_source (),
149                               GETL_INTERACTIVE,
150                               ERRMODE_CONTINUE
151                               );
152
153           string_set_insert (&sip->drivers, "interactive");
154         }
155
156       if (!settings_get_testing_mode ())
157         output_read_configuration (&sip->macros, &sip->drivers);
158       else
159         output_configure_driver ("csv:csv::");
160
161       string_map_destroy (&sip->macros);
162       string_set_destroy (&sip->drivers);
163       }
164       break;
165     case ARGP_KEY_FINI:
166       free (sip);
167       break;
168     case 'e':
169       msg_ui_set_error_file (arg);
170       break;
171     case 'i':
172       sip->interactive = true;
173       break;
174     case 'l':
175       output_list_classes ();
176       break;
177     case 'o':
178       string_set_insert (&sip->drivers, arg);
179       break;
180     default:
181       return ARGP_ERR_UNKNOWN;
182     }
183
184   return 0;
185 }
186
187 const struct argp io_argp =  {io_options, parse_io_opts, 0, 0, 0, 0, 0};
188 const struct argp test_argp =  {test_options, parse_test_opts, 0, 0, 0, 0, 0};
189
190 #if 0
191 static const struct argp_child children [] =
192   {
193     {&io_argp, 0, N_("Options affecting input and output locations:"), 0},
194     {&test_argp, 0, N_("Diagnostic options:"), 0},
195     {0, 0, 0, 0}
196   };
197
198
199 static error_t
200 propagate_aux (int key, char *arg, struct argp_state *state)
201 {
202   if ( key == ARGP_KEY_INIT)
203     {
204       int i;
205       for (i = 0 ; i < sizeof (children) / sizeof (children[0]) - 1 ; ++i)
206         state->child_inputs[i] = state->input;
207     }
208
209   return ARGP_ERR_UNKNOWN;
210 }
211
212 const struct argp terminal_argp =  {NULL, propagate_aux, 0, 0, children, 0, 0};
213
214 #endif