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