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