Print this page
10063 basic support for smatch
10153 checkpaths shouldn't check packaging exceptions
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/cw/cw.c
+++ new/usr/src/tools/cw/cw.c
1 1
2 2 /*
3 3 * CDDL HEADER START
4 4 *
5 5 * The contents of this file are subject to the terms of the
6 6 * Common Development and Distribution License (the "License").
7 7 * You may not use this file except in compliance with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22
23 23 /*
24 24 * Copyright 2018, Richard Lowe.
25 25 */
26 26 /*
27 27 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
28 28 * Use is subject to license terms.
29 + *
30 + * Copyright 2018 Joyent, Inc.
29 31 */
30 32
31 33 /*
32 34 * Wrapper for the GNU C compiler to make it accept the Sun C compiler
33 35 * arguments where possible.
34 36 *
35 37 * Since the translation is inexact, this is something of a work-in-progress.
36 38 *
37 39 */
38 40
39 41 /* If you modify this file, you must increment CW_VERSION */
40 42 #define CW_VERSION "3.0"
41 43
42 44 /*
43 45 * -# Verbose mode
44 46 * -### Show compiler commands built by driver, no compilation
45 47 * -A<name[(tokens)]> Preprocessor predicate assertion
46 48 * -B<[static|dynamic]> Specify dynamic or static binding
47 49 * -C Prevent preprocessor from removing comments
48 50 * -c Compile only - produce .o files, suppress linking
49 51 * -cg92 Alias for -xtarget=ss1000
50 52 * -D<name[=token]> Associate name with token as if by #define
51 53 * -d[y|n] dynamic [-dy] or static [-dn] option to linker
52 54 * -E Compile source through preprocessor only, output to stdout
53 55 * -erroff=<t> Suppress warnings specified by tags t(%none, %all, <tag list>)
54 56 * -errtags=<a> Display messages with tags a(no, yes)
55 57 * -errwarn=<t> Treats warnings specified by tags t(%none, %all, <tag list>)
56 58 * as errors
57 59 * -fast Optimize using a selection of options
58 60 * -fd Report old-style function definitions and declarations
59 61 * -fnonstd Initialize floating-point hardware to non-standard preferences
60 62 * -fns[=<yes|no>] Select non-standard floating point mode
61 63 * -fprecision=<p> Set FP rounding precision mode p(single, double, extended)
62 64 * -fround=<r> Select the IEEE rounding mode in effect at startup
63 65 * -fsimple[=<n>] Select floating-point optimization preferences <n>
64 66 * -fsingle Use single-precision arithmetic (-Xt and -Xs modes only)
65 67 * -ftrap=<t> Select floating-point trapping mode in effect at startup
66 68 * -fstore force floating pt. values to target precision on assignment
67 69 * -G Build a dynamic shared library
68 70 * -g Compile for debugging
69 71 * -H Print path name of each file included during compilation
70 72 * -h <name> Assign <name> to generated dynamic shared library
71 73 * -I<dir> Add <dir> to preprocessor #include file search path
72 74 * -i Passed to linker to ignore any LD_LIBRARY_PATH setting
73 75 * -keeptmp Keep temporary files created during compilation
74 76 * -L<dir> Pass to linker to add <dir> to the library search path
75 77 * -l<name> Link with library lib<name>.a or lib<name>.so
76 78 * -mc Remove duplicate strings from .comment section of output files
77 79 * -mr Remove all strings from .comment section of output files
78 80 * -mr,"string" Remove all strings and append "string" to .comment section
79 81 * -mt Specify options needed when compiling multi-threaded code
80 82 * -native Find available processor, generate code accordingly
81 83 * -nofstore Do not force floating pt. values to target precision
82 84 * on assignment
83 85 * -norunpath Do not build in a runtime path for shared libraries
84 86 * -O Use default optimization level (-xO2 or -xO3. Check man page.)
85 87 * -o <outputfile> Set name of output file to <outputfile>
86 88 * -P Compile source through preprocessor only, output to .i file
87 89 * -p Compile for profiling with prof
88 90 * -Q[y|n] Emit/don't emit identification info to output file
89 91 * -R<dir[:dir]> Build runtime search path list into executable
90 92 * -S Compile and only generate assembly code (.s)
91 93 * -s Strip symbol table from the executable file
92 94 * -t Turn off duplicate symbol warnings when linking
93 95 * -U<name> Delete initial definition of preprocessor symbol <name>
94 96 * -V Report version number of each compilation phase
95 97 * -v Do stricter semantic checking
96 98 * -W<c>,<arg> Pass <arg> to specified component <c> (a,l,m,p,0,2,h,i,u)
97 99 * -w Suppress compiler warning messages
98 100 * -Xa Compile assuming ANSI C conformance, allow K & R extensions
99 101 * (default mode)
100 102 * -Xs Compile assuming (pre-ANSI) K & R C style code
101 103 * -Xt Compile assuming K & R conformance, allow ANSI C
102 104 * -xarch=<a> Specify target architecture instruction set
103 105 * -xbuiltin[=<b>] When profitable inline, or substitute intrinisic functions
104 106 * for system functions, b={%all,%none}
105 107 * -xCC Accept C++ style comments
106 108 * -xchip=<c> Specify the target processor for use by the optimizer
107 109 * -xcode=<c> Generate different code for forming addresses
108 110 * -xcrossfile[=<n>] Enable optimization and inlining across source files,
109 111 * n={0|1}
110 112 * -xe Perform only syntax/semantic checking, no code generation
111 113 * -xF Compile for later mapfile reordering or unused section
112 114 * elimination
113 115 * -xhelp=<f> Display on-line help information f(flags, readme, errors)
114 116 * -xildoff Cancel -xildon
115 117 * -xildon Enable use of the incremental linker, ild
116 118 * -xinline=[<a>,...,<a>] Attempt inlining of specified user routines,
117 119 * <a>={%auto,func,no%func}
118 120 * -xlibmieee Force IEEE 754 return values for math routines in
119 121 * exceptional cases
120 122 * -xlibmil Inline selected libm math routines for optimization
121 123 * -xlic_lib=sunperf Link in the Sun supplied performance libraries
122 124 * -xlicinfo Show license server information
123 125 * -xmaxopt=[off,1,2,3,4,5] maximum optimization level allowed on #pragma opt
124 126 * -xO<n> Generate optimized code (n={1|2|3|4|5})
125 127 * -xP Print prototypes for function definitions
126 128 * -xprofile=<p> Collect data for a profile or use a profile to optimize
127 129 * <p>={{collect,use}[:<path>],tcov}
128 130 * -xregs=<r> Control register allocation
129 131 * -xs Allow debugging without object (.o) files
130 132 * -xsb Compile for use with the WorkShop source browser
131 133 * -xsbfast Generate only WorkShop source browser info, no compilation
132 134 * -xsfpconst Represent unsuffixed floating point constants as single
133 135 * precision
134 136 * -xspace Do not do optimizations that increase code size
135 137 * -xstrconst Place string literals into read-only data segment
136 138 * -xtarget=<t> Specify target system for optimization
137 139 * -xtemp=<dir> Set directory for temporary files to <dir>
138 140 * -xtime Report the execution time for each compilation phase
139 141 * -xunroll=n Enable unrolling loops n times where possible
140 142 * -Y<c>,<dir> Specify <dir> for location of component <c> (a,l,m,p,0,h,i,u)
141 143 * -YA,<dir> Change default directory searched for components
142 144 * -YI,<dir> Change default directory searched for include files
143 145 * -YP,<dir> Change default directory for finding libraries files
144 146 * -YS,<dir> Change default directory for startup object files
145 147 */
146 148
147 149 /*
148 150 * Translation table:
149 151 */
150 152 /*
151 153 * -# -v
152 154 * -### error
153 155 * -A<name[(tokens)]> pass-thru
154 156 * -B<[static|dynamic]> pass-thru (syntax error for anything else)
155 157 * -C pass-thru
156 158 * -c pass-thru
157 159 * -cg92 -m32 -mcpu=v8 -mtune=supersparc (SPARC only)
158 160 * -D<name[=token]> pass-thru
159 161 * -dy or -dn -Wl,-dy or -Wl,-dn
160 162 * -E pass-thru
161 163 * -erroff=E_EMPTY_TRANSLATION_UNIT ignore
162 164 * -errtags=%all -Wall
163 165 * -errwarn=%all -Werror else -Wno-error
164 166 * -fast error
165 167 * -fd error
166 168 * -fnonstd error
167 169 * -fns[=<yes|no>] error
168 170 * -fprecision=<p> error
169 171 * -fround=<r> error
170 172 * -fsimple[=<n>] error
171 173 * -fsingle[=<n>] error
172 174 * -ftrap=<t> error
173 175 * -fstore error
174 176 * -G pass-thru
175 177 * -g pass-thru
176 178 * -H pass-thru
177 179 * -h <name> pass-thru
178 180 * -I<dir> pass-thru
179 181 * -i pass-thru
180 182 * -keeptmp -save-temps
181 183 * -L<dir> pass-thru
182 184 * -l<name> pass-thru
183 185 * -mc error
184 186 * -mr error
185 187 * -mr,"string" error
186 188 * -mt -D_REENTRANT
187 189 * -native error
188 190 * -nofstore error
189 191 * -nolib -nodefaultlibs
190 192 * -norunpath ignore
191 193 * -O -O1 (Check the man page to be certain)
192 194 * -o <outputfile> pass-thru
193 195 * -P -E -o filename.i (or error)
194 196 * -p pass-thru
195 197 * -Q[y|n] error
196 198 * -R<dir[:dir]> pass-thru
197 199 * -S pass-thru
198 200 * -s -Wl,-s
199 201 * -t -Wl,-t
200 202 * -U<name> pass-thru
201 203 * -V --version
202 204 * -v -Wall
203 205 * -Wa,<arg> pass-thru
204 206 * -Wp,<arg> pass-thru except -xc99=<a>
205 207 * -Wl,<arg> pass-thru
206 208 * -W{m,0,2,h,i,u> error/ignore
207 209 * -xmodel=kernel -ffreestanding -mcmodel=kernel -mno-red-zone
208 210 * -Wu,-save_args -msave-args
209 211 * -w pass-thru
210 212 * -Xa -std=iso9899:199409 or -ansi
211 213 * -Xt error
212 214 * -Xs -traditional -std=c89
213 215 * -xarch=<a> table
214 216 * -xbuiltin[=<b>] -fbuiltin (-fno-builtin otherwise)
215 217 * -xCC ignore
216 218 * -xchip=<c> table
217 219 * -xcode=<c> table
218 220 * -xdebugformat=<format> ignore (always use dwarf-2 for gcc)
219 221 * -xcrossfile[=<n>] ignore
220 222 * -xe error
221 223 * -xF error
222 224 * -xhelp=<f> error
223 225 * -xildoff ignore
224 226 * -xildon ignore
225 227 * -xinline ignore
226 228 * -xlibmieee error
227 229 * -xlibmil error
228 230 * -xlic_lib=sunperf error
229 231 * -xmaxopt=[...] error
230 232 * -xO<n> -O<n>
231 233 * -xP error
232 234 * -xprofile=<p> error
233 235 * -xregs=<r> table
234 236 * -xs error
235 237 * -xsb error
236 238 * -xsbfast error
237 239 * -xsfpconst error
238 240 * -xspace ignore (-not -Os)
239 241 * -xstrconst ignore
240 242 * -xtarget=<t> table
241 243 * -xtemp=<dir> error
242 244 * -xtime error
243 245 * -xtransition -Wtransition
244 246 * -xunroll=n error
245 247 * -W0,-xdbggen=no%usedonly -fno-eliminate-unused-debug-symbols
246 248 * -fno-eliminate-unused-debug-types
247 249 * -Y<c>,<dir> error
248 250 * -YA,<dir> error
249 251 * -YI,<dir> -nostdinc -I<dir>
250 252 * -YP,<dir> error
251 253 * -YS,<dir> error
252 254 */
253 255
254 256 #include <ctype.h>
255 257 #include <err.h>
256 258 #include <errno.h>
257 259 #include <fcntl.h>
258 260 #include <getopt.h>
259 261 #include <stdio.h>
260 262 #include <stdlib.h>
261 263 #include <string.h>
262 264 #include <unistd.h>
263 265
264 266 #include <sys/param.h>
265 267 #include <sys/stat.h>
266 268 #include <sys/types.h>
267 269 #include <sys/utsname.h>
268 270 #include <sys/wait.h>
269 271
270 272 #define CW_F_CXX 0x01
271 273 #define CW_F_SHADOW 0x02
272 274 #define CW_F_EXEC 0x04
273 275 #define CW_F_ECHO 0x08
274 276 #define CW_F_XLATE 0x10
275 277 #define CW_F_PROG 0x20
276 278
277 279 typedef enum cw_op {
278 280 CW_O_NONE = 0,
279 281 CW_O_PREPROCESS,
280 282 CW_O_COMPILE,
281 283 CW_O_LINK
282 284 } cw_op_t;
283 285
↓ open down ↓ |
245 lines elided |
↑ open up ↑ |
284 286 struct aelist {
285 287 struct ae {
286 288 struct ae *ae_next;
287 289 char *ae_arg;
288 290 } *ael_head, *ael_tail;
289 291 int ael_argc;
290 292 };
291 293
292 294 typedef enum {
293 295 GNU,
294 - SUN
296 + SUN,
297 + SMATCH
295 298 } compiler_style_t;
296 299
297 300 typedef struct {
298 301 char *c_name;
299 302 char *c_path;
300 303 compiler_style_t c_style;
301 304 } cw_compiler_t;
302 305
303 306 typedef struct cw_ictx {
304 307 struct cw_ictx *i_next;
305 308 cw_compiler_t *i_compiler;
306 309 struct aelist *i_ae;
307 310 uint32_t i_flags;
308 311 int i_oldargc;
309 312 char **i_oldargv;
310 313 pid_t i_pid;
311 314 char i_discard[MAXPATHLEN];
312 315 char *i_stderr;
313 316 } cw_ictx_t;
314 317
315 318 /*
316 319 * Status values to indicate which Studio compiler and associated
317 320 * flags are being used.
318 321 */
319 322 #define M32 0x01 /* -m32 - only on Studio 12 */
320 323 #define M64 0x02 /* -m64 - only on Studio 12 */
321 324 #define SS11 0x100 /* Studio 11 */
322 325 #define SS12 0x200 /* Studio 12 */
323 326
324 327 #define TRANS_ENTRY 5
325 328 /*
326 329 * Translation table definition for the -xarch= flag. The "x_arg"
327 330 * value is translated into the appropriate gcc flags according
328 331 * to the values in x_trans[n]. The x_flags indicates what compiler
329 332 * is being used and what flags have been set via the use of
330 333 * "x_arg".
331 334 */
332 335 typedef struct xarch_table {
333 336 char *x_arg;
334 337 int x_flags;
335 338 char *x_trans[TRANS_ENTRY];
336 339 } xarch_table_t;
337 340
338 341 /*
339 342 * The translation table for the -xarch= flag used in the Studio compilers.
340 343 */
341 344 static const xarch_table_t xtbl[] = {
342 345 #if defined(__x86)
343 346 { "generic", SS11, {NULL} },
344 347 { "generic64", (SS11|M64), { "-m64", "-mtune=opteron" } },
345 348 { "amd64", (SS11|M64), { "-m64", "-mtune=opteron" } },
346 349 { "386", SS11, { "-march=i386" } },
347 350 { "pentium_pro", SS11, { "-march=pentiumpro" } },
348 351 { "sse", SS11, { "-msse", "-mfpmath=sse" } },
349 352 { "sse2", SS11, { "-msse2", "-mfpmath=sse" } },
350 353 #elif defined(__sparc)
351 354 { "generic", (SS11|M32), { "-m32", "-mcpu=v8" } },
352 355 { "generic64", (SS11|M64), { "-m64", "-mcpu=v9" } },
353 356 { "v8", (SS11|M32), { "-m32", "-mcpu=v8", "-mno-v8plus" } },
354 357 { "v8plus", (SS11|M32), { "-m32", "-mcpu=v9", "-mv8plus" } },
355 358 { "v8plusa", (SS11|M32), { "-m32", "-mcpu=ultrasparc", "-mv8plus",
356 359 "-mvis" } },
357 360 { "v8plusb", (SS11|M32), { "-m32", "-mcpu=ultrasparc3", "-mv8plus",
358 361 "-mvis" } },
359 362 { "v9", (SS11|M64), { "-m64", "-mcpu=v9" } },
360 363 { "v9a", (SS11|M64), { "-m64", "-mcpu=ultrasparc", "-mvis" } },
361 364 { "v9b", (SS11|M64), { "-m64", "-mcpu=ultrasparc3", "-mvis" } },
362 365 { "sparc", SS12, { "-mcpu=v9", "-mv8plus" } },
363 366 { "sparcvis", SS12, { "-mcpu=ultrasparc", "-mvis" } },
364 367 { "sparcvis2", SS12, { "-mcpu=ultrasparc3", "-mvis" } }
365 368 #endif
366 369 };
367 370
368 371 static int xtbl_size = sizeof (xtbl) / sizeof (xarch_table_t);
369 372
370 373 static const char *xchip_tbl[] = {
371 374 #if defined(__x86)
372 375 "386", "-mtune=i386", NULL,
373 376 "486", "-mtune=i486", NULL,
374 377 "pentium", "-mtune=pentium", NULL,
375 378 "pentium_pro", "-mtune=pentiumpro", NULL,
376 379 #elif defined(__sparc)
377 380 "super", "-mtune=supersparc", NULL,
378 381 "ultra", "-mtune=ultrasparc", NULL,
379 382 "ultra3", "-mtune=ultrasparc3", NULL,
380 383 #endif
381 384 NULL, NULL
382 385 };
383 386
384 387 static const char *xcode_tbl[] = {
385 388 #if defined(__sparc)
386 389 "abs32", "-fno-pic", "-mcmodel=medlow", NULL,
387 390 "abs44", "-fno-pic", "-mcmodel=medmid", NULL,
388 391 "abs64", "-fno-pic", "-mcmodel=medany", NULL,
389 392 "pic13", "-fpic", NULL,
390 393 "pic32", "-fPIC", NULL,
391 394 #endif
392 395 NULL, NULL
393 396 };
394 397
395 398 static const char *xtarget_tbl[] = {
396 399 #if defined(__x86)
397 400 "pentium_pro", "-march=pentiumpro", NULL,
398 401 #endif /* __x86 */
399 402 NULL, NULL
400 403 };
401 404
402 405 static const char *xregs_tbl[] = {
403 406 #if defined(__sparc)
404 407 "appl", "-mapp-regs", NULL,
405 408 "no%appl", "-mno-app-regs", NULL,
406 409 "float", "-mfpu", NULL,
407 410 "no%float", "-mno-fpu", NULL,
408 411 #endif /* __sparc */
409 412 NULL, NULL
410 413 };
411 414
412 415 static void
413 416 nomem(void)
414 417 {
415 418 errx(1, "out of memory");
416 419 }
417 420
418 421 static void
419 422 newae(struct aelist *ael, const char *arg)
420 423 {
421 424 struct ae *ae;
422 425
423 426 if ((ae = calloc(sizeof (*ae), 1)) == NULL)
424 427 nomem();
425 428 ae->ae_arg = strdup(arg);
426 429 if (ael->ael_tail == NULL)
427 430 ael->ael_head = ae;
428 431 else
429 432 ael->ael_tail->ae_next = ae;
430 433 ael->ael_tail = ae;
431 434 ael->ael_argc++;
432 435 }
433 436
434 437 static cw_ictx_t *
435 438 newictx(void)
436 439 {
437 440 cw_ictx_t *ctx = calloc(sizeof (cw_ictx_t), 1);
438 441 if (ctx)
439 442 if ((ctx->i_ae = calloc(sizeof (struct aelist), 1)) == NULL) {
440 443 free(ctx);
441 444 return (NULL);
442 445 }
443 446
444 447 return (ctx);
445 448 }
446 449
447 450 static void
448 451 error(const char *arg)
449 452 {
450 453 errx(2, "error: mapping failed at or near arg '%s'", arg);
451 454 }
452 455
453 456 /*
454 457 * Add the current favourite set of warnings to the gcc invocation.
455 458 */
456 459 static void
457 460 warnings(struct aelist *h)
458 461 {
459 462 static int warningsonce;
460 463
461 464 if (warningsonce++)
462 465 return;
463 466
464 467 /*
465 468 * Enable as many warnings as exist, then disable those that we never
466 469 * ever want.
467 470 */
468 471 newae(h, "-Wall");
469 472 newae(h, "-Wextra");
470 473 }
471 474
472 475 static void
473 476 optim_disable(struct aelist *h, int level)
474 477 {
475 478 if (level >= 2) {
476 479 newae(h, "-fno-strict-aliasing");
477 480 newae(h, "-fno-unit-at-a-time");
478 481 newae(h, "-fno-optimize-sibling-calls");
479 482 }
480 483 }
481 484
482 485 static void
483 486 Xsmode(struct aelist *h)
484 487 {
485 488 static int xsonce;
486 489
487 490 if (xsonce++)
488 491 return;
489 492
490 493 newae(h, "-traditional");
491 494 newae(h, "-traditional-cpp");
492 495 }
493 496
494 497 static void
495 498 usage()
496 499 {
497 500 extern char *__progname;
498 501 (void) fprintf(stderr,
499 502 "usage: %s [-C] [--versions] --primary <compiler> "
500 503 "[--shadow <compiler>]... -- cflags...\n",
501 504 __progname);
502 505 (void) fprintf(stderr, "compilers take the form: name,path,style\n"
503 506 " - name: a unique name usable in flag specifiers\n"
504 507 " - path: path to the compiler binary\n"
505 508 " - style: the style of flags expected: either sun or gnu\n");
506 509 exit(2);
507 510 }
508 511
509 512 static int
510 513 xlate_xtb(struct aelist *h, const char *xarg)
511 514 {
512 515 int i, j;
513 516
514 517 for (i = 0; i < xtbl_size; i++) {
515 518 if (strcmp(xtbl[i].x_arg, xarg) == 0)
516 519 break;
517 520 }
518 521
519 522 /*
520 523 * At the end of the table and so no matching "arg" entry
521 524 * found and so this must be a bad -xarch= flag.
522 525 */
523 526 if (i == xtbl_size)
524 527 error(xarg);
525 528
526 529 for (j = 0; j < TRANS_ENTRY; j++) {
527 530 if (xtbl[i].x_trans[j] != NULL)
528 531 newae(h, xtbl[i].x_trans[j]);
529 532 else
530 533 break;
531 534 }
532 535 return (xtbl[i].x_flags);
533 536
534 537 }
535 538
536 539 static void
537 540 xlate(struct aelist *h, const char *xarg, const char **table)
538 541 {
539 542 while (*table != NULL && strcmp(xarg, *table) != 0) {
540 543 while (*table != NULL)
541 544 table++;
542 545 table++;
543 546 }
544 547
545 548 if (*table == NULL)
546 549 error(xarg);
547 550
548 551 table++;
549 552
550 553 while (*table != NULL) {
551 554 newae(h, *table);
552 555 table++;
553 556 }
554 557 }
555 558
556 559 static void
557 560 do_gcc(cw_ictx_t *ctx)
558 561 {
559 562 int c;
560 563 int nolibc = 0;
561 564 int in_output = 0, seen_o = 0, c_files = 0;
562 565 cw_op_t op = CW_O_LINK;
563 566 char *model = NULL;
564 567 char *nameflag;
565 568 int mflag = 0;
566 569
567 570 if (ctx->i_flags & CW_F_PROG) {
568 571 newae(ctx->i_ae, "--version");
569 572 return;
570 573 }
571 574
572 575 newae(ctx->i_ae, "-fident");
573 576 newae(ctx->i_ae, "-finline");
574 577 newae(ctx->i_ae, "-fno-inline-functions");
575 578 newae(ctx->i_ae, "-fno-builtin");
576 579 newae(ctx->i_ae, "-fno-asm");
577 580 newae(ctx->i_ae, "-fdiagnostics-show-option");
578 581 newae(ctx->i_ae, "-nodefaultlibs");
579 582
580 583 #if defined(__sparc)
581 584 /*
582 585 * The SPARC ldd and std instructions require 8-byte alignment of
583 586 * their address operand. gcc correctly uses them only when the
584 587 * ABI requires 8-byte alignment; unfortunately we have a number of
585 588 * pieces of buggy code that doesn't conform to the ABI. This
586 589 * flag makes gcc work more like Studio with -xmemalign=4.
587 590 */
588 591 newae(ctx->i_ae, "-mno-integer-ldd-std");
589 592 #endif
590 593
591 594 /*
592 595 * This is needed because 'u' is defined
593 596 * under a conditional on 'sun'. Should
594 597 * probably just remove the conditional,
595 598 * or make it be dependent on '__sun'.
596 599 *
597 600 * -Dunix is also missing in enhanced ANSI mode
598 601 */
599 602 newae(ctx->i_ae, "-D__sun");
600 603
601 604 if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->c_name) == -1)
602 605 nomem();
603 606
604 607 /*
605 608 * Walk the argument list, translating as we go ..
606 609 */
607 610 while (--ctx->i_oldargc > 0) {
608 611 char *arg = *++ctx->i_oldargv;
609 612 size_t arglen = strlen(arg);
610 613
611 614 if (*arg == '-') {
612 615 arglen--;
613 616 } else {
614 617 /*
615 618 * Discard inline files that gcc doesn't grok
616 619 */
617 620 if (!in_output && arglen > 3 &&
618 621 strcmp(arg + arglen - 3, ".il") == 0)
619 622 continue;
620 623
621 624 if (!in_output && arglen > 2 &&
622 625 arg[arglen - 2] == '.' &&
623 626 (arg[arglen - 1] == 'S' || arg[arglen - 1] == 's' ||
624 627 arg[arglen - 1] == 'c' || arg[arglen - 1] == 'i'))
625 628 c_files++;
626 629
627 630 /*
628 631 * Otherwise, filenames and partial arguments
629 632 * are passed through for gcc to chew on. However,
630 633 * output is always discarded for the secondary
631 634 * compiler.
632 635 */
633 636 if ((ctx->i_flags & CW_F_SHADOW) && in_output)
634 637 newae(ctx->i_ae, ctx->i_discard);
635 638 else
636 639 newae(ctx->i_ae, arg);
637 640 in_output = 0;
638 641 continue;
639 642 }
640 643
641 644 if (ctx->i_flags & CW_F_CXX) {
642 645 if (strncmp(arg, "-_g++=", 6) == 0) {
643 646 newae(ctx->i_ae, strchr(arg, '=') + 1);
644 647 continue;
645 648 }
646 649 if (strncmp(arg, "-compat=", 8) == 0) {
647 650 /* discard -compat=4 and -compat=5 */
648 651 continue;
649 652 }
650 653 if (strcmp(arg, "-Qoption") == 0) {
651 654 /* discard -Qoption and its two arguments */
652 655 if (ctx->i_oldargc < 3)
653 656 error(arg);
654 657 ctx->i_oldargc -= 2;
655 658 ctx->i_oldargv += 2;
656 659 continue;
657 660 }
658 661 if (strcmp(arg, "-xwe") == 0) {
659 662 /* turn warnings into errors */
660 663 newae(ctx->i_ae, "-Werror");
661 664 continue;
662 665 }
663 666 if (strcmp(arg, "-norunpath") == 0) {
664 667 /* gcc has no corresponding option */
665 668 continue;
666 669 }
667 670 if (strcmp(arg, "-nolib") == 0) {
668 671 /* -nodefaultlibs is on by default */
669 672 nolibc = 1;
670 673 continue;
671 674 }
672 675 #if defined(__sparc)
673 676 if (strcmp(arg, "-cg92") == 0) {
674 677 mflag |= xlate_xtb(ctx->i_ae, "v8");
675 678 xlate(ctx->i_ae, "super", xchip_tbl);
676 679 continue;
677 680 }
678 681 #endif /* __sparc */
679 682 }
680 683
681 684 switch ((c = arg[1])) {
682 685 case '_':
683 686 if ((strncmp(arg, nameflag, strlen(nameflag)) == 0) ||
684 687 (strncmp(arg, "-_gcc=", 6) == 0) ||
685 688 (strncmp(arg, "-_gnu=", 6) == 0)) {
686 689 newae(ctx->i_ae, strchr(arg, '=') + 1);
687 690 }
688 691 break;
689 692 case '#':
690 693 if (arglen == 1) {
691 694 newae(ctx->i_ae, "-v");
692 695 break;
693 696 }
694 697 error(arg);
695 698 break;
696 699 case 'f':
697 700 if ((strcmp(arg, "-fpic") == 0) ||
698 701 (strcmp(arg, "-fPIC") == 0)) {
699 702 newae(ctx->i_ae, arg);
700 703 break;
701 704 }
702 705 error(arg);
703 706 break;
704 707 case 'g':
705 708 newae(ctx->i_ae, "-gdwarf-2");
706 709 break;
707 710 case 'E':
708 711 if (arglen == 1) {
709 712 newae(ctx->i_ae, "-xc");
710 713 newae(ctx->i_ae, arg);
711 714 op = CW_O_PREPROCESS;
712 715 nolibc = 1;
713 716 break;
714 717 }
715 718 error(arg);
716 719 break;
717 720 case 'c':
718 721 case 'S':
719 722 if (arglen == 1) {
720 723 op = CW_O_COMPILE;
721 724 nolibc = 1;
722 725 }
723 726 /* FALLTHROUGH */
724 727 case 'C':
725 728 case 'H':
726 729 case 'p':
727 730 if (arglen == 1) {
728 731 newae(ctx->i_ae, arg);
729 732 break;
730 733 }
731 734 error(arg);
732 735 break;
733 736 case 'A':
734 737 case 'h':
735 738 case 'I':
736 739 case 'i':
737 740 case 'L':
738 741 case 'l':
739 742 case 'R':
740 743 case 'U':
741 744 case 'u':
742 745 case 'w':
743 746 newae(ctx->i_ae, arg);
744 747 break;
745 748 case 'o':
746 749 seen_o = 1;
747 750 if (arglen == 1) {
748 751 in_output = 1;
749 752 newae(ctx->i_ae, arg);
750 753 } else if (ctx->i_flags & CW_F_SHADOW) {
751 754 newae(ctx->i_ae, "-o");
752 755 newae(ctx->i_ae, ctx->i_discard);
753 756 } else {
754 757 newae(ctx->i_ae, arg);
755 758 }
756 759 break;
757 760 case 'D':
758 761 newae(ctx->i_ae, arg);
759 762 /*
760 763 * XXX Clearly a hack ... do we need _KADB too?
761 764 */
762 765 if (strcmp(arg, "-D_KERNEL") == 0 ||
763 766 strcmp(arg, "-D_BOOT") == 0)
764 767 newae(ctx->i_ae, "-ffreestanding");
765 768 break;
766 769 case 'd':
767 770 if (arglen == 2) {
768 771 if (strcmp(arg, "-dy") == 0) {
769 772 newae(ctx->i_ae, "-Wl,-dy");
770 773 break;
771 774 }
772 775 if (strcmp(arg, "-dn") == 0) {
773 776 newae(ctx->i_ae, "-Wl,-dn");
774 777 break;
775 778 }
776 779 }
777 780 if (strcmp(arg, "-dalign") == 0) {
778 781 /*
779 782 * -dalign forces alignment in some cases;
780 783 * gcc does not need any flag to do this.
781 784 */
782 785 break;
783 786 }
784 787 error(arg);
785 788 break;
786 789 case 'e':
787 790 if (strcmp(arg,
788 791 "-erroff=E_EMPTY_TRANSLATION_UNIT") == 0) {
789 792 /*
790 793 * Accept but ignore this -- gcc doesn't
791 794 * seem to complain about empty translation
792 795 * units
793 796 */
794 797 break;
795 798 }
796 799 /* XX64 -- ignore all -erroff= options, for now */
797 800 if (strncmp(arg, "-erroff=", 8) == 0)
798 801 break;
799 802 if (strcmp(arg, "-errtags=yes") == 0) {
800 803 warnings(ctx->i_ae);
801 804 break;
802 805 }
803 806 if (strcmp(arg, "-errwarn=%all") == 0) {
804 807 newae(ctx->i_ae, "-Werror");
805 808 break;
806 809 }
807 810 error(arg);
808 811 break;
809 812 case 'G':
810 813 newae(ctx->i_ae, "-shared");
811 814 nolibc = 1;
812 815 break;
813 816 case 'k':
814 817 if (strcmp(arg, "-keeptmp") == 0) {
815 818 newae(ctx->i_ae, "-save-temps");
816 819 break;
817 820 }
818 821 error(arg);
819 822 break;
820 823 case 'm':
821 824 if (strcmp(arg, "-mt") == 0) {
822 825 newae(ctx->i_ae, "-D_REENTRANT");
823 826 break;
824 827 }
825 828 if (strcmp(arg, "-m64") == 0) {
826 829 newae(ctx->i_ae, "-m64");
827 830 #if defined(__x86)
828 831 newae(ctx->i_ae, "-mtune=opteron");
829 832 #endif
830 833 mflag |= M64;
831 834 break;
832 835 }
833 836 if (strcmp(arg, "-m32") == 0) {
834 837 newae(ctx->i_ae, "-m32");
835 838 mflag |= M32;
836 839 break;
837 840 }
838 841 error(arg);
839 842 break;
840 843 case 'B': /* linker options */
841 844 case 'M':
842 845 case 'z':
843 846 {
844 847 char *opt;
845 848 size_t len;
846 849 char *s;
847 850
848 851 if (arglen == 1) {
849 852 opt = *++ctx->i_oldargv;
850 853 if (opt == NULL || *opt == '\0')
851 854 error(arg);
852 855 ctx->i_oldargc--;
853 856 } else {
854 857 opt = arg + 2;
855 858 }
856 859 len = strlen(opt) + 7;
857 860 if ((s = malloc(len)) == NULL)
858 861 nomem();
859 862 (void) snprintf(s, len, "-Wl,-%c%s", c, opt);
860 863 newae(ctx->i_ae, s);
861 864 free(s);
862 865 }
863 866 break;
864 867 case 'O':
865 868 if (arglen == 1) {
866 869 newae(ctx->i_ae, "-O");
867 870 break;
868 871 }
869 872 error(arg);
870 873 break;
871 874 case 'P':
872 875 /*
873 876 * We could do '-E -o filename.i', but that's hard,
874 877 * and we don't need it for the case that's triggering
875 878 * this addition. We'll require the user to specify
876 879 * -o in the Makefile. If they don't they'll find out
877 880 * in a hurry.
878 881 */
879 882 newae(ctx->i_ae, "-E");
880 883 op = CW_O_PREPROCESS;
881 884 nolibc = 1;
882 885 break;
883 886 case 's':
884 887 if (arglen == 1) {
885 888 newae(ctx->i_ae, "-Wl,-s");
886 889 break;
887 890 }
888 891 error(arg);
889 892 break;
890 893 case 't':
891 894 if (arglen == 1) {
892 895 newae(ctx->i_ae, "-Wl,-t");
893 896 break;
894 897 }
895 898 error(arg);
896 899 break;
897 900 case 'V':
898 901 if (arglen == 1) {
899 902 ctx->i_flags &= ~CW_F_ECHO;
900 903 newae(ctx->i_ae, "--version");
901 904 break;
902 905 }
903 906 error(arg);
904 907 break;
905 908 case 'v':
906 909 if (arglen == 1) {
907 910 warnings(ctx->i_ae);
908 911 break;
909 912 }
910 913 error(arg);
911 914 break;
912 915 case 'W':
913 916 if (strncmp(arg, "-Wp,-xc99", 9) == 0) {
914 917 /*
915 918 * gcc's preprocessor will accept c99
916 919 * regardless, so accept and ignore.
917 920 */
918 921 break;
919 922 }
920 923 if (strncmp(arg, "-Wa,", 4) == 0 ||
921 924 strncmp(arg, "-Wp,", 4) == 0 ||
922 925 strncmp(arg, "-Wl,", 4) == 0) {
923 926 newae(ctx->i_ae, arg);
924 927 break;
925 928 }
926 929 if (strcmp(arg, "-W0,-noglobal") == 0 ||
927 930 strcmp(arg, "-W0,-xglobalstatic") == 0) {
928 931 /*
929 932 * gcc doesn't prefix local symbols
930 933 * in debug mode, so this is not needed.
931 934 */
932 935 break;
933 936 }
934 937 if (strcmp(arg, "-W0,-Lt") == 0) {
935 938 /*
936 939 * Generate tests at the top of loops.
937 940 * There is no direct gcc equivalent, ignore.
938 941 */
939 942 break;
940 943 }
941 944 if (strcmp(arg, "-W0,-xdbggen=no%usedonly") == 0) {
942 945 newae(ctx->i_ae,
943 946 "-fno-eliminate-unused-debug-symbols");
944 947 newae(ctx->i_ae,
945 948 "-fno-eliminate-unused-debug-types");
946 949 break;
947 950 }
948 951 if (strcmp(arg, "-W2,-xwrap_int") == 0) {
949 952 /*
950 953 * Use the legacy behaviour (pre-SS11)
951 954 * for integer wrapping.
952 955 * gcc does not need this.
953 956 */
954 957 break;
955 958 }
956 959 if (strcmp(arg, "-Wd,-xsafe=unboundsym") == 0) {
957 960 /*
958 961 * Prevents optimizing away checks for
959 962 * unbound weak symbol addresses. gcc does
960 963 * not do this, so it's not needed.
961 964 */
962 965 break;
963 966 }
964 967 if (strncmp(arg, "-Wc,-xcode=", 11) == 0) {
965 968 xlate(ctx->i_ae, arg + 11, xcode_tbl);
966 969 break;
967 970 }
968 971 if (strncmp(arg, "-Wc,-Qiselect", 13) == 0) {
969 972 /*
970 973 * Prevents insertion of register symbols.
971 974 * gcc doesn't do this, so ignore it.
972 975 */
973 976 break;
974 977 }
975 978 if (strcmp(arg, "-Wc,-Qassembler-ounrefsym=0") == 0) {
976 979 /*
977 980 * Prevents optimizing away of static variables.
978 981 * gcc does not do this, so it's not needed.
979 982 */
980 983 break;
981 984 }
982 985 #if defined(__x86)
983 986 if (strcmp(arg, "-Wu,-save_args") == 0) {
984 987 newae(ctx->i_ae, "-msave-args");
985 988 break;
986 989 }
987 990 #endif /* __x86 */
988 991 error(arg);
989 992 break;
990 993 case 'X':
991 994 if (strcmp(arg, "-Xa") == 0 ||
992 995 strcmp(arg, "-Xt") == 0) {
993 996 break;
994 997 }
995 998 if (strcmp(arg, "-Xs") == 0) {
996 999 Xsmode(ctx->i_ae);
997 1000 break;
998 1001 }
999 1002 error(arg);
1000 1003 break;
1001 1004 case 'x':
1002 1005 if (arglen == 1)
1003 1006 error(arg);
1004 1007 switch (arg[2]) {
1005 1008 case 'a':
1006 1009 if (strncmp(arg, "-xarch=", 7) == 0) {
1007 1010 mflag |= xlate_xtb(ctx->i_ae, arg + 7);
1008 1011 break;
1009 1012 }
1010 1013 error(arg);
1011 1014 break;
1012 1015 case 'b':
1013 1016 if (strncmp(arg, "-xbuiltin=", 10) == 0) {
1014 1017 if (strcmp(arg + 10, "%all"))
1015 1018 newae(ctx->i_ae, "-fbuiltin");
1016 1019 break;
1017 1020 }
1018 1021 error(arg);
1019 1022 break;
1020 1023 case 'C':
1021 1024 /* Accept C++ style comments -- ignore */
1022 1025 if (strcmp(arg, "-xCC") == 0)
1023 1026 break;
1024 1027 error(arg);
1025 1028 break;
1026 1029 case 'c':
1027 1030 if (strncmp(arg, "-xc99=%all", 10) == 0) {
1028 1031 newae(ctx->i_ae, "-std=gnu99");
1029 1032 break;
1030 1033 }
1031 1034 if (strncmp(arg, "-xc99=%none", 11) == 0) {
1032 1035 newae(ctx->i_ae, "-std=gnu89");
1033 1036 break;
1034 1037 }
1035 1038 if (strncmp(arg, "-xchip=", 7) == 0) {
1036 1039 xlate(ctx->i_ae, arg + 7, xchip_tbl);
1037 1040 break;
1038 1041 }
1039 1042 if (strncmp(arg, "-xcode=", 7) == 0) {
1040 1043 xlate(ctx->i_ae, arg + 7, xcode_tbl);
1041 1044 break;
1042 1045 }
1043 1046 if (strncmp(arg, "-xcrossfile", 11) == 0)
1044 1047 break;
1045 1048 error(arg);
1046 1049 break;
1047 1050 case 'd':
1048 1051 if (strncmp(arg, "-xdebugformat=", 14) == 0)
1049 1052 break;
1050 1053 error(arg);
1051 1054 break;
1052 1055 case 'F':
1053 1056 /*
1054 1057 * Compile for mapfile reordering, or unused
1055 1058 * section elimination, syntax can be -xF or
1056 1059 * more complex, like -xF=%all -- ignore.
1057 1060 */
1058 1061 if (strncmp(arg, "-xF", 3) == 0)
1059 1062 break;
1060 1063 error(arg);
1061 1064 break;
1062 1065 case 'i':
1063 1066 if (strncmp(arg, "-xinline", 8) == 0)
1064 1067 /* No inlining; ignore */
1065 1068 break;
1066 1069 if (strcmp(arg, "-xildon") == 0 ||
1067 1070 strcmp(arg, "-xildoff") == 0)
1068 1071 /* No incremental linking; ignore */
1069 1072 break;
1070 1073 error(arg);
1071 1074 break;
1072 1075 #if defined(__x86)
1073 1076 case 'm':
1074 1077 if (strcmp(arg, "-xmodel=kernel") == 0) {
1075 1078 newae(ctx->i_ae, "-ffreestanding");
1076 1079 newae(ctx->i_ae, "-mno-red-zone");
1077 1080 model = "-mcmodel=kernel";
1078 1081 nolibc = 1;
1079 1082 break;
1080 1083 }
1081 1084 error(arg);
1082 1085 break;
1083 1086 #endif /* __x86 */
1084 1087 case 'O':
1085 1088 if (strncmp(arg, "-xO", 3) == 0) {
1086 1089 size_t len = strlen(arg);
1087 1090 char *s = NULL;
1088 1091 int c = *(arg + 3);
1089 1092 int level;
1090 1093
1091 1094 if (len != 4 || !isdigit(c))
1092 1095 error(arg);
1093 1096
1094 1097 level = atoi(arg + 3);
1095 1098 if (level > 5)
1096 1099 error(arg);
1097 1100 if (level >= 2) {
1098 1101 /*
1099 1102 * For gcc-3.4.x at -O2 we
1100 1103 * need to disable optimizations
1101 1104 * that break ON.
1102 1105 */
1103 1106 optim_disable(ctx->i_ae, level);
1104 1107 /*
1105 1108 * limit -xO3 to -O2 as well.
1106 1109 */
1107 1110 level = 2;
1108 1111 }
1109 1112 if (asprintf(&s, "-O%d", level) == -1)
1110 1113 nomem();
1111 1114 newae(ctx->i_ae, s);
1112 1115 free(s);
1113 1116 break;
1114 1117 }
1115 1118 error(arg);
1116 1119 break;
1117 1120 case 'r':
1118 1121 if (strncmp(arg, "-xregs=", 7) == 0) {
1119 1122 xlate(ctx->i_ae, arg + 7, xregs_tbl);
1120 1123 break;
1121 1124 }
1122 1125 error(arg);
1123 1126 break;
1124 1127 case 's':
1125 1128 if (strcmp(arg, "-xs") == 0 ||
1126 1129 strcmp(arg, "-xspace") == 0 ||
1127 1130 strcmp(arg, "-xstrconst") == 0)
1128 1131 break;
1129 1132 error(arg);
1130 1133 break;
1131 1134 case 't':
1132 1135 if (strncmp(arg, "-xtarget=", 9) == 0) {
1133 1136 xlate(ctx->i_ae, arg + 9, xtarget_tbl);
1134 1137 break;
1135 1138 }
1136 1139 error(arg);
1137 1140 break;
1138 1141 case 'e':
1139 1142 case 'h':
1140 1143 case 'l':
1141 1144 default:
1142 1145 error(arg);
1143 1146 break;
1144 1147 }
1145 1148 break;
1146 1149 case 'Y':
1147 1150 if (arglen == 1) {
1148 1151 if ((arg = *++ctx->i_oldargv) == NULL ||
1149 1152 *arg == '\0')
1150 1153 error("-Y");
1151 1154 ctx->i_oldargc--;
1152 1155 arglen = strlen(arg + 1);
1153 1156 } else {
1154 1157 arg += 2;
1155 1158 }
1156 1159 /* Just ignore -YS,... for now */
1157 1160 if (strncmp(arg, "S,", 2) == 0)
1158 1161 break;
1159 1162 if (strncmp(arg, "l,", 2) == 0) {
1160 1163 char *s = strdup(arg);
1161 1164 s[0] = '-';
1162 1165 s[1] = 'B';
1163 1166 newae(ctx->i_ae, s);
1164 1167 free(s);
1165 1168 break;
1166 1169 }
1167 1170 if (strncmp(arg, "I,", 2) == 0) {
1168 1171 char *s = strdup(arg);
1169 1172 s[0] = '-';
1170 1173 s[1] = 'I';
1171 1174 newae(ctx->i_ae, "-nostdinc");
1172 1175 newae(ctx->i_ae, s);
1173 1176 free(s);
1174 1177 break;
1175 1178 }
1176 1179 error(arg);
1177 1180 break;
1178 1181 case 'Q':
1179 1182 /*
1180 1183 * We could map -Qy into -Wl,-Qy etc.
1181 1184 */
1182 1185 default:
1183 1186 error(arg);
1184 1187 break;
1185 1188 }
1186 1189 }
1187 1190
1188 1191 free(nameflag);
1189 1192
1190 1193 if (c_files > 1 && (ctx->i_flags & CW_F_SHADOW) &&
1191 1194 op != CW_O_PREPROCESS) {
1192 1195 errx(2, "multiple source files are "
1193 1196 "allowed only with -E or -P");
1194 1197 }
1195 1198
1196 1199 /*
1197 1200 * Make sure that we do not have any unintended interactions between
1198 1201 * the xarch options passed in and the version of the Studio compiler
1199 1202 * used.
1200 1203 */
1201 1204 if ((mflag & (SS11|SS12)) == (SS11|SS12)) {
1202 1205 errx(2,
1203 1206 "Conflicting \"-xarch=\" flags (both Studio 11 and 12)\n");
1204 1207 }
1205 1208
1206 1209 switch (mflag) {
1207 1210 case 0:
1208 1211 /* FALLTHROUGH */
1209 1212 case M32:
1210 1213 #if defined(__sparc)
1211 1214 /*
1212 1215 * Only -m32 is defined and so put in the missing xarch
1213 1216 * translation.
1214 1217 */
1215 1218 newae(ctx->i_ae, "-mcpu=v8");
1216 1219 newae(ctx->i_ae, "-mno-v8plus");
1217 1220 #endif
1218 1221 break;
1219 1222 case M64:
1220 1223 #if defined(__sparc)
1221 1224 /*
1222 1225 * Only -m64 is defined and so put in the missing xarch
1223 1226 * translation.
1224 1227 */
1225 1228 newae(ctx->i_ae, "-mcpu=v9");
1226 1229 #endif
1227 1230 break;
1228 1231 case SS12:
1229 1232 #if defined(__sparc)
1230 1233 /* no -m32/-m64 flag used - this is an error for sparc builds */
1231 1234 (void) fprintf(stderr, "No -m32/-m64 flag defined\n");
1232 1235 exit(2);
1233 1236 #endif
1234 1237 break;
1235 1238 case SS11:
1236 1239 /* FALLTHROUGH */
1237 1240 case (SS11|M32):
1238 1241 case (SS11|M64):
1239 1242 break;
1240 1243 case (SS12|M32):
1241 1244 #if defined(__sparc)
1242 1245 /*
1243 1246 * Need to add in further 32 bit options because with SS12
1244 1247 * the xarch=sparcvis option can be applied to 32 or 64
1245 1248 * bit, and so the translatation table (xtbl) cannot handle
1246 1249 * that.
1247 1250 */
1248 1251 newae(ctx->i_ae, "-mv8plus");
1249 1252 #endif
1250 1253 break;
1251 1254 case (SS12|M64):
1252 1255 break;
1253 1256 default:
1254 1257 (void) fprintf(stderr,
1255 1258 "Incompatible -xarch= and/or -m32/-m64 options used.\n");
1256 1259 exit(2);
1257 1260 }
1258 1261
1259 1262 if ((op == CW_O_LINK || op == CW_O_PREPROCESS) &&
1260 1263 (ctx->i_flags & CW_F_SHADOW))
1261 1264 exit(0);
1262 1265
1263 1266 if (model != NULL)
↓ open down ↓ |
959 lines elided |
↑ open up ↑ |
1264 1267 newae(ctx->i_ae, model);
1265 1268 if (!nolibc)
1266 1269 newae(ctx->i_ae, "-lc");
1267 1270 if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
1268 1271 newae(ctx->i_ae, "-o");
1269 1272 newae(ctx->i_ae, ctx->i_discard);
1270 1273 }
1271 1274 }
1272 1275
1273 1276 static void
1277 +do_smatch(cw_ictx_t *ctx)
1278 +{
1279 + if (ctx->i_flags & CW_F_PROG) {
1280 + newae(ctx->i_ae, "--version");
1281 + return;
1282 + }
1283 +
1284 + /*
1285 + * Some sources shouldn't run smatch at all.
1286 + */
1287 + for (int i = 0; i < ctx->i_oldargc; i++) {
1288 + char *arg = ctx->i_oldargv[i];
1289 +
1290 + if (strcmp(arg, "-_smatch=off") == 0) {
1291 + ctx->i_flags &= ~ (CW_F_EXEC | CW_F_ECHO);
1292 + return;
1293 + }
1294 + }
1295 +
1296 + /*
1297 + * smatch can handle gcc's options.
1298 + */
1299 + do_gcc(ctx);
1300 +}
1301 +
1302 +static void
1274 1303 do_cc(cw_ictx_t *ctx)
1275 1304 {
1276 1305 int in_output = 0, seen_o = 0;
1277 1306 cw_op_t op = CW_O_LINK;
1278 1307 char *nameflag;
1279 1308
1280 1309 if (ctx->i_flags & CW_F_PROG) {
1281 1310 newae(ctx->i_ae, "-V");
1282 1311 return;
1283 1312 }
1284 1313
1285 1314 if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->c_name) == -1)
1286 1315 nomem();
1287 1316
1288 1317 while (--ctx->i_oldargc > 0) {
1289 1318 char *arg = *++ctx->i_oldargv;
1290 1319
1291 1320 if (strncmp(arg, "-_CC=", 5) == 0) {
1292 1321 newae(ctx->i_ae, strchr(arg, '=') + 1);
1293 1322 continue;
1294 1323 }
1295 1324
1296 1325 if (*arg != '-') {
1297 1326 if (in_output == 0 || !(ctx->i_flags & CW_F_SHADOW)) {
1298 1327 newae(ctx->i_ae, arg);
1299 1328 } else {
1300 1329 in_output = 0;
1301 1330 newae(ctx->i_ae, ctx->i_discard);
1302 1331 }
1303 1332 continue;
1304 1333 }
1305 1334 switch (*(arg + 1)) {
1306 1335 case '_':
1307 1336 if ((strncmp(arg, nameflag, strlen(nameflag)) == 0) ||
1308 1337 (strncmp(arg, "-_cc=", 5) == 0) ||
1309 1338 (strncmp(arg, "-_sun=", 6) == 0)) {
1310 1339 newae(ctx->i_ae, strchr(arg, '=') + 1);
1311 1340 }
1312 1341 break;
1313 1342
1314 1343 case 'V':
1315 1344 ctx->i_flags &= ~CW_F_ECHO;
1316 1345 newae(ctx->i_ae, arg);
1317 1346 break;
1318 1347 case 'o':
1319 1348 seen_o = 1;
1320 1349 if (strlen(arg) == 2) {
1321 1350 in_output = 1;
1322 1351 newae(ctx->i_ae, arg);
1323 1352 } else if (ctx->i_flags & CW_F_SHADOW) {
1324 1353 newae(ctx->i_ae, "-o");
1325 1354 newae(ctx->i_ae, ctx->i_discard);
1326 1355 } else {
1327 1356 newae(ctx->i_ae, arg);
1328 1357 }
1329 1358 break;
1330 1359 case 'c':
1331 1360 case 'S':
1332 1361 if (strlen(arg) == 2)
1333 1362 op = CW_O_COMPILE;
1334 1363 newae(ctx->i_ae, arg);
1335 1364 break;
1336 1365 case 'E':
1337 1366 case 'P':
1338 1367 if (strlen(arg) == 2)
1339 1368 op = CW_O_PREPROCESS;
1340 1369 /*FALLTHROUGH*/
1341 1370 default:
1342 1371 newae(ctx->i_ae, arg);
1343 1372 }
1344 1373 }
1345 1374
1346 1375 free(nameflag);
1347 1376
1348 1377 if ((op == CW_O_LINK || op == CW_O_PREPROCESS) &&
1349 1378 (ctx->i_flags & CW_F_SHADOW))
1350 1379 exit(0);
1351 1380
1352 1381 if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
1353 1382 newae(ctx->i_ae, "-o");
1354 1383 newae(ctx->i_ae, ctx->i_discard);
1355 1384 }
1356 1385 }
1357 1386
1358 1387 static void
1359 1388 prepctx(cw_ictx_t *ctx)
1360 1389 {
1361 1390 newae(ctx->i_ae, ctx->i_compiler->c_path);
1362 1391
1363 1392 if (ctx->i_flags & CW_F_PROG) {
1364 1393 (void) printf("%s: %s\n", (ctx->i_flags & CW_F_SHADOW) ?
1365 1394 "shadow" : "primary", ctx->i_compiler->c_path);
1366 1395 (void) fflush(stdout);
1367 1396 }
1368 1397
↓ open down ↓ |
85 lines elided |
↑ open up ↑ |
1369 1398 if (!(ctx->i_flags & CW_F_XLATE))
1370 1399 return;
1371 1400
1372 1401 switch (ctx->i_compiler->c_style) {
1373 1402 case SUN:
1374 1403 do_cc(ctx);
1375 1404 break;
1376 1405 case GNU:
1377 1406 do_gcc(ctx);
1378 1407 break;
1408 + case SMATCH:
1409 + do_smatch(ctx);
1410 + break;
1379 1411 }
1380 1412 }
1381 1413
1382 1414 static int
1383 1415 invoke(cw_ictx_t *ctx)
1384 1416 {
1385 1417 char **newargv;
1386 1418 int ac;
1387 1419 struct ae *a;
1388 1420
1389 1421 if ((newargv = calloc(sizeof (*newargv), ctx->i_ae->ael_argc + 1)) ==
1390 1422 NULL)
1391 1423 nomem();
1392 1424
1393 1425 if (ctx->i_flags & CW_F_ECHO)
1394 1426 (void) fprintf(stderr, "+ ");
1395 1427
1396 1428 for (ac = 0, a = ctx->i_ae->ael_head; a; a = a->ae_next, ac++) {
1397 1429 newargv[ac] = a->ae_arg;
1398 1430 if (ctx->i_flags & CW_F_ECHO)
1399 1431 (void) fprintf(stderr, "%s ", a->ae_arg);
1400 1432 if (a == ctx->i_ae->ael_tail)
1401 1433 break;
1402 1434 }
1403 1435
1404 1436 if (ctx->i_flags & CW_F_ECHO) {
1405 1437 (void) fprintf(stderr, "\n");
1406 1438 (void) fflush(stderr);
1407 1439 }
1408 1440
1409 1441 if (!(ctx->i_flags & CW_F_EXEC))
1410 1442 return (0);
1411 1443
1412 1444 /*
1413 1445 * We must fix up the environment here so that the dependency files are
1414 1446 * not trampled by the shadow compiler. Also take care of GCC
1415 1447 * environment variables that will throw off gcc. This assumes a primary
1416 1448 * gcc.
1417 1449 */
1418 1450 if ((ctx->i_flags & CW_F_SHADOW) &&
1419 1451 (unsetenv("SUNPRO_DEPENDENCIES") != 0 ||
1420 1452 unsetenv("DEPENDENCIES_OUTPUT") != 0 ||
1421 1453 unsetenv("GCC_ROOT") != 0)) {
1422 1454 (void) fprintf(stderr, "error: environment setup failed: %s\n",
1423 1455 strerror(errno));
1424 1456 return (-1);
1425 1457 }
1426 1458
1427 1459 (void) execv(newargv[0], newargv);
1428 1460 warn("couldn't run %s", newargv[0]);
1429 1461
1430 1462 return (-1);
1431 1463 }
1432 1464
1433 1465 static int
1434 1466 reap(cw_ictx_t *ctx)
1435 1467 {
1436 1468 int status, ret = 0;
1437 1469 char buf[1024];
1438 1470 struct stat s;
1439 1471
1440 1472 /*
1441 1473 * Only wait for one specific child.
1442 1474 */
1443 1475 if (ctx->i_pid <= 0)
1444 1476 return (-1);
1445 1477
1446 1478 do {
1447 1479 if (waitpid(ctx->i_pid, &status, 0) < 0) {
1448 1480 warn("cannot reap child");
1449 1481 return (-1);
1450 1482 }
1451 1483 if (status != 0) {
1452 1484 if (WIFSIGNALED(status)) {
1453 1485 ret = -WTERMSIG(status);
1454 1486 break;
1455 1487 } else if (WIFEXITED(status)) {
1456 1488 ret = WEXITSTATUS(status);
1457 1489 break;
1458 1490 }
1459 1491 }
1460 1492 } while (!WIFEXITED(status) && !WIFSIGNALED(status));
1461 1493
1462 1494 (void) unlink(ctx->i_discard);
1463 1495
1464 1496 if (stat(ctx->i_stderr, &s) < 0) {
1465 1497 warn("stat failed on child cleanup");
1466 1498 return (-1);
1467 1499 }
1468 1500 if (s.st_size != 0) {
1469 1501 FILE *f;
1470 1502
1471 1503 if ((f = fopen(ctx->i_stderr, "r")) != NULL) {
1472 1504 while (fgets(buf, sizeof (buf), f))
1473 1505 (void) fprintf(stderr, "%s", buf);
1474 1506 (void) fflush(stderr);
1475 1507 (void) fclose(f);
1476 1508 }
1477 1509 }
1478 1510 (void) unlink(ctx->i_stderr);
1479 1511 free(ctx->i_stderr);
1480 1512
1481 1513 /*
1482 1514 * cc returns an error code when given -V; we want that to succeed.
1483 1515 */
1484 1516 if (ctx->i_flags & CW_F_PROG)
1485 1517 return (0);
1486 1518
1487 1519 return (ret);
1488 1520 }
1489 1521
1490 1522 static int
1491 1523 exec_ctx(cw_ictx_t *ctx, int block)
1492 1524 {
1493 1525 char *file;
1494 1526
1495 1527 /*
1496 1528 * To avoid offending cc's sensibilities, the name of its output
1497 1529 * file must end in '.o'.
1498 1530 */
1499 1531 if ((file = tempnam(NULL, ".cw")) == NULL) {
1500 1532 nomem();
1501 1533 return (-1);
1502 1534 }
1503 1535 (void) strlcpy(ctx->i_discard, file, MAXPATHLEN);
1504 1536 (void) strlcat(ctx->i_discard, ".o", MAXPATHLEN);
1505 1537 free(file);
1506 1538
1507 1539 if ((ctx->i_stderr = tempnam(NULL, ".cw")) == NULL) {
1508 1540 nomem();
1509 1541 return (-1);
1510 1542 }
1511 1543
1512 1544 if ((ctx->i_pid = fork()) == 0) {
1513 1545 int fd;
1514 1546
1515 1547 (void) fclose(stderr);
1516 1548 if ((fd = open(ctx->i_stderr, O_WRONLY | O_CREAT | O_EXCL,
1517 1549 0666)) < 0) {
1518 1550 err(1, "open failed for standard error");
1519 1551 }
1520 1552 if (dup2(fd, 2) < 0) {
1521 1553 err(1, "dup2 failed for standard error");
1522 1554 }
1523 1555 if (fd != 2)
1524 1556 (void) close(fd);
1525 1557 if (freopen("/dev/fd/2", "w", stderr) == NULL) {
1526 1558 err(1, "freopen failed for /dev/fd/2");
1527 1559 }
1528 1560
1529 1561 prepctx(ctx);
1530 1562 exit(invoke(ctx));
1531 1563 }
1532 1564
1533 1565 if (ctx->i_pid < 0) {
1534 1566 err(1, "fork failed");
1535 1567 }
1536 1568
1537 1569 if (block)
1538 1570 return (reap(ctx));
1539 1571
1540 1572 return (0);
1541 1573 }
1542 1574
1543 1575 static void
1544 1576 parse_compiler(const char *spec, cw_compiler_t *compiler)
1545 1577 {
1546 1578 char *tspec, *token;
1547 1579
1548 1580 if ((tspec = strdup(spec)) == NULL)
1549 1581 nomem();
1550 1582
1551 1583 if ((token = strsep(&tspec, ",")) == NULL)
1552 1584 errx(1, "Compiler is missing a name: %s", spec);
↓ open down ↓ |
164 lines elided |
↑ open up ↑ |
1553 1585 compiler->c_name = token;
1554 1586
1555 1587 if ((token = strsep(&tspec, ",")) == NULL)
1556 1588 errx(1, "Compiler is missing a path: %s", spec);
1557 1589 compiler->c_path = token;
1558 1590
1559 1591 if ((token = strsep(&tspec, ",")) == NULL)
1560 1592 errx(1, "Compiler is missing a style: %s", spec);
1561 1593
1562 1594 if ((strcasecmp(token, "gnu") == 0) ||
1563 - (strcasecmp(token, "gcc") == 0))
1595 + (strcasecmp(token, "gcc") == 0)) {
1564 1596 compiler->c_style = GNU;
1565 - else if ((strcasecmp(token, "sun") == 0) ||
1566 - (strcasecmp(token, "cc") == 0))
1597 + } else if ((strcasecmp(token, "sun") == 0) ||
1598 + (strcasecmp(token, "cc") == 0)) {
1567 1599 compiler->c_style = SUN;
1568 - else
1600 + } else if ((strcasecmp(token, "smatch") == 0)) {
1601 + compiler->c_style = SMATCH;
1602 + } else {
1569 1603 errx(1, "unknown compiler style: %s", token);
1604 + }
1570 1605
1571 1606 if (tspec != NULL)
1572 1607 errx(1, "Excess tokens in compiler: %s", spec);
1573 1608 }
1574 1609
1575 1610 int
1576 1611 main(int argc, char **argv)
1577 1612 {
1578 1613 int ch;
1579 1614 cw_compiler_t primary = { NULL, NULL, 0 };
1580 1615 cw_compiler_t shadows[10];
1581 1616 int nshadows = 0;
1582 1617 int ret = 0;
1583 1618 boolean_t do_serial = B_FALSE;
1584 1619 boolean_t do_exec = B_FALSE;
1585 1620 boolean_t vflg = B_FALSE;
1586 1621 boolean_t Cflg = B_FALSE;
1587 1622 boolean_t cflg = B_FALSE;
1588 1623 boolean_t nflg = B_FALSE;
1589 1624
1590 1625 cw_ictx_t *main_ctx;
1591 1626
1592 1627 static struct option longopts[] = {
1593 1628 { "compiler", no_argument, NULL, 'c' },
1594 1629 { "noecho", no_argument, NULL, 'n' },
1595 1630 { "primary", required_argument, NULL, 'p' },
1596 1631 { "shadow", required_argument, NULL, 's' },
1597 1632 { "versions", no_argument, NULL, 'v' },
1598 1633 { NULL, 0, NULL, 0 },
1599 1634 };
1600 1635
1601 1636
1602 1637 if ((main_ctx = newictx()) == NULL)
1603 1638 nomem();
1604 1639
1605 1640 while ((ch = getopt_long(argc, argv, "C", longopts, NULL)) != -1) {
1606 1641 switch (ch) {
1607 1642 case 'c':
1608 1643 cflg = B_TRUE;
1609 1644 break;
1610 1645 case 'C':
1611 1646 Cflg = B_TRUE;
1612 1647 break;
1613 1648 case 'n':
1614 1649 nflg = B_TRUE;
1615 1650 break;
1616 1651 case 'p':
1617 1652 if (primary.c_path != NULL) {
1618 1653 warnx("Only one primary compiler may "
1619 1654 "be specified");
1620 1655 usage();
1621 1656 }
1622 1657
1623 1658 parse_compiler(optarg, &primary);
1624 1659 break;
1625 1660 case 's':
1626 1661 if (nshadows >= 10)
1627 1662 errx(1, "May only use 10 shadows at "
1628 1663 "the moment");
1629 1664 parse_compiler(optarg, &shadows[nshadows]);
1630 1665 nshadows++;
1631 1666 break;
1632 1667 case 'v':
1633 1668 vflg = B_TRUE;
1634 1669 break;
1635 1670 default:
1636 1671 (void) fprintf(stderr, "Did you forget '--'?\n");
1637 1672 usage();
1638 1673 }
1639 1674 }
1640 1675
1641 1676 if (primary.c_path == NULL) {
1642 1677 warnx("A primary compiler must be specified");
1643 1678 usage();
1644 1679 }
1645 1680
1646 1681 do_serial = (getenv("CW_SHADOW_SERIAL") == NULL) ? B_FALSE : B_TRUE;
1647 1682 do_exec = (getenv("CW_NO_EXEC") == NULL) ? B_TRUE : B_FALSE;
1648 1683
1649 1684 /* Leave room for argv[0] */
1650 1685 argc -= (optind - 1);
1651 1686 argv += (optind - 1);
1652 1687
1653 1688 main_ctx->i_oldargc = argc;
1654 1689 main_ctx->i_oldargv = argv;
1655 1690 main_ctx->i_flags = CW_F_XLATE;
1656 1691 if (nflg == 0)
1657 1692 main_ctx->i_flags |= CW_F_ECHO;
1658 1693 if (do_exec)
1659 1694 main_ctx->i_flags |= CW_F_EXEC;
1660 1695 if (Cflg)
1661 1696 main_ctx->i_flags |= CW_F_CXX;
1662 1697 main_ctx->i_compiler = &primary;
1663 1698
1664 1699 if (cflg) {
1665 1700 (void) fputs(primary.c_path, stdout);
1666 1701 }
1667 1702
1668 1703 if (vflg) {
1669 1704 (void) printf("cw version %s\n", CW_VERSION);
1670 1705 (void) fflush(stdout);
1671 1706 main_ctx->i_flags &= ~CW_F_ECHO;
1672 1707 main_ctx->i_flags |= CW_F_PROG | CW_F_EXEC;
1673 1708 do_serial = 1;
1674 1709 }
1675 1710
1676 1711 ret |= exec_ctx(main_ctx, do_serial);
1677 1712
1678 1713 for (int i = 0; i < nshadows; i++) {
1679 1714 int r;
1680 1715 cw_ictx_t *shadow_ctx;
1681 1716
1682 1717 if ((shadow_ctx = newictx()) == NULL)
1683 1718 nomem();
1684 1719
1685 1720 memcpy(shadow_ctx, main_ctx, sizeof (cw_ictx_t));
1686 1721
1687 1722 shadow_ctx->i_flags |= CW_F_SHADOW;
1688 1723 shadow_ctx->i_compiler = &shadows[i];
1689 1724
1690 1725 r = exec_ctx(shadow_ctx, do_serial);
1691 1726 if (r == 0) {
1692 1727 shadow_ctx->i_next = main_ctx->i_next;
1693 1728 main_ctx->i_next = shadow_ctx;
1694 1729 }
1695 1730 ret |= r;
1696 1731 }
1697 1732
1698 1733 if (!do_serial) {
1699 1734 cw_ictx_t *next = main_ctx;
1700 1735 while (next != NULL) {
1701 1736 cw_ictx_t *toreap = next;
1702 1737 next = next->i_next;
1703 1738 ret |= reap(toreap);
1704 1739 }
1705 1740 }
1706 1741
1707 1742 return (ret);
1708 1743 }
↓ open down ↓ |
129 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX