Merge commit 'origin/stable'
[pspp-builds.git] / src / ui / command-line.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
18 #include <config.h>
19 #include "command-line.h"
20 #include <argp.h>
21 #include <gl/xalloc.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <libpspp/compiler.h>
25 #include <assert.h>
26
27
28 struct clp_child
29 {
30   void *aux;
31 };
32
33 struct command_line_processor
34 {
35   struct argp master_parser;
36
37   struct clp_child *child_lookup_table;
38   struct argp_child *children;
39   int n_children;
40
41   const char *doc;
42   const char *args_doc;
43
44   void *aux;
45 };
46
47
48 /* Convenience function for use in parsing functions.
49    Returns the object for this parser */
50 struct command_line_processor *
51 get_subject (struct argp_state *state)
52 {
53   const struct argp *root = state->root_argp;
54
55   const struct argp_child *children = root->children;
56
57   return  (struct command_line_processor *) children[0].argp;
58 }
59
60
61 /* Create a command line processor.
62    DOC is typically the name of the program and short description.
63    ARGS_DOC is a short description of the non option arguments.
64    AUX is an arbitrary pointer.
65  */
66 struct command_line_processor *
67 command_line_processor_create (const char *doc, const char *args_doc, void *aux)
68 {
69   struct command_line_processor *clp = xzalloc (sizeof (*clp));
70
71   clp->children = NULL;
72   clp->child_lookup_table = NULL;
73
74   clp->doc = doc;
75   clp->args_doc = args_doc;
76   clp->aux = aux;
77
78   return clp;
79 }
80
81 /* Destroy a command line processor */
82 void
83 command_line_processor_destroy (struct command_line_processor *clp)
84 {
85   free (clp->children);
86   free (clp->child_lookup_table);
87   free (clp);
88 }
89
90
91 /* Add a CHILD to the processor CLP, with the doc string DOC.
92    AUX is an auxilliary pointer, specific to CHILD.
93    If AUX is not known or not needed then it may be set to NULL
94 */
95 void
96 command_line_processor_add_options (struct command_line_processor *clp, const struct argp *child,
97                                const char *doc, void *aux)
98 {
99   clp->n_children++;
100
101   clp->children = xrealloc (clp->children, (clp->n_children + 1) * sizeof (*clp->children));
102   memset (&clp->children[clp->n_children - 1], 0, sizeof (*clp->children));
103
104   clp->child_lookup_table = xrealloc (clp->child_lookup_table,
105                                       clp->n_children * sizeof (*clp->child_lookup_table));
106
107   clp->child_lookup_table [clp->n_children - 1].aux = aux;
108
109   clp->children [clp->n_children - 1].argp = child;
110   clp->children [clp->n_children - 1].header = doc;
111   clp->children [clp->n_children].argp = NULL;
112 }
113
114
115 /* Set the aux paramter for CHILD in CLP to AUX.
116    Any previous value will be overwritten.
117  */
118 void
119 command_line_processor_replace_aux (struct command_line_processor *clp, const struct argp *child, void *aux)
120 {
121   int i;
122   for (i = 0 ; i < clp->n_children; ++i )
123     {
124       if (child->options == clp->children[i].argp->options)
125         {
126           clp->child_lookup_table[i].aux = aux;
127           break;
128         }
129     }
130   assert (i < clp->n_children);
131 }
132
133
134 static error_t
135 top_level_parser (int key UNUSED, char *arg UNUSED, struct argp_state *state)
136 {
137   int i;
138   struct command_line_processor *clp = state->input;
139
140   if ( key == ARGP_KEY_INIT)
141     {
142
143       for (i = 0;  i < clp->n_children ; ++i)
144         {
145           state->child_inputs[i] = clp->child_lookup_table[i].aux;
146         }
147     }
148
149   return ARGP_ERR_UNKNOWN;
150 }
151
152
153 /* Parse the command line specified by (ARGC, ARGV) using CLP */
154 void
155 command_line_processor_parse (struct command_line_processor *clp, int argc, char **argv)
156 {
157   clp->master_parser.parser = top_level_parser;
158   clp->master_parser.args_doc = clp->args_doc;
159
160   clp->master_parser.doc = clp->doc;
161
162   clp->master_parser.children = clp->children;
163
164   argp_parse (&clp->master_parser, argc, argv, 0, 0, clp);
165 }
166