xref: /titanic_52/usr/src/tools/aw/aw.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * Wrapper for the GNU assembler to make it accept the Sun assembler
31*7c478bd9Sstevel@tonic-gate  * arguments where possible.
32*7c478bd9Sstevel@tonic-gate  *
33*7c478bd9Sstevel@tonic-gate  * There are several limitations; the Sun assembler takes multiple
34*7c478bd9Sstevel@tonic-gate  * source files, we only take one.
35*7c478bd9Sstevel@tonic-gate  *
36*7c478bd9Sstevel@tonic-gate  * -b, -s, -xF, -T plain not supported.
37*7c478bd9Sstevel@tonic-gate  * -S isn't supported either, because while GNU as does generate
38*7c478bd9Sstevel@tonic-gate  * listings with -a, there's no obvious mapping between sub-options.
39*7c478bd9Sstevel@tonic-gate  * -K pic, -K PIC not supported either, though it's not clear what
40*7c478bd9Sstevel@tonic-gate  * these actually do ..
41*7c478bd9Sstevel@tonic-gate  * -Qy (not supported) adds a string to the .comment section
42*7c478bd9Sstevel@tonic-gate  * describing the assembler version, while
43*7c478bd9Sstevel@tonic-gate  * -Qn (supported) suppresses the string (also the default).
44*7c478bd9Sstevel@tonic-gate  *
45*7c478bd9Sstevel@tonic-gate  * We also add '-#' support to see invocation lines..
46*7c478bd9Sstevel@tonic-gate  * We also add '-xarch=amd64' in case we need to feed the assembler
47*7c478bd9Sstevel@tonic-gate  * something different (or in case we need to invoke a different binary
48*7c478bd9Sstevel@tonic-gate  * altogether!)
49*7c478bd9Sstevel@tonic-gate  */
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
52*7c478bd9Sstevel@tonic-gate #include <sys/wait.h>
53*7c478bd9Sstevel@tonic-gate #include <stdio.h>
54*7c478bd9Sstevel@tonic-gate #include <unistd.h>
55*7c478bd9Sstevel@tonic-gate #include <string.h>
56*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate static const char *progname;
59*7c478bd9Sstevel@tonic-gate static int verbose;
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate struct aelist {
62*7c478bd9Sstevel@tonic-gate 	int ael_argc;
63*7c478bd9Sstevel@tonic-gate 	struct ae {
64*7c478bd9Sstevel@tonic-gate 		struct ae *ae_next;
65*7c478bd9Sstevel@tonic-gate 		char *ae_arg;
66*7c478bd9Sstevel@tonic-gate 	} *ael_head, *ael_tail;
67*7c478bd9Sstevel@tonic-gate };
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate static struct aelist *
70*7c478bd9Sstevel@tonic-gate newael(void)
71*7c478bd9Sstevel@tonic-gate {
72*7c478bd9Sstevel@tonic-gate 	return (calloc(sizeof (struct aelist), 1));
73*7c478bd9Sstevel@tonic-gate }
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate static void
76*7c478bd9Sstevel@tonic-gate newae(struct aelist *ael, const char *arg)
77*7c478bd9Sstevel@tonic-gate {
78*7c478bd9Sstevel@tonic-gate 	struct ae *ae;
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate 	ae = calloc(sizeof (*ae), 1);
81*7c478bd9Sstevel@tonic-gate 	ae->ae_arg = strdup(arg);
82*7c478bd9Sstevel@tonic-gate 	if (ael->ael_tail == NULL)
83*7c478bd9Sstevel@tonic-gate 		ael->ael_head = ae;
84*7c478bd9Sstevel@tonic-gate 	else
85*7c478bd9Sstevel@tonic-gate 		ael->ael_tail->ae_next = ae;
86*7c478bd9Sstevel@tonic-gate 	ael->ael_tail = ae;
87*7c478bd9Sstevel@tonic-gate 	ael->ael_argc++;
88*7c478bd9Sstevel@tonic-gate }
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate static void
91*7c478bd9Sstevel@tonic-gate fixae_arg(struct ae *ae, const char *newarg)
92*7c478bd9Sstevel@tonic-gate {
93*7c478bd9Sstevel@tonic-gate 	free(ae->ae_arg);
94*7c478bd9Sstevel@tonic-gate 	ae->ae_arg = strdup(newarg);
95*7c478bd9Sstevel@tonic-gate }
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate static char **
98*7c478bd9Sstevel@tonic-gate aeltoargv(struct aelist *ael)
99*7c478bd9Sstevel@tonic-gate {
100*7c478bd9Sstevel@tonic-gate 	struct ae *ae;
101*7c478bd9Sstevel@tonic-gate 	char **argv;
102*7c478bd9Sstevel@tonic-gate 	int argc;
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate 	argv = calloc(sizeof (*argv), ael->ael_argc + 1);
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate 	for (argc = 0, ae = ael->ael_head; ae; ae = ae->ae_next, argc++) {
107*7c478bd9Sstevel@tonic-gate 		argv[argc] = ae->ae_arg;
108*7c478bd9Sstevel@tonic-gate 		if (ae == ael->ael_tail)
109*7c478bd9Sstevel@tonic-gate 			break;
110*7c478bd9Sstevel@tonic-gate 	}
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate 	return (argv);
113*7c478bd9Sstevel@tonic-gate }
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate static int
116*7c478bd9Sstevel@tonic-gate error(const char *arg)
117*7c478bd9Sstevel@tonic-gate {
118*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
119*7c478bd9Sstevel@tonic-gate 	    "%s: as->gas mapping failed at or near arg '%s'\n", progname, arg);
120*7c478bd9Sstevel@tonic-gate 	return (2);
121*7c478bd9Sstevel@tonic-gate }
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate static int
124*7c478bd9Sstevel@tonic-gate usage(const char *arg)
125*7c478bd9Sstevel@tonic-gate {
126*7c478bd9Sstevel@tonic-gate 	if (arg != NULL)
127*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "error: %s\n", arg);
128*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "Usage: %s [-V] [-#]\n"
129*7c478bd9Sstevel@tonic-gate 	    "\t[-xarch=architecture]\n"
130*7c478bd9Sstevel@tonic-gate 	    "\t[-o objfile] [-L]\n"
131*7c478bd9Sstevel@tonic-gate 	    "\t[-P [[-Ipath] [-Dname] [-Dname=def] [-Uname]]...]\n"
132*7c478bd9Sstevel@tonic-gate 	    "\t[-m] [-n] file.s ...\n", progname);
133*7c478bd9Sstevel@tonic-gate 	return (3);
134*7c478bd9Sstevel@tonic-gate }
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate static void
137*7c478bd9Sstevel@tonic-gate copyuntil(FILE *in, FILE *out, int termchar)
138*7c478bd9Sstevel@tonic-gate {
139*7c478bd9Sstevel@tonic-gate 	int c;
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate 	while ((c = fgetc(in)) != EOF) {
142*7c478bd9Sstevel@tonic-gate 		if (out && fputc(c, out) == EOF)
143*7c478bd9Sstevel@tonic-gate 			exit(1);
144*7c478bd9Sstevel@tonic-gate 		if (c == termchar)
145*7c478bd9Sstevel@tonic-gate 			break;
146*7c478bd9Sstevel@tonic-gate 	}
147*7c478bd9Sstevel@tonic-gate }
148*7c478bd9Sstevel@tonic-gate 
149*7c478bd9Sstevel@tonic-gate /*
150*7c478bd9Sstevel@tonic-gate  * The idea here is to take directives like this emitted
151*7c478bd9Sstevel@tonic-gate  * by cpp:
152*7c478bd9Sstevel@tonic-gate  *
153*7c478bd9Sstevel@tonic-gate  *	# num
154*7c478bd9Sstevel@tonic-gate  *
155*7c478bd9Sstevel@tonic-gate  * and convert them to directives like this that are
156*7c478bd9Sstevel@tonic-gate  * understood by the GNU assembler:
157*7c478bd9Sstevel@tonic-gate  *
158*7c478bd9Sstevel@tonic-gate  *	.line num
159*7c478bd9Sstevel@tonic-gate  *
160*7c478bd9Sstevel@tonic-gate  * and similarly:
161*7c478bd9Sstevel@tonic-gate  *
162*7c478bd9Sstevel@tonic-gate  *	# num "string" optional stuff
163*7c478bd9Sstevel@tonic-gate  *
164*7c478bd9Sstevel@tonic-gate  * is converted to
165*7c478bd9Sstevel@tonic-gate  *
166*7c478bd9Sstevel@tonic-gate  *	.line num
167*7c478bd9Sstevel@tonic-gate  *	.file "string"
168*7c478bd9Sstevel@tonic-gate  *
169*7c478bd9Sstevel@tonic-gate  * While this could be done with a sequence of sed
170*7c478bd9Sstevel@tonic-gate  * commands, this is simpler and faster..
171*7c478bd9Sstevel@tonic-gate  */
172*7c478bd9Sstevel@tonic-gate static pid_t
173*7c478bd9Sstevel@tonic-gate filter(int pipein, int pipeout)
174*7c478bd9Sstevel@tonic-gate {
175*7c478bd9Sstevel@tonic-gate 	pid_t pid;
176*7c478bd9Sstevel@tonic-gate 	FILE *in, *out;
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate 	if (verbose)
179*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "{#line filter} ");
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate 	switch (pid = fork()) {
182*7c478bd9Sstevel@tonic-gate 	case 0:
183*7c478bd9Sstevel@tonic-gate 		if (dup2(pipein, 0) == -1 ||
184*7c478bd9Sstevel@tonic-gate 		    dup2(pipeout, 1) == -1) {
185*7c478bd9Sstevel@tonic-gate 			perror("dup2");
186*7c478bd9Sstevel@tonic-gate 			exit(1);
187*7c478bd9Sstevel@tonic-gate 		}
188*7c478bd9Sstevel@tonic-gate 		closefrom(3);
189*7c478bd9Sstevel@tonic-gate 		break;
190*7c478bd9Sstevel@tonic-gate 	case -1:
191*7c478bd9Sstevel@tonic-gate 		perror("fork");
192*7c478bd9Sstevel@tonic-gate 	default:
193*7c478bd9Sstevel@tonic-gate 		return (pid);
194*7c478bd9Sstevel@tonic-gate 	}
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate 	in = fdopen(0, "r");
197*7c478bd9Sstevel@tonic-gate 	out = fdopen(1, "w");
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate 	while (!feof(in)) {
200*7c478bd9Sstevel@tonic-gate 		int c, num;
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 		switch (c = fgetc(in)) {
203*7c478bd9Sstevel@tonic-gate 		case '#':
204*7c478bd9Sstevel@tonic-gate 			switch (fscanf(in, " %d", &num)) {
205*7c478bd9Sstevel@tonic-gate 			case 0:
206*7c478bd9Sstevel@tonic-gate 				/*
207*7c478bd9Sstevel@tonic-gate 				 * discard comment lines completely
208*7c478bd9Sstevel@tonic-gate 				 * discard ident strings completely too.
209*7c478bd9Sstevel@tonic-gate 				 * (GNU as politely ignores them..)
210*7c478bd9Sstevel@tonic-gate 				 */
211*7c478bd9Sstevel@tonic-gate 				copyuntil(in, NULL, '\n');
212*7c478bd9Sstevel@tonic-gate 				break;
213*7c478bd9Sstevel@tonic-gate 			default:
214*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "fscanf botch?");
215*7c478bd9Sstevel@tonic-gate 				/*FALLTHROUGH*/
216*7c478bd9Sstevel@tonic-gate 			case EOF:
217*7c478bd9Sstevel@tonic-gate 				exit(1);
218*7c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
219*7c478bd9Sstevel@tonic-gate 			case 1:
220*7c478bd9Sstevel@tonic-gate 				/*
221*7c478bd9Sstevel@tonic-gate 				 * This line has a number at the beginning;
222*7c478bd9Sstevel@tonic-gate 				 * if it has a string after the number, then
223*7c478bd9Sstevel@tonic-gate 				 * it's a filename.
224*7c478bd9Sstevel@tonic-gate 				 */
225*7c478bd9Sstevel@tonic-gate 				if (fgetc(in) == ' ' && fgetc(in) == '"') {
226*7c478bd9Sstevel@tonic-gate 					(void) fprintf(out, "\t.file \"");
227*7c478bd9Sstevel@tonic-gate 					copyuntil(in, out, '"');
228*7c478bd9Sstevel@tonic-gate 					(void) fputc('\n', out);
229*7c478bd9Sstevel@tonic-gate 				}
230*7c478bd9Sstevel@tonic-gate 				(void) fprintf(out, "\t.line %d\n", num - 1);
231*7c478bd9Sstevel@tonic-gate 				/*
232*7c478bd9Sstevel@tonic-gate 				 * discard the rest of the line
233*7c478bd9Sstevel@tonic-gate 				 */
234*7c478bd9Sstevel@tonic-gate 				copyuntil(in, NULL, '\n');
235*7c478bd9Sstevel@tonic-gate 				break;
236*7c478bd9Sstevel@tonic-gate 			}
237*7c478bd9Sstevel@tonic-gate 			break;
238*7c478bd9Sstevel@tonic-gate 		case '\n':
239*7c478bd9Sstevel@tonic-gate 			/*
240*7c478bd9Sstevel@tonic-gate 			 * preserve newlines
241*7c478bd9Sstevel@tonic-gate 			 */
242*7c478bd9Sstevel@tonic-gate 			(void) fputc(c, out);
243*7c478bd9Sstevel@tonic-gate 			break;
244*7c478bd9Sstevel@tonic-gate 		case EOF:
245*7c478bd9Sstevel@tonic-gate 			/*
246*7c478bd9Sstevel@tonic-gate 			 * don't write EOF!
247*7c478bd9Sstevel@tonic-gate 			 */
248*7c478bd9Sstevel@tonic-gate 			break;
249*7c478bd9Sstevel@tonic-gate 		default:
250*7c478bd9Sstevel@tonic-gate 			/*
251*7c478bd9Sstevel@tonic-gate 			 * lines that don't begin with '#' are copied
252*7c478bd9Sstevel@tonic-gate 			 */
253*7c478bd9Sstevel@tonic-gate 			(void) fputc(c, out);
254*7c478bd9Sstevel@tonic-gate 			copyuntil(in, out, '\n');
255*7c478bd9Sstevel@tonic-gate 			break;
256*7c478bd9Sstevel@tonic-gate 		}
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate 		if (ferror(out))
259*7c478bd9Sstevel@tonic-gate 			exit(1);
260*7c478bd9Sstevel@tonic-gate 	}
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate 	exit(0);
263*7c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
264*7c478bd9Sstevel@tonic-gate }
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate static pid_t
267*7c478bd9Sstevel@tonic-gate invoke(char **argv, int pipein, int pipeout)
268*7c478bd9Sstevel@tonic-gate {
269*7c478bd9Sstevel@tonic-gate 	pid_t pid;
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate 	if (verbose) {
272*7c478bd9Sstevel@tonic-gate 		char **dargv = argv;
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate 		while (*dargv)
275*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s ", *dargv++);
276*7c478bd9Sstevel@tonic-gate 	}
277*7c478bd9Sstevel@tonic-gate 
278*7c478bd9Sstevel@tonic-gate 	switch (pid = fork()) {
279*7c478bd9Sstevel@tonic-gate 	case 0:
280*7c478bd9Sstevel@tonic-gate 		if (pipein >= 0 && dup2(pipein, 0) == -1) {
281*7c478bd9Sstevel@tonic-gate 			perror("dup2");
282*7c478bd9Sstevel@tonic-gate 			exit(1);
283*7c478bd9Sstevel@tonic-gate 		}
284*7c478bd9Sstevel@tonic-gate 		if (pipeout >= 0 && dup2(pipeout, 1) == -1) {
285*7c478bd9Sstevel@tonic-gate 			perror("dup2");
286*7c478bd9Sstevel@tonic-gate 			exit(1);
287*7c478bd9Sstevel@tonic-gate 		}
288*7c478bd9Sstevel@tonic-gate 		closefrom(3);
289*7c478bd9Sstevel@tonic-gate 		(void) execvp(argv[0], argv);
290*7c478bd9Sstevel@tonic-gate 		perror("execvp");
291*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: couldn't run %s\n",
292*7c478bd9Sstevel@tonic-gate 		    progname, argv[0]);
293*7c478bd9Sstevel@tonic-gate 		break;
294*7c478bd9Sstevel@tonic-gate 	case -1:
295*7c478bd9Sstevel@tonic-gate 		perror("fork");
296*7c478bd9Sstevel@tonic-gate 	default:
297*7c478bd9Sstevel@tonic-gate 		return (pid);
298*7c478bd9Sstevel@tonic-gate 	}
299*7c478bd9Sstevel@tonic-gate 	exit(2);
300*7c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
301*7c478bd9Sstevel@tonic-gate }
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate static int
304*7c478bd9Sstevel@tonic-gate pipeline(char **ppargv, char **asargv)
305*7c478bd9Sstevel@tonic-gate {
306*7c478bd9Sstevel@tonic-gate 	int pipedes[4];
307*7c478bd9Sstevel@tonic-gate 	int active = 0;
308*7c478bd9Sstevel@tonic-gate 	int rval = 0;
309*7c478bd9Sstevel@tonic-gate 	pid_t pid_pp, pid_f, pid_as;
310*7c478bd9Sstevel@tonic-gate 
311*7c478bd9Sstevel@tonic-gate 	if (pipe(pipedes) == -1 || pipe(pipedes + 2) == -1) {
312*7c478bd9Sstevel@tonic-gate 		perror("pipe");
313*7c478bd9Sstevel@tonic-gate 		return (4);
314*7c478bd9Sstevel@tonic-gate 	}
315*7c478bd9Sstevel@tonic-gate 
316*7c478bd9Sstevel@tonic-gate 	if ((pid_pp = invoke(ppargv, -1, pipedes[0])) > 0)
317*7c478bd9Sstevel@tonic-gate 		active++;
318*7c478bd9Sstevel@tonic-gate 
319*7c478bd9Sstevel@tonic-gate 	if (verbose)
320*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "| ");
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate 	if ((pid_f = filter(pipedes[1], pipedes[2])) > 0)
323*7c478bd9Sstevel@tonic-gate 		active++;
324*7c478bd9Sstevel@tonic-gate 
325*7c478bd9Sstevel@tonic-gate 	if (verbose)
326*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "| ");
327*7c478bd9Sstevel@tonic-gate 
328*7c478bd9Sstevel@tonic-gate 	if ((pid_as = invoke(asargv, pipedes[3], -1)) > 0)
329*7c478bd9Sstevel@tonic-gate 		active++;
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate 	if (verbose) {
332*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "\n");
333*7c478bd9Sstevel@tonic-gate 		(void) fflush(stderr);
334*7c478bd9Sstevel@tonic-gate 	}
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate 	closefrom(3);
337*7c478bd9Sstevel@tonic-gate 
338*7c478bd9Sstevel@tonic-gate 	if (active != 3)
339*7c478bd9Sstevel@tonic-gate 		return (5);
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate 	while (active != 0) {
342*7c478bd9Sstevel@tonic-gate 		pid_t pid;
343*7c478bd9Sstevel@tonic-gate 		int stat;
344*7c478bd9Sstevel@tonic-gate 
345*7c478bd9Sstevel@tonic-gate 		if ((pid = wait(&stat)) == -1) {
346*7c478bd9Sstevel@tonic-gate 			rval++;
347*7c478bd9Sstevel@tonic-gate 			break;
348*7c478bd9Sstevel@tonic-gate 		}
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate 		if (!WIFEXITED(stat))
351*7c478bd9Sstevel@tonic-gate 			continue;
352*7c478bd9Sstevel@tonic-gate 
353*7c478bd9Sstevel@tonic-gate 		if (pid == pid_pp || pid == pid_f || pid == pid_as) {
354*7c478bd9Sstevel@tonic-gate 			active--;
355*7c478bd9Sstevel@tonic-gate 			if (WEXITSTATUS(stat) != 0)
356*7c478bd9Sstevel@tonic-gate 				rval++;
357*7c478bd9Sstevel@tonic-gate 		}
358*7c478bd9Sstevel@tonic-gate 	}
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate 	return (rval);
361*7c478bd9Sstevel@tonic-gate }
362*7c478bd9Sstevel@tonic-gate 
363*7c478bd9Sstevel@tonic-gate int
364*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
365*7c478bd9Sstevel@tonic-gate {
366*7c478bd9Sstevel@tonic-gate 	struct aelist *cpp = NULL;
367*7c478bd9Sstevel@tonic-gate 	struct aelist *m4 = NULL;
368*7c478bd9Sstevel@tonic-gate 	struct aelist *as = newael();
369*7c478bd9Sstevel@tonic-gate 	char **asargv;
370*7c478bd9Sstevel@tonic-gate 	char *outfile = NULL;
371*7c478bd9Sstevel@tonic-gate 	char *srcfile = NULL;
372*7c478bd9Sstevel@tonic-gate 	const char *as_dir, *as64_dir, *m4_dir, *m4_lib_dir, *cpp_dir;
373*7c478bd9Sstevel@tonic-gate 	char *as_pgm, *as64_pgm, *m4_pgm, *m4_cmdefs, *cpp_pgm;
374*7c478bd9Sstevel@tonic-gate 	int as64 = 0;
375*7c478bd9Sstevel@tonic-gate 	int code;
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate 	if ((progname = strrchr(argv[0], '/')) == NULL)
378*7c478bd9Sstevel@tonic-gate 		progname = argv[0];
379*7c478bd9Sstevel@tonic-gate 	else
380*7c478bd9Sstevel@tonic-gate 		progname++;
381*7c478bd9Sstevel@tonic-gate 
382*7c478bd9Sstevel@tonic-gate 	/*
383*7c478bd9Sstevel@tonic-gate 	 * Helpful when debugging, or when changing tool versions..
384*7c478bd9Sstevel@tonic-gate 	 */
385*7c478bd9Sstevel@tonic-gate 	if ((as_dir = getenv("AW_AS_DIR")) == NULL)
386*7c478bd9Sstevel@tonic-gate 		as_dir = DEFAULT_AS_DIR;	/* /usr/sfw/bin */
387*7c478bd9Sstevel@tonic-gate 	as_pgm = malloc(strlen(as_dir) + strlen("/gas") + 1);
388*7c478bd9Sstevel@tonic-gate 	(void) sprintf(as_pgm, "%s/gas", as_dir);
389*7c478bd9Sstevel@tonic-gate 
390*7c478bd9Sstevel@tonic-gate 	if ((as64_dir = getenv("AW_AS64_DIR")) == NULL)
391*7c478bd9Sstevel@tonic-gate 		as64_dir = DEFAULT_AS64_DIR;	/* /usr/sfw/bin */
392*7c478bd9Sstevel@tonic-gate 	as64_pgm = malloc(strlen(as64_dir) + strlen("/gas") + 1);
393*7c478bd9Sstevel@tonic-gate 	(void) sprintf(as64_pgm, "%s/gas", as64_dir);
394*7c478bd9Sstevel@tonic-gate 
395*7c478bd9Sstevel@tonic-gate 	if ((m4_dir = getenv("AW_M4_DIR")) == NULL)
396*7c478bd9Sstevel@tonic-gate 		m4_dir = DEFAULT_M4_DIR;	/* /usr/ccs/bin */
397*7c478bd9Sstevel@tonic-gate 	m4_pgm = malloc(strlen(m4_dir) + strlen("/m4") + 1);
398*7c478bd9Sstevel@tonic-gate 	(void) sprintf(m4_pgm, "%s/m4", m4_dir);
399*7c478bd9Sstevel@tonic-gate 
400*7c478bd9Sstevel@tonic-gate 	if ((m4_lib_dir = getenv("AW_M4LIB_DIR")) == NULL)
401*7c478bd9Sstevel@tonic-gate 		m4_lib_dir = DEFAULT_M4LIB_DIR;	/* /usr/ccs/lib */
402*7c478bd9Sstevel@tonic-gate 	m4_cmdefs = malloc(strlen(m4_lib_dir) + strlen("/cmdefs") + 1);
403*7c478bd9Sstevel@tonic-gate 	(void) sprintf(m4_cmdefs, "%s/cmdefs", m4_lib_dir);
404*7c478bd9Sstevel@tonic-gate 
405*7c478bd9Sstevel@tonic-gate 	if ((cpp_dir = getenv("AW_CPP_DIR")) == NULL)
406*7c478bd9Sstevel@tonic-gate 		cpp_dir = DEFAULT_CPP_DIR;	/* /usr/ccs/lib */
407*7c478bd9Sstevel@tonic-gate 	cpp_pgm = malloc(strlen(cpp_dir) + strlen("/cpp") + 1);
408*7c478bd9Sstevel@tonic-gate 	(void) sprintf(cpp_pgm, "%s/cpp", cpp_dir);
409*7c478bd9Sstevel@tonic-gate 
410*7c478bd9Sstevel@tonic-gate 	newae(as, as_pgm);
411*7c478bd9Sstevel@tonic-gate 	newae(as, "--warn");
412*7c478bd9Sstevel@tonic-gate 	newae(as, "--fatal-warnings");
413*7c478bd9Sstevel@tonic-gate 	newae(as, "--traditional-format");
414*7c478bd9Sstevel@tonic-gate 
415*7c478bd9Sstevel@tonic-gate 	/*
416*7c478bd9Sstevel@tonic-gate 	 * This is a support hack to rewrite code for the compiler
417*7c478bd9Sstevel@tonic-gate 	 * which should probably cause an assembler programmer to recode
418*7c478bd9Sstevel@tonic-gate 	 * - so, generate a warning in this case.
419*7c478bd9Sstevel@tonic-gate 	 */
420*7c478bd9Sstevel@tonic-gate 	newae(as, "-K");
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate 	/*
423*7c478bd9Sstevel@tonic-gate 	 * Walk the argument list, translating as we go ..
424*7c478bd9Sstevel@tonic-gate 	 */
425*7c478bd9Sstevel@tonic-gate 	while (--argc > 0) {
426*7c478bd9Sstevel@tonic-gate 		char *arg;
427*7c478bd9Sstevel@tonic-gate 		int arglen;
428*7c478bd9Sstevel@tonic-gate 
429*7c478bd9Sstevel@tonic-gate 		arg = *++argv;
430*7c478bd9Sstevel@tonic-gate 		arglen = strlen(arg);
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate 		if (*arg != '-') {
433*7c478bd9Sstevel@tonic-gate 			char *filename;
434*7c478bd9Sstevel@tonic-gate 
435*7c478bd9Sstevel@tonic-gate 			/*
436*7c478bd9Sstevel@tonic-gate 			 * filenames ending in '.s' are taken to be
437*7c478bd9Sstevel@tonic-gate 			 * assembler files, and provide the default
438*7c478bd9Sstevel@tonic-gate 			 * basename of the output file.
439*7c478bd9Sstevel@tonic-gate 			 *
440*7c478bd9Sstevel@tonic-gate 			 * other files are passed through to the
441*7c478bd9Sstevel@tonic-gate 			 * preprocessor, if present, or to gas if not.
442*7c478bd9Sstevel@tonic-gate 			 */
443*7c478bd9Sstevel@tonic-gate 			filename = arg;
444*7c478bd9Sstevel@tonic-gate 			if (arglen > 2 &&
445*7c478bd9Sstevel@tonic-gate 			    strcmp(arg + arglen - 2, ".s") == 0) {
446*7c478bd9Sstevel@tonic-gate 				/*
447*7c478bd9Sstevel@tonic-gate 				 * Though 'as' allows multiple assembler
448*7c478bd9Sstevel@tonic-gate 				 * files to be processed in one invocation
449*7c478bd9Sstevel@tonic-gate 				 * of the assembler, ON only processes one
450*7c478bd9Sstevel@tonic-gate 				 * file at a time, which makes things a lot
451*7c478bd9Sstevel@tonic-gate 				 * simpler!
452*7c478bd9Sstevel@tonic-gate 				 */
453*7c478bd9Sstevel@tonic-gate 				if (srcfile == NULL)
454*7c478bd9Sstevel@tonic-gate 					srcfile = arg;
455*7c478bd9Sstevel@tonic-gate 				else
456*7c478bd9Sstevel@tonic-gate 					return (usage(
457*7c478bd9Sstevel@tonic-gate 					    "one assembler file at a time"));
458*7c478bd9Sstevel@tonic-gate 
459*7c478bd9Sstevel@tonic-gate 				/*
460*7c478bd9Sstevel@tonic-gate 				 * If we haven't seen a -o option yet,
461*7c478bd9Sstevel@tonic-gate 				 * default the output to the basename
462*7c478bd9Sstevel@tonic-gate 				 * of the input, substituting a .o on the end
463*7c478bd9Sstevel@tonic-gate 				 */
464*7c478bd9Sstevel@tonic-gate 				if (outfile == NULL) {
465*7c478bd9Sstevel@tonic-gate 					char *argcopy;
466*7c478bd9Sstevel@tonic-gate 
467*7c478bd9Sstevel@tonic-gate 					argcopy = strdup(arg);
468*7c478bd9Sstevel@tonic-gate 					argcopy[arglen - 1] = 'o';
469*7c478bd9Sstevel@tonic-gate 
470*7c478bd9Sstevel@tonic-gate 					if ((outfile = strrchr(
471*7c478bd9Sstevel@tonic-gate 					    argcopy, '/')) == NULL)
472*7c478bd9Sstevel@tonic-gate 						outfile = argcopy;
473*7c478bd9Sstevel@tonic-gate 					else
474*7c478bd9Sstevel@tonic-gate 						outfile++;
475*7c478bd9Sstevel@tonic-gate 				}
476*7c478bd9Sstevel@tonic-gate 			}
477*7c478bd9Sstevel@tonic-gate 			if (cpp)
478*7c478bd9Sstevel@tonic-gate 				newae(cpp, filename);
479*7c478bd9Sstevel@tonic-gate 			else if (m4)
480*7c478bd9Sstevel@tonic-gate 				newae(m4, filename);
481*7c478bd9Sstevel@tonic-gate 			else
482*7c478bd9Sstevel@tonic-gate 				newae(as, filename);
483*7c478bd9Sstevel@tonic-gate 			continue;
484*7c478bd9Sstevel@tonic-gate 		} else
485*7c478bd9Sstevel@tonic-gate 			arglen--;
486*7c478bd9Sstevel@tonic-gate 
487*7c478bd9Sstevel@tonic-gate 		switch (arg[1]) {
488*7c478bd9Sstevel@tonic-gate 		case 'K':
489*7c478bd9Sstevel@tonic-gate 			/*
490*7c478bd9Sstevel@tonic-gate 			 * -K pic
491*7c478bd9Sstevel@tonic-gate 			 * -K PIC
492*7c478bd9Sstevel@tonic-gate 			 */
493*7c478bd9Sstevel@tonic-gate 			if (arglen == 1) {
494*7c478bd9Sstevel@tonic-gate 				if ((arg = *++argv) == NULL || *arg == '\0')
495*7c478bd9Sstevel@tonic-gate 					return (usage("malformed -K"));
496*7c478bd9Sstevel@tonic-gate 				argc--;
497*7c478bd9Sstevel@tonic-gate 			} else {
498*7c478bd9Sstevel@tonic-gate 				arg += 2;
499*7c478bd9Sstevel@tonic-gate 			}
500*7c478bd9Sstevel@tonic-gate 			if (strcmp(arg, "PIC") != 0 && strcmp(arg, "pic") != 0)
501*7c478bd9Sstevel@tonic-gate 				return (usage("malformed -K"));
502*7c478bd9Sstevel@tonic-gate 			break;		/* just ignore -Kpic for gcc */
503*7c478bd9Sstevel@tonic-gate 		case 'Q':
504*7c478bd9Sstevel@tonic-gate 			if (strcmp(arg, "-Qn") == 0)
505*7c478bd9Sstevel@tonic-gate 				break;
506*7c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
507*7c478bd9Sstevel@tonic-gate 		case 'b':
508*7c478bd9Sstevel@tonic-gate 		case 's':
509*7c478bd9Sstevel@tonic-gate 		case 'T':
510*7c478bd9Sstevel@tonic-gate 			/*
511*7c478bd9Sstevel@tonic-gate 			 * -b	Extra symbol table for source browser ..
512*7c478bd9Sstevel@tonic-gate 			 *	not relevant to gas, thus should error.
513*7c478bd9Sstevel@tonic-gate 			 * -s	Put stabs in .stabs section not stabs.excl
514*7c478bd9Sstevel@tonic-gate 			 *	not clear if there's an equivalent
515*7c478bd9Sstevel@tonic-gate 			 * -T	4.x migration option
516*7c478bd9Sstevel@tonic-gate 			 */
517*7c478bd9Sstevel@tonic-gate 		default:
518*7c478bd9Sstevel@tonic-gate 			return (error(arg));
519*7c478bd9Sstevel@tonic-gate 		case 'x':
520*7c478bd9Sstevel@tonic-gate 			/*
521*7c478bd9Sstevel@tonic-gate 			 * Accept -xarch special case to invoke alternate
522*7c478bd9Sstevel@tonic-gate 			 * assemblers or assembler flags for different
523*7c478bd9Sstevel@tonic-gate 			 * architectures.
524*7c478bd9Sstevel@tonic-gate 			 */
525*7c478bd9Sstevel@tonic-gate 			if (strcmp(arg, "-xarch=amd64") == 0 ||
526*7c478bd9Sstevel@tonic-gate 			    strcmp(arg, "-xarch=generic64") == 0) {
527*7c478bd9Sstevel@tonic-gate 				as64++;
528*7c478bd9Sstevel@tonic-gate 				fixae_arg(as->ael_head, as64_pgm);
529*7c478bd9Sstevel@tonic-gate 				break;
530*7c478bd9Sstevel@tonic-gate 			}
531*7c478bd9Sstevel@tonic-gate 			/*
532*7c478bd9Sstevel@tonic-gate 			 * XX64: Is this useful to gas?
533*7c478bd9Sstevel@tonic-gate 			 */
534*7c478bd9Sstevel@tonic-gate 			if (strcmp(arg, "-xmodel=kernel") == 0)
535*7c478bd9Sstevel@tonic-gate 				break;
536*7c478bd9Sstevel@tonic-gate 
537*7c478bd9Sstevel@tonic-gate 			/*
538*7c478bd9Sstevel@tonic-gate 			 * -xF	Generates performance analysis data
539*7c478bd9Sstevel@tonic-gate 			 *	no equivalent
540*7c478bd9Sstevel@tonic-gate 			 */
541*7c478bd9Sstevel@tonic-gate 			return (error(arg));
542*7c478bd9Sstevel@tonic-gate 		case 'V':
543*7c478bd9Sstevel@tonic-gate 			newae(as, arg);
544*7c478bd9Sstevel@tonic-gate 			break;
545*7c478bd9Sstevel@tonic-gate 		case '#':
546*7c478bd9Sstevel@tonic-gate 			verbose++;
547*7c478bd9Sstevel@tonic-gate 			break;
548*7c478bd9Sstevel@tonic-gate 		case 'L':
549*7c478bd9Sstevel@tonic-gate 			newae(as, "--keep-locals");
550*7c478bd9Sstevel@tonic-gate 			break;
551*7c478bd9Sstevel@tonic-gate 		case 'n':
552*7c478bd9Sstevel@tonic-gate 			newae(as, "--no-warn");
553*7c478bd9Sstevel@tonic-gate 			break;
554*7c478bd9Sstevel@tonic-gate 		case 'o':
555*7c478bd9Sstevel@tonic-gate 			if (arglen != 1)
556*7c478bd9Sstevel@tonic-gate 				return (usage("bad -o flag"));
557*7c478bd9Sstevel@tonic-gate 			if ((arg = *++argv) == NULL || *arg == '\0')
558*7c478bd9Sstevel@tonic-gate 				return (usage("bad -o flag"));
559*7c478bd9Sstevel@tonic-gate 			outfile = arg;
560*7c478bd9Sstevel@tonic-gate 			argc--;
561*7c478bd9Sstevel@tonic-gate 			arglen = strlen(arg + 1);
562*7c478bd9Sstevel@tonic-gate 			break;
563*7c478bd9Sstevel@tonic-gate 		case 'm':
564*7c478bd9Sstevel@tonic-gate 			if (cpp)
565*7c478bd9Sstevel@tonic-gate 				return (usage("-m conflicts with -P"));
566*7c478bd9Sstevel@tonic-gate 			if (m4 == NULL) {
567*7c478bd9Sstevel@tonic-gate 				m4 = newael();
568*7c478bd9Sstevel@tonic-gate 				newae(m4, m4_pgm);
569*7c478bd9Sstevel@tonic-gate 				newae(m4, m4_cmdefs);
570*7c478bd9Sstevel@tonic-gate 			}
571*7c478bd9Sstevel@tonic-gate 			break;
572*7c478bd9Sstevel@tonic-gate 		case 'P':
573*7c478bd9Sstevel@tonic-gate 			if (m4)
574*7c478bd9Sstevel@tonic-gate 				return (usage("-P conflicts with -m"));
575*7c478bd9Sstevel@tonic-gate 			if (cpp == NULL) {
576*7c478bd9Sstevel@tonic-gate 				cpp = newael();
577*7c478bd9Sstevel@tonic-gate 				newae(cpp, cpp_pgm);
578*7c478bd9Sstevel@tonic-gate 				newae(cpp, "-D__GNUC_AS__");
579*7c478bd9Sstevel@tonic-gate 			}
580*7c478bd9Sstevel@tonic-gate 			break;
581*7c478bd9Sstevel@tonic-gate 		case 'D':
582*7c478bd9Sstevel@tonic-gate 		case 'U':
583*7c478bd9Sstevel@tonic-gate 			if (cpp)
584*7c478bd9Sstevel@tonic-gate 				newae(cpp, arg);
585*7c478bd9Sstevel@tonic-gate 			else if (m4)
586*7c478bd9Sstevel@tonic-gate 				newae(m4, arg);
587*7c478bd9Sstevel@tonic-gate 			else
588*7c478bd9Sstevel@tonic-gate 				newae(as, arg);
589*7c478bd9Sstevel@tonic-gate 			break;
590*7c478bd9Sstevel@tonic-gate 		case 'I':
591*7c478bd9Sstevel@tonic-gate 			if (cpp)
592*7c478bd9Sstevel@tonic-gate 				newae(cpp, arg);
593*7c478bd9Sstevel@tonic-gate 			else
594*7c478bd9Sstevel@tonic-gate 				newae(as, arg);
595*7c478bd9Sstevel@tonic-gate 			break;
596*7c478bd9Sstevel@tonic-gate 		case '-':	/* a gas-specific option */
597*7c478bd9Sstevel@tonic-gate 			newae(as, arg);
598*7c478bd9Sstevel@tonic-gate 			break;
599*7c478bd9Sstevel@tonic-gate 		}
600*7c478bd9Sstevel@tonic-gate 	}
601*7c478bd9Sstevel@tonic-gate 
602*7c478bd9Sstevel@tonic-gate #if defined(__i386)
603*7c478bd9Sstevel@tonic-gate 	if (as64)
604*7c478bd9Sstevel@tonic-gate 		newae(as, "--64");
605*7c478bd9Sstevel@tonic-gate 	else
606*7c478bd9Sstevel@tonic-gate 		newae(as, "--32");
607*7c478bd9Sstevel@tonic-gate #endif
608*7c478bd9Sstevel@tonic-gate 
609*7c478bd9Sstevel@tonic-gate 	if (srcfile == NULL)
610*7c478bd9Sstevel@tonic-gate 		return (usage("no source file(s) specified"));
611*7c478bd9Sstevel@tonic-gate 	if (outfile == NULL)
612*7c478bd9Sstevel@tonic-gate 		outfile = "a.out";
613*7c478bd9Sstevel@tonic-gate 	newae(as, "-o");
614*7c478bd9Sstevel@tonic-gate 	newae(as, outfile);
615*7c478bd9Sstevel@tonic-gate 
616*7c478bd9Sstevel@tonic-gate 	asargv = aeltoargv(as);
617*7c478bd9Sstevel@tonic-gate 	if (cpp) {
618*7c478bd9Sstevel@tonic-gate #if defined(__sparc)
619*7c478bd9Sstevel@tonic-gate 		newae(cpp, "-Dsparc");
620*7c478bd9Sstevel@tonic-gate 		newae(cpp, "-D__sparc");
621*7c478bd9Sstevel@tonic-gate 		if (as64)
622*7c478bd9Sstevel@tonic-gate 			newae(cpp, "-D__sparcv9");
623*7c478bd9Sstevel@tonic-gate 		else
624*7c478bd9Sstevel@tonic-gate 			newae(cpp, "-D__sparcv8");
625*7c478bd9Sstevel@tonic-gate #elif defined(__i386) || defined(__x86)
626*7c478bd9Sstevel@tonic-gate 		if (as64) {
627*7c478bd9Sstevel@tonic-gate 			newae(cpp, "-D__x86_64");
628*7c478bd9Sstevel@tonic-gate 			newae(cpp, "-D__amd64");
629*7c478bd9Sstevel@tonic-gate 		} else {
630*7c478bd9Sstevel@tonic-gate 			newae(cpp, "-Di386");
631*7c478bd9Sstevel@tonic-gate 			newae(cpp, "-D__i386");
632*7c478bd9Sstevel@tonic-gate 		}
633*7c478bd9Sstevel@tonic-gate #else
634*7c478bd9Sstevel@tonic-gate #error	"need isa-dependent defines"
635*7c478bd9Sstevel@tonic-gate #endif
636*7c478bd9Sstevel@tonic-gate 		code = pipeline(aeltoargv(cpp), asargv);
637*7c478bd9Sstevel@tonic-gate 	} else if (m4)
638*7c478bd9Sstevel@tonic-gate 		code = pipeline(aeltoargv(m4), asargv);
639*7c478bd9Sstevel@tonic-gate 	else {
640*7c478bd9Sstevel@tonic-gate 		/*
641*7c478bd9Sstevel@tonic-gate 		 * XXX	should arrange to fork/exec so that we
642*7c478bd9Sstevel@tonic-gate 		 *	can unlink the output file if errors are
643*7c478bd9Sstevel@tonic-gate 		 *	detected..
644*7c478bd9Sstevel@tonic-gate 		 */
645*7c478bd9Sstevel@tonic-gate 		(void) execvp(asargv[0], asargv);
646*7c478bd9Sstevel@tonic-gate 		perror("execvp");
647*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: couldn't run %s\n",
648*7c478bd9Sstevel@tonic-gate 		    progname, asargv[0]);
649*7c478bd9Sstevel@tonic-gate 		code = 7;
650*7c478bd9Sstevel@tonic-gate 	}
651*7c478bd9Sstevel@tonic-gate 	if (code != 0)
652*7c478bd9Sstevel@tonic-gate 		(void) unlink(outfile);
653*7c478bd9Sstevel@tonic-gate 	return (code);
654*7c478bd9Sstevel@tonic-gate }
655