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