usage: Print metavariables in SHOUTY letters.
[sw-tools] / src / sw.c
CommitLineData
3315e8b3 1/* -*-c-*-
2 *
9796a787 3 * $Id: sw.c,v 1.4 2004/04/08 01:52:19 mdw Exp $
3315e8b3 4 *
5 * Main driver code for sw-tools
6 *
7 * (c) 1999 EBI
8 */
9
10/*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of sw-tools.
13 *
14 * sw-tools is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * sw-tools is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with sw-tools; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 */
28
3315e8b3 29/*----- Header files ------------------------------------------------------*/
30
31#include "config.h"
32
33#include <ctype.h>
34#include <errno.h>
35#include <signal.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39
40#include <unistd.h>
41
42#include <mLib/alloc.h>
43#include <mLib/dstr.h>
44#include <mLib/exc.h>
45#include <mLib/mdwopt.h>
46#include <mLib/quis.h>
47#include <mLib/report.h>
48#include <mLib/sub.h>
49
50#define CMD_LINK 0
51#include "sw.h"
52#include "sw_arch.h"
53#include "sw_build.h"
54#include "sw_info.h"
55#include "sw_links.h"
56#include "sw_rsh.h"
57
58/*----- Static variables --------------------------------------------------*/
59
60static cmd *cmds = CMD_LINK;
61
62/*----- Global option variables -------------------------------------------*
63 *
64 * It'd be nicer if these could be parsed by the build commands, but alas
65 * this is not to be. Consider `sw configure --arch=i386-linux
66 * --with-diffutils': how is the program to know which options are for it and
67 * which are for the remote one? The `configure' command is important,
68 * because it does some hairy stuff under the covers (inserting magical
69 * options, and running `../configure'), so I can't just require `sw run
70 * configure'. Requiring the user to always put in a `--' to separate the
71 * two lots of options is horrific. So they get picked up at the main
72 * program and stuffed into global variables.
73 *
74 * On the other hand, there is the advantage that `--output' options can be
75 * put in an environment variable here.
76 */
77
78const char *opt_output = 0;
79const char *opt_arch = 0;
1efab4fe 80unsigned int opt_flags = optFlag_percent;
3315e8b3 81
82/*----- Helpful GNUy message routines -------------------------------------*/
83
84/* --- @version@ --- */
85
86static void version(FILE *fp)
87{
88 fprintf(fp, "%s v. " VERSION "\n", QUIS);
89}
90
91/* --- @usage@ --- */
92
93static void usage(FILE *fp)
94{
afdcbf8e 95 fprintf(fp, "Usage: %s [-fbip] [-a ARCH,...] [-o STYLE] COMMAND [ARGS]\n",
3315e8b3 96 QUIS);
97}
98
99/* --- @help@ --- */
100
101static void help(FILE *fp, int full)
102{
103 cmd *p;
104 version(fp);
105 fputc('\n', fp);
106 usage(fp);
107 fputs("\n\
108Performs various handy jobs with multiple-architecture builds.\n\
109\n\
110There are some options which affect a few of the available commands:\n\
111\n\
112-a, --arch=ARCH,... Only build on the named architectures.\n\
113-b, --beep Beep when the build is complete.\n\
114-i, --install Mark architectures as done when build succeeds.\n\
115-f, --force Run build commands on installed architectures.\n\
1efab4fe 116-p, --percent Enable `%'-escapes in build command arguments.\n\
3315e8b3 117-o, --output=STYLE Display output in a particular style. Use style\n\
118 `help' for a list.\n\
119\n", fp);
120
121 if (full) {
122 fputs("The various commands provided are:\n\n", fp);
123 for (p = cmds; p; p = p->next) {
124 fputs(p->help, fp);
125 fputc('\n', fp);
126 }
127 fprintf(fp,
128"`%s' is an [mdw] production, brought to you in association with the\n\
129European Bioinformatics Institute.\n", QUIS);
130 } else {
131 fputs("The various commands, in summary:\n\n", fp);
132 for (p = cmds; p; p = p->next) {
133 size_t sz = strcspn(p->help, "\n\t");
134 fwrite(p->help, 1, sz, fp);
135 fputc('\n', fp);
136 }
137 fprintf(fp,
138"\nType `%s --help-full' for complete information. There's a lot of it!\n",
139 QUIS);
140 }
141}
142
143/*----- Main code ---------------------------------------------------------*/
144
145/* --- @main@ --- *
146 *
147 * Arguments: @int argc@ = number of command line arguments
148 * @char *argv[]@ = array of command line strings
149 *
150 * Returns: Zero on success, nonzero on failure.
151 *
152 * Use: Main program. Parses some trivial arguments out, and
153 * dispatches control to one of the subprogram handlers.
154 */
155
156int main(int argc, char *argv[])
157{
158 unsigned f = 0;
159
160 enum {
161 f_bogus = 1
162 };
163
164 /* --- Initialize the support library --- */
165
166 ego(argv[0]);
167 sub_init();
168
169 /* --- Parse command line flags --- */
170
171 for (;;) {
172 static struct option opt[] = {
173
174 /* --- Standard GNUy help options --- */
175
176 { "help", 0, 0, 'h' },
177 { "help-full", 0, 0, 'H' },
178 { "version", 0, 0, 'v' },
179 { "usage", 0, 0, 'u' },
180
181 /* --- Build options --- *
182 *
183 */
184
185 { "arch", OPTF_ARGREQ, 0, 'a' },
186 { "force", 0, 0, 'f' },
187 { "install", 0, 0, 'i' },
188 { "output", OPTF_ARGREQ, 0, 'o' },
1efab4fe 189 { "beep", OPTF_NEGATE, 0, 'b' },
190 { "percent", OPTF_NEGATE, 0, 'p' },
191 { "escape", OPTF_NEGATE, 0, 'p' },
3315e8b3 192
193 /* --- Internal-use-only magical options --- *
194 *
195 * You get what you deserve if you use this.
196 */
197
198 { "me", OPTF_ARGREQ, 0, '=' },
199 { "remote", OPTF_ARGREQ, 0, '!' },
200
201 /* --- Termination marker --- */
202
203 { 0, 0, 0, 0 }
204 };
1efab4fe 205 int i = mdwopt(argc, argv, "+hHvu a:b+p+fio:", opt, 0, 0,
206 OPTF_ENVVAR | OPTF_NEGATION);
3315e8b3 207 if (i < 0)
208 break;
209
210 switch (i) {
211
212 /* --- GNUy help --- */
213
214 case 'h':
215 help(stdout, 0);
216 exit(0);
217 case 'H':
218 help(stdout, 1);
219 exit(0);
220 case 'v':
221 version(stdout);
222 exit(0);
223 case 'u':
224 usage(stdout);
225 exit(0);
226
227 /* --- Build options --- */
228
229 case 'a':
230 opt_arch = optarg;
231 break;
232 case 'f':
233 opt_flags |= optFlag_force;
234 break;
235 case 'b':
236 opt_flags |= optFlag_beep;
237 break;
1efab4fe 238 case 'b' | OPTF_NEGATED:
239 opt_flags &= ~optFlag_beep;
240 break;
241 case 'p':
242 opt_flags |= optFlag_percent;
243 break;
244 case 'p' | OPTF_NEGATED:
245 opt_flags &= ~optFlag_percent;
246 break;
3315e8b3 247 case 'i':
248 opt_flags |= optFlag_install;
249 break;
250 case 'o':
251 opt_output = optarg;
252 break;
253
254 /* --- Magical options for internal use --- */
255
256 case '=':
257 ego(optarg);
258 break;
259 case '!':
260 swrsh_remote(optarg);
261 _exit(1);
262
263 /* --- The user screwed up --- */
264
265 default:
266 f |= f_bogus;
267 break;
268 }
269 }
270
271 if (f & f_bogus || argc == optind) {
272 usage(stderr);
273 exit(1);
274 }
275
276 /* --- Pick up the operation name --- */
277
278 argc -= optind;
279 argv += optind;
280 optind = 0;
281
282 {
283 cmd *p, *chosen = 0;
284 const char *which = argv[0];
285 size_t sz = strlen(which);
286
287 for (p = cmds; p; p = p->next) {
288 if (strncmp(which, p->name, sz) == 0) {
289 if (p->name[sz] == 0) {
290 chosen = p;
291 break;
292 } else if (chosen)
293 die(1, "ambiguous command name `%s'", which);
294 chosen = p;
295 }
296 }
297
298 if (!chosen)
299 die(1, "unknown command name `%s'", which);
300 signal(SIGPIPE, SIG_IGN);
301 TRY
302 return (chosen->cmd(argc, argv));
303 CATCH switch (exc_type) {
304 case EXC_NOMEM:
305 die(1, "not enough memory");
306 default:
307 RETHROW;
308 } END_TRY;
309 }
310 return (127);
311}
312
313/*----- That's all, folks -------------------------------------------------*/