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