17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 524b9abbaSab196087 * Common Development and Distribution License (the "License"). 624b9abbaSab196087 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 211b30f017Sgvasick 227c478bd9Sstevel@tonic-gate /* 23*7fbf8d03SScott Rotondo * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* 287c478bd9Sstevel@tonic-gate * Wrapper for the GNU assembler to make it accept the Sun assembler 297c478bd9Sstevel@tonic-gate * arguments where possible. 307c478bd9Sstevel@tonic-gate * 317c478bd9Sstevel@tonic-gate * There are several limitations; the Sun assembler takes multiple 327c478bd9Sstevel@tonic-gate * source files, we only take one. 337c478bd9Sstevel@tonic-gate * 347c478bd9Sstevel@tonic-gate * -b, -s, -xF, -T plain not supported. 357c478bd9Sstevel@tonic-gate * -S isn't supported either, because while GNU as does generate 367c478bd9Sstevel@tonic-gate * listings with -a, there's no obvious mapping between sub-options. 377c478bd9Sstevel@tonic-gate * -K pic, -K PIC not supported either, though it's not clear what 387c478bd9Sstevel@tonic-gate * these actually do .. 397c478bd9Sstevel@tonic-gate * -Qy (not supported) adds a string to the .comment section 407c478bd9Sstevel@tonic-gate * describing the assembler version, while 417c478bd9Sstevel@tonic-gate * -Qn (supported) suppresses the string (also the default). 427c478bd9Sstevel@tonic-gate * 437c478bd9Sstevel@tonic-gate * We also add '-#' support to see invocation lines.. 447c478bd9Sstevel@tonic-gate * We also add '-xarch=amd64' in case we need to feed the assembler 457c478bd9Sstevel@tonic-gate * something different (or in case we need to invoke a different binary 467c478bd9Sstevel@tonic-gate * altogether!) 477c478bd9Sstevel@tonic-gate */ 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate #include <sys/types.h> 507c478bd9Sstevel@tonic-gate #include <sys/wait.h> 517c478bd9Sstevel@tonic-gate #include <stdio.h> 527c478bd9Sstevel@tonic-gate #include <unistd.h> 537c478bd9Sstevel@tonic-gate #include <string.h> 547c478bd9Sstevel@tonic-gate #include <stdlib.h> 5524b9abbaSab196087 #include <sys/param.h> 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate static const char *progname; 587c478bd9Sstevel@tonic-gate static int verbose; 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate struct aelist { 617c478bd9Sstevel@tonic-gate int ael_argc; 627c478bd9Sstevel@tonic-gate struct ae { 637c478bd9Sstevel@tonic-gate struct ae *ae_next; 647c478bd9Sstevel@tonic-gate char *ae_arg; 657c478bd9Sstevel@tonic-gate } *ael_head, *ael_tail; 667c478bd9Sstevel@tonic-gate }; 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate static struct aelist * 697c478bd9Sstevel@tonic-gate newael(void) 707c478bd9Sstevel@tonic-gate { 717c478bd9Sstevel@tonic-gate return (calloc(sizeof (struct aelist), 1)); 727c478bd9Sstevel@tonic-gate } 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate static void 757c478bd9Sstevel@tonic-gate newae(struct aelist *ael, const char *arg) 767c478bd9Sstevel@tonic-gate { 777c478bd9Sstevel@tonic-gate struct ae *ae; 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate ae = calloc(sizeof (*ae), 1); 807c478bd9Sstevel@tonic-gate ae->ae_arg = strdup(arg); 817c478bd9Sstevel@tonic-gate if (ael->ael_tail == NULL) 827c478bd9Sstevel@tonic-gate ael->ael_head = ae; 837c478bd9Sstevel@tonic-gate else 847c478bd9Sstevel@tonic-gate ael->ael_tail->ae_next = ae; 857c478bd9Sstevel@tonic-gate ael->ael_tail = ae; 867c478bd9Sstevel@tonic-gate ael->ael_argc++; 877c478bd9Sstevel@tonic-gate } 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate static void 907c478bd9Sstevel@tonic-gate fixae_arg(struct ae *ae, const char *newarg) 917c478bd9Sstevel@tonic-gate { 927c478bd9Sstevel@tonic-gate free(ae->ae_arg); 937c478bd9Sstevel@tonic-gate ae->ae_arg = strdup(newarg); 947c478bd9Sstevel@tonic-gate } 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate static char ** 977c478bd9Sstevel@tonic-gate aeltoargv(struct aelist *ael) 987c478bd9Sstevel@tonic-gate { 997c478bd9Sstevel@tonic-gate struct ae *ae; 1007c478bd9Sstevel@tonic-gate char **argv; 1017c478bd9Sstevel@tonic-gate int argc; 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate argv = calloc(sizeof (*argv), ael->ael_argc + 1); 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate for (argc = 0, ae = ael->ael_head; ae; ae = ae->ae_next, argc++) { 1067c478bd9Sstevel@tonic-gate argv[argc] = ae->ae_arg; 1077c478bd9Sstevel@tonic-gate if (ae == ael->ael_tail) 1087c478bd9Sstevel@tonic-gate break; 1097c478bd9Sstevel@tonic-gate } 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate return (argv); 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate static int 1157c478bd9Sstevel@tonic-gate error(const char *arg) 1167c478bd9Sstevel@tonic-gate { 1177c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1187c478bd9Sstevel@tonic-gate "%s: as->gas mapping failed at or near arg '%s'\n", progname, arg); 1197c478bd9Sstevel@tonic-gate return (2); 1207c478bd9Sstevel@tonic-gate } 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate static int 1237c478bd9Sstevel@tonic-gate usage(const char *arg) 1247c478bd9Sstevel@tonic-gate { 1257c478bd9Sstevel@tonic-gate if (arg != NULL) 1267c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "error: %s\n", arg); 1277c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Usage: %s [-V] [-#]\n" 1287c478bd9Sstevel@tonic-gate "\t[-xarch=architecture]\n" 1297c478bd9Sstevel@tonic-gate "\t[-o objfile] [-L]\n" 1307c478bd9Sstevel@tonic-gate "\t[-P [[-Ipath] [-Dname] [-Dname=def] [-Uname]]...]\n" 1317c478bd9Sstevel@tonic-gate "\t[-m] [-n] file.s ...\n", progname); 1327c478bd9Sstevel@tonic-gate return (3); 1337c478bd9Sstevel@tonic-gate } 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate static void 1367c478bd9Sstevel@tonic-gate copyuntil(FILE *in, FILE *out, int termchar) 1377c478bd9Sstevel@tonic-gate { 1387c478bd9Sstevel@tonic-gate int c; 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate while ((c = fgetc(in)) != EOF) { 1417c478bd9Sstevel@tonic-gate if (out && fputc(c, out) == EOF) 1427c478bd9Sstevel@tonic-gate exit(1); 1437c478bd9Sstevel@tonic-gate if (c == termchar) 1447c478bd9Sstevel@tonic-gate break; 1457c478bd9Sstevel@tonic-gate } 1467c478bd9Sstevel@tonic-gate } 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate /* 14924b9abbaSab196087 * Variant of copyuntil(), used for copying the path used 15024b9abbaSab196087 * for .file directives. This version removes the workspace 15124b9abbaSab196087 * from the head of the path, or failing that, attempts to remove 15224b9abbaSab196087 * /usr/include. This is a workaround for the way gas handles 15324b9abbaSab196087 * these directives. The objects produced by gas contain STT_FILE 15424b9abbaSab196087 * symbols for every .file directive. These FILE symbols contain our 15524b9abbaSab196087 * workspace paths, leading to wsdiff incorrectly flagging them as 15624b9abbaSab196087 * having changed. By clipping off the workspace from these paths, 15724b9abbaSab196087 * we eliminate these false positives. 15824b9abbaSab196087 */ 15924b9abbaSab196087 static void 16024b9abbaSab196087 copyuntil_path(FILE *in, FILE *out, int termchar, 16124b9abbaSab196087 const char *wspace, size_t wspace_len) 16224b9abbaSab196087 { 16324b9abbaSab196087 #define PROTO_INC "/proto/root_i386/usr/include/" 16424b9abbaSab196087 #define SYS_INC "/usr/include/" 16524b9abbaSab196087 1663cf6f95fSab196087 static const size_t proto_inc_len = sizeof (PROTO_INC) - 1; 1673cf6f95fSab196087 static const size_t sys_inc_len = sizeof (SYS_INC) - 1; 16824b9abbaSab196087 16924b9abbaSab196087 /* 17024b9abbaSab196087 * Dynamically sized buffer for reading paths. Retained 17124b9abbaSab196087 * and reused between calls. 17224b9abbaSab196087 */ 17324b9abbaSab196087 static char *buf = NULL; 1743cf6f95fSab196087 static size_t bufsize = 0; 17524b9abbaSab196087 1763cf6f95fSab196087 size_t bufcnt = 0; 17724b9abbaSab196087 char *bufptr; 17824b9abbaSab196087 int c; 17924b9abbaSab196087 18024b9abbaSab196087 /* Read the path into the buffer */ 18124b9abbaSab196087 while ((c = fgetc(in)) != EOF) { 18224b9abbaSab196087 /* 18324b9abbaSab196087 * If we need a buffer, or need a larger buffer, 18424b9abbaSab196087 * fix that here. 18524b9abbaSab196087 */ 18624b9abbaSab196087 if (bufcnt >= bufsize) { 1873cf6f95fSab196087 bufsize = (bufsize == 0) ? MAXPATHLEN : (bufsize * 2); 18824b9abbaSab196087 buf = realloc(buf, bufsize + 1); /* + room for NULL */ 18924b9abbaSab196087 if (buf == NULL) { 19024b9abbaSab196087 perror("realloc"); 19124b9abbaSab196087 exit(1); 19224b9abbaSab196087 } 19324b9abbaSab196087 } 19424b9abbaSab196087 19524b9abbaSab196087 buf[bufcnt++] = c; 19624b9abbaSab196087 if (c == termchar) 19724b9abbaSab196087 break; 19824b9abbaSab196087 } 19924b9abbaSab196087 if (bufcnt == 0) 20024b9abbaSab196087 return; 20124b9abbaSab196087 20224b9abbaSab196087 /* 20324b9abbaSab196087 * We have a non-empty buffer, and thus the opportunity 20424b9abbaSab196087 * to do some surgery on it before passing it to the output. 20524b9abbaSab196087 */ 20624b9abbaSab196087 buf[bufcnt] = '\0'; 20724b9abbaSab196087 bufptr = buf; 20824b9abbaSab196087 20924b9abbaSab196087 /* 21024b9abbaSab196087 * If our workspace is at the start, remove it. 21124b9abbaSab196087 * If not, then look for the system /usr/include instead. 21224b9abbaSab196087 */ 21324b9abbaSab196087 if ((wspace_len > 0) && (wspace_len < bufcnt) && 21424b9abbaSab196087 (strncmp(bufptr, wspace, wspace_len) == 0)) { 21524b9abbaSab196087 bufptr += wspace_len; 21624b9abbaSab196087 bufcnt -= wspace_len; 21724b9abbaSab196087 21824b9abbaSab196087 /* 21924b9abbaSab196087 * Further opportunity: Also clip the prefix 22024b9abbaSab196087 * that leads to /usr/include in the proto. 22124b9abbaSab196087 */ 22224b9abbaSab196087 if ((proto_inc_len < bufcnt) && 22324b9abbaSab196087 (strncmp(bufptr, PROTO_INC, proto_inc_len) == 0)) { 22424b9abbaSab196087 bufptr += proto_inc_len; 22524b9abbaSab196087 bufcnt -= proto_inc_len; 22624b9abbaSab196087 } 22724b9abbaSab196087 } else if ((sys_inc_len < bufcnt) && 22824b9abbaSab196087 (strncmp(bufptr, SYS_INC, sys_inc_len) == 0)) { 22924b9abbaSab196087 bufptr += sys_inc_len; 23024b9abbaSab196087 bufcnt -= sys_inc_len; 23124b9abbaSab196087 } 23224b9abbaSab196087 23324b9abbaSab196087 /* Output whatever is left */ 23424b9abbaSab196087 if (out && (fwrite(bufptr, 1, bufcnt, out) != bufcnt)) { 23524b9abbaSab196087 perror("fwrite"); 23624b9abbaSab196087 exit(1); 23724b9abbaSab196087 } 23824b9abbaSab196087 23924b9abbaSab196087 #undef PROTO_INC 24024b9abbaSab196087 #undef SYS_INC 24124b9abbaSab196087 } 24224b9abbaSab196087 24324b9abbaSab196087 /* 2447c478bd9Sstevel@tonic-gate * The idea here is to take directives like this emitted 2457c478bd9Sstevel@tonic-gate * by cpp: 2467c478bd9Sstevel@tonic-gate * 2477c478bd9Sstevel@tonic-gate * # num 2487c478bd9Sstevel@tonic-gate * 2497c478bd9Sstevel@tonic-gate * and convert them to directives like this that are 2507c478bd9Sstevel@tonic-gate * understood by the GNU assembler: 2517c478bd9Sstevel@tonic-gate * 2527c478bd9Sstevel@tonic-gate * .line num 2537c478bd9Sstevel@tonic-gate * 2547c478bd9Sstevel@tonic-gate * and similarly: 2557c478bd9Sstevel@tonic-gate * 2567c478bd9Sstevel@tonic-gate * # num "string" optional stuff 2577c478bd9Sstevel@tonic-gate * 2587c478bd9Sstevel@tonic-gate * is converted to 2597c478bd9Sstevel@tonic-gate * 2607c478bd9Sstevel@tonic-gate * .line num 2617c478bd9Sstevel@tonic-gate * .file "string" 2627c478bd9Sstevel@tonic-gate * 2637c478bd9Sstevel@tonic-gate * While this could be done with a sequence of sed 2647c478bd9Sstevel@tonic-gate * commands, this is simpler and faster.. 2657c478bd9Sstevel@tonic-gate */ 2667c478bd9Sstevel@tonic-gate static pid_t 2677c478bd9Sstevel@tonic-gate filter(int pipein, int pipeout) 2687c478bd9Sstevel@tonic-gate { 2697c478bd9Sstevel@tonic-gate pid_t pid; 2707c478bd9Sstevel@tonic-gate FILE *in, *out; 27124b9abbaSab196087 char *wspace; 27224b9abbaSab196087 size_t wspace_len; 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate if (verbose) 2757c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "{#line filter} "); 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate switch (pid = fork()) { 2787c478bd9Sstevel@tonic-gate case 0: 2797c478bd9Sstevel@tonic-gate if (dup2(pipein, 0) == -1 || 2807c478bd9Sstevel@tonic-gate dup2(pipeout, 1) == -1) { 2817c478bd9Sstevel@tonic-gate perror("dup2"); 2827c478bd9Sstevel@tonic-gate exit(1); 2837c478bd9Sstevel@tonic-gate } 2847c478bd9Sstevel@tonic-gate closefrom(3); 2857c478bd9Sstevel@tonic-gate break; 2867c478bd9Sstevel@tonic-gate case -1: 2877c478bd9Sstevel@tonic-gate perror("fork"); 2887c478bd9Sstevel@tonic-gate default: 2897c478bd9Sstevel@tonic-gate return (pid); 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate in = fdopen(0, "r"); 2937c478bd9Sstevel@tonic-gate out = fdopen(1, "w"); 2947c478bd9Sstevel@tonic-gate 29524b9abbaSab196087 /* 29624b9abbaSab196087 * Key off the CODEMGR_WS environment variable to detect 29724b9abbaSab196087 * if we're in an activated workspace, and to get the 29824b9abbaSab196087 * path to the workspace. 29924b9abbaSab196087 */ 30024b9abbaSab196087 wspace = getenv("CODEMGR_WS"); 30124b9abbaSab196087 if (wspace != NULL) 30224b9abbaSab196087 wspace_len = strlen(wspace); 30324b9abbaSab196087 3047c478bd9Sstevel@tonic-gate while (!feof(in)) { 3057c478bd9Sstevel@tonic-gate int c, num; 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate switch (c = fgetc(in)) { 3087c478bd9Sstevel@tonic-gate case '#': 3097c478bd9Sstevel@tonic-gate switch (fscanf(in, " %d", &num)) { 3107c478bd9Sstevel@tonic-gate case 0: 3117c478bd9Sstevel@tonic-gate /* 3127c478bd9Sstevel@tonic-gate * discard comment lines completely 3137c478bd9Sstevel@tonic-gate * discard ident strings completely too. 3147c478bd9Sstevel@tonic-gate * (GNU as politely ignores them..) 3157c478bd9Sstevel@tonic-gate */ 3167c478bd9Sstevel@tonic-gate copyuntil(in, NULL, '\n'); 3177c478bd9Sstevel@tonic-gate break; 3187c478bd9Sstevel@tonic-gate default: 3197c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "fscanf botch?"); 3207c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 3217c478bd9Sstevel@tonic-gate case EOF: 3227c478bd9Sstevel@tonic-gate exit(1); 3237c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 3247c478bd9Sstevel@tonic-gate case 1: 3257c478bd9Sstevel@tonic-gate /* 3267c478bd9Sstevel@tonic-gate * This line has a number at the beginning; 3277c478bd9Sstevel@tonic-gate * if it has a string after the number, then 3287c478bd9Sstevel@tonic-gate * it's a filename. 32924b9abbaSab196087 * 33024b9abbaSab196087 * If this is an activated workspace, use 33124b9abbaSab196087 * copyuntil_path() to do path rewriting 33224b9abbaSab196087 * that will prevent workspace paths from 33324b9abbaSab196087 * being burned into the resulting object. 33424b9abbaSab196087 * If not in an activated workspace, then 33524b9abbaSab196087 * copy the existing path straight through 33624b9abbaSab196087 * without interpretation. 3377c478bd9Sstevel@tonic-gate */ 3387c478bd9Sstevel@tonic-gate if (fgetc(in) == ' ' && fgetc(in) == '"') { 3397c478bd9Sstevel@tonic-gate (void) fprintf(out, "\t.file \""); 34024b9abbaSab196087 if (wspace != NULL) 34124b9abbaSab196087 copyuntil_path(in, out, '"', 34224b9abbaSab196087 wspace, wspace_len); 34324b9abbaSab196087 else 3447c478bd9Sstevel@tonic-gate copyuntil(in, out, '"'); 3457c478bd9Sstevel@tonic-gate (void) fputc('\n', out); 3467c478bd9Sstevel@tonic-gate } 3477c478bd9Sstevel@tonic-gate (void) fprintf(out, "\t.line %d\n", num - 1); 3487c478bd9Sstevel@tonic-gate /* 3497c478bd9Sstevel@tonic-gate * discard the rest of the line 3507c478bd9Sstevel@tonic-gate */ 3517c478bd9Sstevel@tonic-gate copyuntil(in, NULL, '\n'); 3527c478bd9Sstevel@tonic-gate break; 3537c478bd9Sstevel@tonic-gate } 3547c478bd9Sstevel@tonic-gate break; 3557c478bd9Sstevel@tonic-gate case '\n': 3567c478bd9Sstevel@tonic-gate /* 3577c478bd9Sstevel@tonic-gate * preserve newlines 3587c478bd9Sstevel@tonic-gate */ 3597c478bd9Sstevel@tonic-gate (void) fputc(c, out); 3607c478bd9Sstevel@tonic-gate break; 3617c478bd9Sstevel@tonic-gate case EOF: 3627c478bd9Sstevel@tonic-gate /* 3637c478bd9Sstevel@tonic-gate * don't write EOF! 3647c478bd9Sstevel@tonic-gate */ 3657c478bd9Sstevel@tonic-gate break; 3667c478bd9Sstevel@tonic-gate default: 3677c478bd9Sstevel@tonic-gate /* 3687c478bd9Sstevel@tonic-gate * lines that don't begin with '#' are copied 3697c478bd9Sstevel@tonic-gate */ 3707c478bd9Sstevel@tonic-gate (void) fputc(c, out); 3717c478bd9Sstevel@tonic-gate copyuntil(in, out, '\n'); 3727c478bd9Sstevel@tonic-gate break; 3737c478bd9Sstevel@tonic-gate } 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate if (ferror(out)) 3767c478bd9Sstevel@tonic-gate exit(1); 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate exit(0); 3807c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate static pid_t 3847c478bd9Sstevel@tonic-gate invoke(char **argv, int pipein, int pipeout) 3857c478bd9Sstevel@tonic-gate { 3867c478bd9Sstevel@tonic-gate pid_t pid; 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate if (verbose) { 3897c478bd9Sstevel@tonic-gate char **dargv = argv; 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate while (*dargv) 3927c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s ", *dargv++); 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate switch (pid = fork()) { 3967c478bd9Sstevel@tonic-gate case 0: 3977c478bd9Sstevel@tonic-gate if (pipein >= 0 && dup2(pipein, 0) == -1) { 3987c478bd9Sstevel@tonic-gate perror("dup2"); 3997c478bd9Sstevel@tonic-gate exit(1); 4007c478bd9Sstevel@tonic-gate } 4017c478bd9Sstevel@tonic-gate if (pipeout >= 0 && dup2(pipeout, 1) == -1) { 4027c478bd9Sstevel@tonic-gate perror("dup2"); 4037c478bd9Sstevel@tonic-gate exit(1); 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate closefrom(3); 4067c478bd9Sstevel@tonic-gate (void) execvp(argv[0], argv); 4077c478bd9Sstevel@tonic-gate perror("execvp"); 4087c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: couldn't run %s\n", 4097c478bd9Sstevel@tonic-gate progname, argv[0]); 4107c478bd9Sstevel@tonic-gate break; 4117c478bd9Sstevel@tonic-gate case -1: 4127c478bd9Sstevel@tonic-gate perror("fork"); 4137c478bd9Sstevel@tonic-gate default: 4147c478bd9Sstevel@tonic-gate return (pid); 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate exit(2); 4177c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate static int 4217c478bd9Sstevel@tonic-gate pipeline(char **ppargv, char **asargv) 4227c478bd9Sstevel@tonic-gate { 4237c478bd9Sstevel@tonic-gate int pipedes[4]; 4247c478bd9Sstevel@tonic-gate int active = 0; 4257c478bd9Sstevel@tonic-gate int rval = 0; 4267c478bd9Sstevel@tonic-gate pid_t pid_pp, pid_f, pid_as; 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate if (pipe(pipedes) == -1 || pipe(pipedes + 2) == -1) { 4297c478bd9Sstevel@tonic-gate perror("pipe"); 4307c478bd9Sstevel@tonic-gate return (4); 4317c478bd9Sstevel@tonic-gate } 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate if ((pid_pp = invoke(ppargv, -1, pipedes[0])) > 0) 4347c478bd9Sstevel@tonic-gate active++; 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate if (verbose) 4377c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "| "); 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate if ((pid_f = filter(pipedes[1], pipedes[2])) > 0) 4407c478bd9Sstevel@tonic-gate active++; 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate if (verbose) 4437c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "| "); 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate if ((pid_as = invoke(asargv, pipedes[3], -1)) > 0) 4467c478bd9Sstevel@tonic-gate active++; 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate if (verbose) { 4497c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 4507c478bd9Sstevel@tonic-gate (void) fflush(stderr); 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate closefrom(3); 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate if (active != 3) 4567c478bd9Sstevel@tonic-gate return (5); 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate while (active != 0) { 4597c478bd9Sstevel@tonic-gate pid_t pid; 4607c478bd9Sstevel@tonic-gate int stat; 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate if ((pid = wait(&stat)) == -1) { 4637c478bd9Sstevel@tonic-gate rval++; 4647c478bd9Sstevel@tonic-gate break; 4657c478bd9Sstevel@tonic-gate } 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate if (!WIFEXITED(stat)) 4687c478bd9Sstevel@tonic-gate continue; 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate if (pid == pid_pp || pid == pid_f || pid == pid_as) { 4717c478bd9Sstevel@tonic-gate active--; 4727c478bd9Sstevel@tonic-gate if (WEXITSTATUS(stat) != 0) 4737c478bd9Sstevel@tonic-gate rval++; 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate return (rval); 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate int 4817c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 4827c478bd9Sstevel@tonic-gate { 4837c478bd9Sstevel@tonic-gate struct aelist *cpp = NULL; 4847c478bd9Sstevel@tonic-gate struct aelist *m4 = NULL; 4857c478bd9Sstevel@tonic-gate struct aelist *as = newael(); 4867c478bd9Sstevel@tonic-gate char **asargv; 4877c478bd9Sstevel@tonic-gate char *outfile = NULL; 4887c478bd9Sstevel@tonic-gate char *srcfile = NULL; 489*7fbf8d03SScott Rotondo const char *dir, *cmd; 490*7fbf8d03SScott Rotondo static char as_pgm[MAXPATHLEN]; 491*7fbf8d03SScott Rotondo static char as64_pgm[MAXPATHLEN]; 492*7fbf8d03SScott Rotondo static char m4_pgm[MAXPATHLEN]; 493*7fbf8d03SScott Rotondo static char m4_cmdefs[MAXPATHLEN]; 494*7fbf8d03SScott Rotondo static char cpp_pgm[MAXPATHLEN]; 4957c478bd9Sstevel@tonic-gate int as64 = 0; 4967c478bd9Sstevel@tonic-gate int code; 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate if ((progname = strrchr(argv[0], '/')) == NULL) 4997c478bd9Sstevel@tonic-gate progname = argv[0]; 5007c478bd9Sstevel@tonic-gate else 5017c478bd9Sstevel@tonic-gate progname++; 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate /* 5047c478bd9Sstevel@tonic-gate * Helpful when debugging, or when changing tool versions.. 5057c478bd9Sstevel@tonic-gate */ 506*7fbf8d03SScott Rotondo if ((cmd = getenv("AW_AS")) != NULL) 507*7fbf8d03SScott Rotondo strlcpy(as_pgm, cmd, sizeof (as_pgm)); 508*7fbf8d03SScott Rotondo else { 509*7fbf8d03SScott Rotondo if ((dir = getenv("AW_AS_DIR")) == NULL) 510*7fbf8d03SScott Rotondo dir = DEFAULT_AS_DIR; /* /usr/sfw/bin */ 511*7fbf8d03SScott Rotondo (void) snprintf(as_pgm, sizeof (as_pgm), "%s/gas", dir); 512*7fbf8d03SScott Rotondo } 5137c478bd9Sstevel@tonic-gate 514*7fbf8d03SScott Rotondo if ((cmd = getenv("AW_AS64")) != NULL) 515*7fbf8d03SScott Rotondo strlcpy(as64_pgm, cmd, sizeof (as64_pgm)); 516*7fbf8d03SScott Rotondo else { 517*7fbf8d03SScott Rotondo if ((dir = getenv("AW_AS64_DIR")) == NULL) 518*7fbf8d03SScott Rotondo dir = DEFAULT_AS64_DIR; /* /usr/sfw/bin */ 519*7fbf8d03SScott Rotondo (void) snprintf(as64_pgm, sizeof (as_pgm), "%s/gas", dir); 520*7fbf8d03SScott Rotondo } 5217c478bd9Sstevel@tonic-gate 522*7fbf8d03SScott Rotondo if ((cmd = getenv("AW_M4")) != NULL) 523*7fbf8d03SScott Rotondo strlcpy(m4_pgm, cmd, sizeof (m4_pgm)); 524*7fbf8d03SScott Rotondo else { 525*7fbf8d03SScott Rotondo if ((dir = getenv("AW_M4_DIR")) == NULL) 526*7fbf8d03SScott Rotondo dir = DEFAULT_M4_DIR; /* /usr/ccs/bin */ 527*7fbf8d03SScott Rotondo (void) snprintf(m4_pgm, sizeof (m4_pgm), "%s/m4", dir); 528*7fbf8d03SScott Rotondo } 5297c478bd9Sstevel@tonic-gate 530*7fbf8d03SScott Rotondo if ((cmd = getenv("AW_M4LIB")) != NULL) 531*7fbf8d03SScott Rotondo strlcpy(m4_cmdefs, cmd, sizeof (m4_cmdefs)); 532*7fbf8d03SScott Rotondo else { 533*7fbf8d03SScott Rotondo if ((dir = getenv("AW_M4LIB_DIR")) == NULL) 534*7fbf8d03SScott Rotondo dir = DEFAULT_M4LIB_DIR; /* /usr/ccs/lib */ 535*7fbf8d03SScott Rotondo (void) snprintf(m4_cmdefs, sizeof (m4_cmdefs), 536*7fbf8d03SScott Rotondo "%s/cm4defs", dir); 537*7fbf8d03SScott Rotondo } 5387c478bd9Sstevel@tonic-gate 539*7fbf8d03SScott Rotondo if ((cmd = getenv("AW_CPP")) != NULL) 540*7fbf8d03SScott Rotondo strlcpy(cpp_pgm, cmd, sizeof (cpp_pgm)); 541*7fbf8d03SScott Rotondo else { 542*7fbf8d03SScott Rotondo if ((dir = getenv("AW_CPP_DIR")) == NULL) 543*7fbf8d03SScott Rotondo dir = DEFAULT_CPP_DIR; /* /usr/ccs/lib */ 544*7fbf8d03SScott Rotondo (void) snprintf(cpp_pgm, sizeof (cpp_pgm), "%s/cpp", dir); 545*7fbf8d03SScott Rotondo } 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate newae(as, as_pgm); 5487c478bd9Sstevel@tonic-gate newae(as, "--warn"); 5497c478bd9Sstevel@tonic-gate newae(as, "--fatal-warnings"); 5507c478bd9Sstevel@tonic-gate newae(as, "--traditional-format"); 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate /* 5537c478bd9Sstevel@tonic-gate * This is a support hack to rewrite code for the compiler 5547c478bd9Sstevel@tonic-gate * which should probably cause an assembler programmer to recode 5557c478bd9Sstevel@tonic-gate * - so, generate a warning in this case. 5561b30f017Sgvasick * 5571b30f017Sgvasick * -K was dropped begining with version 2.18. 5587c478bd9Sstevel@tonic-gate */ 5591b30f017Sgvasick { 5601b30f017Sgvasick struct aelist *as_ver = newael(); 5611b30f017Sgvasick struct aelist *ggrep = newael(); 5621b30f017Sgvasick 5631b30f017Sgvasick newae(as_ver, as_pgm); 5641b30f017Sgvasick newae(as_ver, "--version"); 5651b30f017Sgvasick newae(ggrep, "/usr/bin/ggrep"); 5661b30f017Sgvasick newae(ggrep, "-q"); 5671b30f017Sgvasick newae(ggrep, "-E"); 5681b30f017Sgvasick newae(ggrep, "2.1[567]"); 5691b30f017Sgvasick code = pipeline(aeltoargv(as_ver), aeltoargv(ggrep)); 5701b30f017Sgvasick if (code == 0) { 5717c478bd9Sstevel@tonic-gate newae(as, "-K"); 5721b30f017Sgvasick } 5731b30f017Sgvasick } 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate /* 5767c478bd9Sstevel@tonic-gate * Walk the argument list, translating as we go .. 5777c478bd9Sstevel@tonic-gate */ 5787c478bd9Sstevel@tonic-gate while (--argc > 0) { 5797c478bd9Sstevel@tonic-gate char *arg; 5807c478bd9Sstevel@tonic-gate int arglen; 5817c478bd9Sstevel@tonic-gate 5827c478bd9Sstevel@tonic-gate arg = *++argv; 5837c478bd9Sstevel@tonic-gate arglen = strlen(arg); 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate if (*arg != '-') { 5867c478bd9Sstevel@tonic-gate char *filename; 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate /* 5897c478bd9Sstevel@tonic-gate * filenames ending in '.s' are taken to be 5907c478bd9Sstevel@tonic-gate * assembler files, and provide the default 5917c478bd9Sstevel@tonic-gate * basename of the output file. 5927c478bd9Sstevel@tonic-gate * 5937c478bd9Sstevel@tonic-gate * other files are passed through to the 5947c478bd9Sstevel@tonic-gate * preprocessor, if present, or to gas if not. 5957c478bd9Sstevel@tonic-gate */ 5967c478bd9Sstevel@tonic-gate filename = arg; 5977c478bd9Sstevel@tonic-gate if (arglen > 2 && 5987c478bd9Sstevel@tonic-gate strcmp(arg + arglen - 2, ".s") == 0) { 5997c478bd9Sstevel@tonic-gate /* 6007c478bd9Sstevel@tonic-gate * Though 'as' allows multiple assembler 6017c478bd9Sstevel@tonic-gate * files to be processed in one invocation 6027c478bd9Sstevel@tonic-gate * of the assembler, ON only processes one 6037c478bd9Sstevel@tonic-gate * file at a time, which makes things a lot 6047c478bd9Sstevel@tonic-gate * simpler! 6057c478bd9Sstevel@tonic-gate */ 6067c478bd9Sstevel@tonic-gate if (srcfile == NULL) 6077c478bd9Sstevel@tonic-gate srcfile = arg; 6087c478bd9Sstevel@tonic-gate else 6097c478bd9Sstevel@tonic-gate return (usage( 6107c478bd9Sstevel@tonic-gate "one assembler file at a time")); 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate /* 6137c478bd9Sstevel@tonic-gate * If we haven't seen a -o option yet, 6147c478bd9Sstevel@tonic-gate * default the output to the basename 6157c478bd9Sstevel@tonic-gate * of the input, substituting a .o on the end 6167c478bd9Sstevel@tonic-gate */ 6177c478bd9Sstevel@tonic-gate if (outfile == NULL) { 6187c478bd9Sstevel@tonic-gate char *argcopy; 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate argcopy = strdup(arg); 6217c478bd9Sstevel@tonic-gate argcopy[arglen - 1] = 'o'; 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate if ((outfile = strrchr( 6247c478bd9Sstevel@tonic-gate argcopy, '/')) == NULL) 6257c478bd9Sstevel@tonic-gate outfile = argcopy; 6267c478bd9Sstevel@tonic-gate else 6277c478bd9Sstevel@tonic-gate outfile++; 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate } 6307c478bd9Sstevel@tonic-gate if (cpp) 6317c478bd9Sstevel@tonic-gate newae(cpp, filename); 6327c478bd9Sstevel@tonic-gate else if (m4) 6337c478bd9Sstevel@tonic-gate newae(m4, filename); 6347c478bd9Sstevel@tonic-gate else 6357c478bd9Sstevel@tonic-gate newae(as, filename); 6367c478bd9Sstevel@tonic-gate continue; 6377c478bd9Sstevel@tonic-gate } else 6387c478bd9Sstevel@tonic-gate arglen--; 6397c478bd9Sstevel@tonic-gate 6407c478bd9Sstevel@tonic-gate switch (arg[1]) { 6417c478bd9Sstevel@tonic-gate case 'K': 6427c478bd9Sstevel@tonic-gate /* 6437c478bd9Sstevel@tonic-gate * -K pic 6447c478bd9Sstevel@tonic-gate * -K PIC 6457c478bd9Sstevel@tonic-gate */ 6467c478bd9Sstevel@tonic-gate if (arglen == 1) { 6477c478bd9Sstevel@tonic-gate if ((arg = *++argv) == NULL || *arg == '\0') 6487c478bd9Sstevel@tonic-gate return (usage("malformed -K")); 6497c478bd9Sstevel@tonic-gate argc--; 6507c478bd9Sstevel@tonic-gate } else { 6517c478bd9Sstevel@tonic-gate arg += 2; 6527c478bd9Sstevel@tonic-gate } 6537c478bd9Sstevel@tonic-gate if (strcmp(arg, "PIC") != 0 && strcmp(arg, "pic") != 0) 6547c478bd9Sstevel@tonic-gate return (usage("malformed -K")); 6557c478bd9Sstevel@tonic-gate break; /* just ignore -Kpic for gcc */ 6567c478bd9Sstevel@tonic-gate case 'Q': 6577c478bd9Sstevel@tonic-gate if (strcmp(arg, "-Qn") == 0) 6587c478bd9Sstevel@tonic-gate break; 6597c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 6607c478bd9Sstevel@tonic-gate case 'b': 6617c478bd9Sstevel@tonic-gate case 's': 6627c478bd9Sstevel@tonic-gate case 'T': 6637c478bd9Sstevel@tonic-gate /* 6647c478bd9Sstevel@tonic-gate * -b Extra symbol table for source browser .. 6657c478bd9Sstevel@tonic-gate * not relevant to gas, thus should error. 6667c478bd9Sstevel@tonic-gate * -s Put stabs in .stabs section not stabs.excl 6677c478bd9Sstevel@tonic-gate * not clear if there's an equivalent 6687c478bd9Sstevel@tonic-gate * -T 4.x migration option 6697c478bd9Sstevel@tonic-gate */ 6707c478bd9Sstevel@tonic-gate default: 6717c478bd9Sstevel@tonic-gate return (error(arg)); 6727c478bd9Sstevel@tonic-gate case 'x': 6737c478bd9Sstevel@tonic-gate /* 6747c478bd9Sstevel@tonic-gate * Accept -xarch special case to invoke alternate 6757c478bd9Sstevel@tonic-gate * assemblers or assembler flags for different 6767c478bd9Sstevel@tonic-gate * architectures. 6777c478bd9Sstevel@tonic-gate */ 6787c478bd9Sstevel@tonic-gate if (strcmp(arg, "-xarch=amd64") == 0 || 6797c478bd9Sstevel@tonic-gate strcmp(arg, "-xarch=generic64") == 0) { 6807c478bd9Sstevel@tonic-gate as64++; 6817c478bd9Sstevel@tonic-gate fixae_arg(as->ael_head, as64_pgm); 6827c478bd9Sstevel@tonic-gate break; 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate /* 6857c478bd9Sstevel@tonic-gate * XX64: Is this useful to gas? 6867c478bd9Sstevel@tonic-gate */ 6877c478bd9Sstevel@tonic-gate if (strcmp(arg, "-xmodel=kernel") == 0) 6887c478bd9Sstevel@tonic-gate break; 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate /* 6917c478bd9Sstevel@tonic-gate * -xF Generates performance analysis data 6927c478bd9Sstevel@tonic-gate * no equivalent 6937c478bd9Sstevel@tonic-gate */ 6947c478bd9Sstevel@tonic-gate return (error(arg)); 6957c478bd9Sstevel@tonic-gate case 'V': 6967c478bd9Sstevel@tonic-gate newae(as, arg); 6977c478bd9Sstevel@tonic-gate break; 6987c478bd9Sstevel@tonic-gate case '#': 6997c478bd9Sstevel@tonic-gate verbose++; 7007c478bd9Sstevel@tonic-gate break; 7017c478bd9Sstevel@tonic-gate case 'L': 7027c478bd9Sstevel@tonic-gate newae(as, "--keep-locals"); 7037c478bd9Sstevel@tonic-gate break; 7047c478bd9Sstevel@tonic-gate case 'n': 7057c478bd9Sstevel@tonic-gate newae(as, "--no-warn"); 7067c478bd9Sstevel@tonic-gate break; 7077c478bd9Sstevel@tonic-gate case 'o': 7087c478bd9Sstevel@tonic-gate if (arglen != 1) 7097c478bd9Sstevel@tonic-gate return (usage("bad -o flag")); 7107c478bd9Sstevel@tonic-gate if ((arg = *++argv) == NULL || *arg == '\0') 7117c478bd9Sstevel@tonic-gate return (usage("bad -o flag")); 7127c478bd9Sstevel@tonic-gate outfile = arg; 7137c478bd9Sstevel@tonic-gate argc--; 7147c478bd9Sstevel@tonic-gate arglen = strlen(arg + 1); 7157c478bd9Sstevel@tonic-gate break; 7167c478bd9Sstevel@tonic-gate case 'm': 7177c478bd9Sstevel@tonic-gate if (cpp) 7187c478bd9Sstevel@tonic-gate return (usage("-m conflicts with -P")); 7197c478bd9Sstevel@tonic-gate if (m4 == NULL) { 7207c478bd9Sstevel@tonic-gate m4 = newael(); 7217c478bd9Sstevel@tonic-gate newae(m4, m4_pgm); 7227c478bd9Sstevel@tonic-gate newae(m4, m4_cmdefs); 7237c478bd9Sstevel@tonic-gate } 7247c478bd9Sstevel@tonic-gate break; 7257c478bd9Sstevel@tonic-gate case 'P': 7267c478bd9Sstevel@tonic-gate if (m4) 7277c478bd9Sstevel@tonic-gate return (usage("-P conflicts with -m")); 7287c478bd9Sstevel@tonic-gate if (cpp == NULL) { 7297c478bd9Sstevel@tonic-gate cpp = newael(); 7307c478bd9Sstevel@tonic-gate newae(cpp, cpp_pgm); 7317c478bd9Sstevel@tonic-gate newae(cpp, "-D__GNUC_AS__"); 7327c478bd9Sstevel@tonic-gate } 7337c478bd9Sstevel@tonic-gate break; 7347c478bd9Sstevel@tonic-gate case 'D': 7357c478bd9Sstevel@tonic-gate case 'U': 7367c478bd9Sstevel@tonic-gate if (cpp) 7377c478bd9Sstevel@tonic-gate newae(cpp, arg); 7387c478bd9Sstevel@tonic-gate else if (m4) 7397c478bd9Sstevel@tonic-gate newae(m4, arg); 7407c478bd9Sstevel@tonic-gate else 7417c478bd9Sstevel@tonic-gate newae(as, arg); 7427c478bd9Sstevel@tonic-gate break; 7437c478bd9Sstevel@tonic-gate case 'I': 7447c478bd9Sstevel@tonic-gate if (cpp) 7457c478bd9Sstevel@tonic-gate newae(cpp, arg); 7467c478bd9Sstevel@tonic-gate else 7477c478bd9Sstevel@tonic-gate newae(as, arg); 7487c478bd9Sstevel@tonic-gate break; 7497c478bd9Sstevel@tonic-gate case '-': /* a gas-specific option */ 7507c478bd9Sstevel@tonic-gate newae(as, arg); 7517c478bd9Sstevel@tonic-gate break; 7527c478bd9Sstevel@tonic-gate } 7537c478bd9Sstevel@tonic-gate } 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate #if defined(__i386) 7567c478bd9Sstevel@tonic-gate if (as64) 7577c478bd9Sstevel@tonic-gate newae(as, "--64"); 7587c478bd9Sstevel@tonic-gate else 7597c478bd9Sstevel@tonic-gate newae(as, "--32"); 7607c478bd9Sstevel@tonic-gate #endif 7617c478bd9Sstevel@tonic-gate 7627c478bd9Sstevel@tonic-gate if (srcfile == NULL) 7637c478bd9Sstevel@tonic-gate return (usage("no source file(s) specified")); 7647c478bd9Sstevel@tonic-gate if (outfile == NULL) 7657c478bd9Sstevel@tonic-gate outfile = "a.out"; 7667c478bd9Sstevel@tonic-gate newae(as, "-o"); 7677c478bd9Sstevel@tonic-gate newae(as, outfile); 7687c478bd9Sstevel@tonic-gate 7697c478bd9Sstevel@tonic-gate asargv = aeltoargv(as); 7707c478bd9Sstevel@tonic-gate if (cpp) { 7717c478bd9Sstevel@tonic-gate #if defined(__sparc) 7727c478bd9Sstevel@tonic-gate newae(cpp, "-Dsparc"); 7737c478bd9Sstevel@tonic-gate newae(cpp, "-D__sparc"); 7747c478bd9Sstevel@tonic-gate if (as64) 7757c478bd9Sstevel@tonic-gate newae(cpp, "-D__sparcv9"); 7767c478bd9Sstevel@tonic-gate else 7777c478bd9Sstevel@tonic-gate newae(cpp, "-D__sparcv8"); 7787c478bd9Sstevel@tonic-gate #elif defined(__i386) || defined(__x86) 7797c478bd9Sstevel@tonic-gate if (as64) { 7807c478bd9Sstevel@tonic-gate newae(cpp, "-D__x86_64"); 7817c478bd9Sstevel@tonic-gate newae(cpp, "-D__amd64"); 7827c478bd9Sstevel@tonic-gate } else { 7837c478bd9Sstevel@tonic-gate newae(cpp, "-Di386"); 7847c478bd9Sstevel@tonic-gate newae(cpp, "-D__i386"); 7857c478bd9Sstevel@tonic-gate } 7867c478bd9Sstevel@tonic-gate #else 7877c478bd9Sstevel@tonic-gate #error "need isa-dependent defines" 7887c478bd9Sstevel@tonic-gate #endif 7897c478bd9Sstevel@tonic-gate code = pipeline(aeltoargv(cpp), asargv); 7907c478bd9Sstevel@tonic-gate } else if (m4) 7917c478bd9Sstevel@tonic-gate code = pipeline(aeltoargv(m4), asargv); 7927c478bd9Sstevel@tonic-gate else { 7937c478bd9Sstevel@tonic-gate /* 7947c478bd9Sstevel@tonic-gate * XXX should arrange to fork/exec so that we 7957c478bd9Sstevel@tonic-gate * can unlink the output file if errors are 7967c478bd9Sstevel@tonic-gate * detected.. 7977c478bd9Sstevel@tonic-gate */ 7987c478bd9Sstevel@tonic-gate (void) execvp(asargv[0], asargv); 7997c478bd9Sstevel@tonic-gate perror("execvp"); 8007c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: couldn't run %s\n", 8017c478bd9Sstevel@tonic-gate progname, asargv[0]); 8027c478bd9Sstevel@tonic-gate code = 7; 8037c478bd9Sstevel@tonic-gate } 8047c478bd9Sstevel@tonic-gate if (code != 0) 8057c478bd9Sstevel@tonic-gate (void) unlink(outfile); 8067c478bd9Sstevel@tonic-gate return (code); 8077c478bd9Sstevel@tonic-gate } 808