mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-06 11:18:30 +00:00
Apply some touchups
This commit is contained in:
parent
9f149e1de3
commit
2f3bd90216
139 changed files with 1188 additions and 1154 deletions
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/arraylist2.internal.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
|
@ -53,6 +54,11 @@
|
|||
* directory be a .a prerequisite so archives rebuild on file deletion.
|
||||
*/
|
||||
|
||||
struct Args {
|
||||
size_t n;
|
||||
char **p;
|
||||
};
|
||||
|
||||
struct String {
|
||||
size_t i, n;
|
||||
char *p;
|
||||
|
@ -95,14 +101,18 @@ static void MakeHeader(struct Header *h, const char *name, int ref, int mode,
|
|||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
FILE *f;
|
||||
void *elf;
|
||||
char *line;
|
||||
char *strs;
|
||||
ssize_t rc;
|
||||
size_t wrote;
|
||||
size_t remain;
|
||||
struct stat *st;
|
||||
uint32_t outpos;
|
||||
Elf64_Sym *syms;
|
||||
struct Args args;
|
||||
uint64_t outsize;
|
||||
char **objectargs;
|
||||
uint8_t *tablebuf;
|
||||
struct iovec iov[7];
|
||||
const char *symname;
|
||||
|
@ -112,7 +122,6 @@ int main(int argc, char *argv[]) {
|
|||
struct String symbols;
|
||||
struct String filenames;
|
||||
struct Header *header1, *header2;
|
||||
size_t wrote, remain, objectargcount;
|
||||
int *offsets, *modes, *sizes, *names;
|
||||
int i, j, fd, err, name, outfd, tablebufsize;
|
||||
|
||||
|
@ -121,6 +130,25 @@ int main(int argc, char *argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
for (i = 3; i < argc; ++i) {
|
||||
if (argv[i][0] != '@') {
|
||||
args.p = realloc(args.p, ++args.n * sizeof(*args.p));
|
||||
args.p[args.n - 1] = strdup(argv[i]);
|
||||
} else {
|
||||
CHECK_NOTNULL((f = fopen(argv[i] + 1, "r")));
|
||||
while ((line = chomp(xgetline(f)))) {
|
||||
if (!isempty(line)) {
|
||||
args.p = realloc(args.p, ++args.n * sizeof(*args.p));
|
||||
args.p[args.n - 1] = line;
|
||||
} else {
|
||||
free(line);
|
||||
}
|
||||
}
|
||||
CHECK_NE(-1, fclose(f));
|
||||
}
|
||||
}
|
||||
|
||||
st = xmalloc(sizeof(struct stat));
|
||||
symbols.i = 0;
|
||||
symbols.n = 4096;
|
||||
|
@ -133,32 +161,29 @@ int main(int argc, char *argv[]) {
|
|||
symnames.p = xmalloc(symnames.n * sizeof(int));
|
||||
|
||||
outpath = argv[2];
|
||||
objectargs = argv + 3;
|
||||
objectargcount = argc - 3;
|
||||
modes = xmalloc(sizeof(int) * objectargcount);
|
||||
names = xmalloc(sizeof(int) * objectargcount);
|
||||
sizes = xmalloc(sizeof(int) * objectargcount);
|
||||
modes = xmalloc(sizeof(int) * args.n);
|
||||
names = xmalloc(sizeof(int) * args.n);
|
||||
sizes = xmalloc(sizeof(int) * args.n);
|
||||
|
||||
// load global symbols and populate page cache
|
||||
for (i = 0; i < objectargcount; ++i) {
|
||||
for (i = 0; i < args.n; ++i) {
|
||||
TryAgain:
|
||||
CHECK_NE(-1, (fd = open(objectargs[i], O_RDONLY)));
|
||||
CHECK_NE(-1, (fd = open(args.p[i], O_RDONLY)), "%s", args.p[i]);
|
||||
CHECK_NE(-1, fstat(fd, st));
|
||||
CHECK_LT(st->st_size, 0x7ffff000);
|
||||
if (!st->st_size || S_ISDIR(st->st_mode) ||
|
||||
endswith(objectargs[i], ".pkg")) {
|
||||
if (!st->st_size || S_ISDIR(st->st_mode) || endswith(args.p[i], ".pkg")) {
|
||||
close(fd);
|
||||
for (j = i; j + 1 < objectargcount; ++j) {
|
||||
objectargs[j] = objectargs[j + 1];
|
||||
for (j = i; j + 1 < args.n; ++j) {
|
||||
args.p[j] = args.p[j + 1];
|
||||
}
|
||||
--objectargcount;
|
||||
--args.n;
|
||||
goto TryAgain;
|
||||
}
|
||||
names[i] = filenames.i;
|
||||
sizes[i] = st->st_size;
|
||||
modes[i] = st->st_mode;
|
||||
CONCAT(&filenames.p, &filenames.i, &filenames.n, basename(objectargs[i]),
|
||||
strlen(basename(objectargs[i])));
|
||||
CONCAT(&filenames.p, &filenames.i, &filenames.n, basename(args.p[i]),
|
||||
strlen(basename(args.p[i])));
|
||||
CONCAT(&filenames.p, &filenames.i, &filenames.n, "/\n", 2);
|
||||
CHECK_NE(MAP_FAILED,
|
||||
(elf = mmap(NULL, st->st_size, PROT_READ, MAP_PRIVATE, fd, 0)));
|
||||
|
@ -182,7 +207,7 @@ int main(int argc, char *argv[]) {
|
|||
outsize = 0;
|
||||
tablebufsize = 4 + symnames.i * 4;
|
||||
tablebuf = xmalloc(tablebufsize);
|
||||
offsets = xmalloc(objectargcount * 4);
|
||||
offsets = xmalloc(args.n * 4);
|
||||
header1 = xmalloc(sizeof(struct Header));
|
||||
header2 = xmalloc(sizeof(struct Header));
|
||||
iov[0].iov_base = "!<arch>\n";
|
||||
|
@ -199,7 +224,7 @@ int main(int argc, char *argv[]) {
|
|||
outsize += (iov[5].iov_len = 60);
|
||||
iov[6].iov_base = filenames.p;
|
||||
outsize += (iov[6].iov_len = filenames.i);
|
||||
for (i = 0; i < objectargcount; ++i) {
|
||||
for (i = 0; i < args.n; ++i) {
|
||||
outsize += outsize & 1;
|
||||
offsets[i] = outsize;
|
||||
outsize += 60;
|
||||
|
@ -219,8 +244,8 @@ int main(int argc, char *argv[]) {
|
|||
CHECK_NE(-1, (outfd = open(outpath, O_WRONLY | O_TRUNC | O_CREAT, 0644)));
|
||||
ftruncate(outfd, outsize);
|
||||
if ((outsize = writev(outfd, iov, ARRAYLEN(iov))) == -1) goto fail;
|
||||
for (i = 0; i < objectargcount; ++i) {
|
||||
if ((fd = open(objectargs[i], O_RDONLY)) == -1) goto fail;
|
||||
for (i = 0; i < args.n; ++i) {
|
||||
if ((fd = open(args.p[i], O_RDONLY)) == -1) goto fail;
|
||||
iov[0].iov_base = "\n";
|
||||
outsize += (iov[0].iov_len = outsize & 1);
|
||||
iov[1].iov_base = header1;
|
||||
|
@ -233,6 +258,8 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
close(outfd);
|
||||
|
||||
for (i = 0; i < args.n; ++i) free(args.p[i]);
|
||||
free(args.p);
|
||||
free(header2);
|
||||
free(header1);
|
||||
free(offsets);
|
||||
|
|
337
tool/build/compile.c
Normal file
337
tool/build/compile.c
Normal file
|
@ -0,0 +1,337 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sigbits.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
#define MANUAL \
|
||||
"\
|
||||
OVERVIEW\n\
|
||||
\n\
|
||||
GNU/LLVM Compiler Collection Frontend Frontend\n\
|
||||
\n\
|
||||
DESCRIPTION\n\
|
||||
\n\
|
||||
This launches gcc or clang while filtering out\n\
|
||||
flags they whine about.\n\
|
||||
\n\
|
||||
EXAMPLE\n\
|
||||
\n\
|
||||
compile.com gcc -o program program.c\n\
|
||||
\n"
|
||||
|
||||
struct Flags {
|
||||
size_t n;
|
||||
char **p;
|
||||
};
|
||||
|
||||
struct Command {
|
||||
size_t n;
|
||||
char *p;
|
||||
};
|
||||
|
||||
bool iscc;
|
||||
bool isclang;
|
||||
bool isgcc;
|
||||
bool wantasan;
|
||||
bool wantfentry;
|
||||
bool wantframe;
|
||||
bool wantnop;
|
||||
bool wantnopg;
|
||||
bool wantpg;
|
||||
bool wantrecord;
|
||||
bool wantubsan;
|
||||
|
||||
char *cc;
|
||||
char *colorflag;
|
||||
char *outdir;
|
||||
char *outpath;
|
||||
char ccpath[PATH_MAX];
|
||||
int ccversion;
|
||||
|
||||
struct Flags flags;
|
||||
struct Command command;
|
||||
|
||||
void AddFlag(char *s) {
|
||||
size_t n;
|
||||
flags.p = realloc(flags.p, ++flags.n * sizeof(*flags.p));
|
||||
flags.p[flags.n - 1] = s;
|
||||
if (s) {
|
||||
n = strlen(s);
|
||||
if (command.n) {
|
||||
command.p = realloc(command.p, command.n + 1 + n);
|
||||
command.p[command.n] = ' ';
|
||||
memcpy(command.p + command.n + 1, s, n);
|
||||
command.n += 1 + n;
|
||||
} else {
|
||||
command.p = realloc(command.p, command.n + n);
|
||||
memcpy(command.p + command.n, s, n);
|
||||
command.n += n;
|
||||
}
|
||||
} else {
|
||||
command.p = realloc(command.p, command.n + 1);
|
||||
command.p[command.n] = '\n';
|
||||
command.n += 1;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i, ws, pid;
|
||||
sigset_t mask, savemask;
|
||||
|
||||
if (argc == 1) {
|
||||
write(2, MANUAL, sizeof(MANUAL) - 1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (argc == 2 && !strcmp(argv[1], "--do-nothing")) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!isdirectory("o/third_party/gcc")) {
|
||||
system("third_party/gcc/unbundle.sh");
|
||||
}
|
||||
|
||||
cc = argv[1];
|
||||
if (!strchr(cc, '/')) {
|
||||
if (!(cc = commandv(argv[1], ccpath))) exit(127);
|
||||
}
|
||||
|
||||
ccversion = atoi(firstnonnull(emptytonull(getenv("CCVERSION")), "4"));
|
||||
isgcc = strstr(basename(cc), "gcc");
|
||||
isclang = strstr(basename(cc), "clang");
|
||||
iscc = isgcc | isclang;
|
||||
|
||||
for (i = 1; i < argc; ++i) {
|
||||
if (argv[i][0] != '-') {
|
||||
AddFlag(argv[i]);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(argv[i], "-o")) {
|
||||
AddFlag(argv[i]);
|
||||
AddFlag((outpath = argv[++i]));
|
||||
continue;
|
||||
}
|
||||
if (iscc) {
|
||||
AddFlag(argv[i]);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(argv[i], "-w")) {
|
||||
AddFlag(argv[i]);
|
||||
AddFlag("-D__W__");
|
||||
} else if (!strcmp(argv[i], "-Oz")) {
|
||||
if (isclang) {
|
||||
AddFlag(argv[i]);
|
||||
} else {
|
||||
AddFlag("-Os");
|
||||
}
|
||||
} else if (!strcmp(argv[i], "-pg")) {
|
||||
wantpg = true;
|
||||
} else if (!strcmp(argv[i], "-x-no-pg")) {
|
||||
wantnopg = true;
|
||||
} else if (!strcmp(argv[i], "-mfentry")) {
|
||||
wantfentry = true;
|
||||
} else if (!strcmp(argv[i], "-mnop-mcount")) {
|
||||
wantnop = true;
|
||||
} else if (!strcmp(argv[i], "-mrecord-mcount")) {
|
||||
wantrecord = true;
|
||||
} else if (!strcmp(argv[i], "-fno-omit-frame-pointer")) {
|
||||
wantframe = true;
|
||||
} else if (!strcmp(argv[i], "-fomit-frame-pointer")) {
|
||||
wantframe = false;
|
||||
} else if (!strcmp(argv[i], "-mno-vzeroupper")) {
|
||||
if (isgcc) {
|
||||
AddFlag("-Wa,-msse2avx");
|
||||
AddFlag("-D__MNO_VZEROUPPER__");
|
||||
} else if (isclang) {
|
||||
AddFlag("-mllvm");
|
||||
AddFlag("-x86-use-vzeroupper=0");
|
||||
}
|
||||
} else if (!strcmp(argv[i], "-msse2avx")) {
|
||||
if (isgcc) {
|
||||
AddFlag(argv[i]);
|
||||
} else if (isclang) {
|
||||
AddFlag("-Wa,-msse2avx");
|
||||
}
|
||||
} else if (!strcmp(argv[i], "-fsanitize=address")) {
|
||||
if (isgcc && ccversion >= 6) wantasan = true;
|
||||
} else if (!strcmp(argv[i], "-fsanitize=undefined")) {
|
||||
if (isgcc && ccversion >= 6) wantubsan = true;
|
||||
} else if (!strcmp(argv[i], "-fno-sanitize=address")) {
|
||||
wantasan = false;
|
||||
} else if (!strcmp(argv[i], "-fno-sanitize=undefined")) {
|
||||
wantubsan = false;
|
||||
} else if (!strcmp(argv[i], "-fno-sanitize=all")) {
|
||||
wantasan = false;
|
||||
wantubsan = false;
|
||||
} else if (startswith(argv[i], "-fsanitize=implicit") &&
|
||||
strstr(argv[i], "integer")) {
|
||||
if (isgcc) AddFlag(argv[i]);
|
||||
} else if (startswith(argv[i], "-fvect-cost") ||
|
||||
startswith(argv[i], "-mstringop") ||
|
||||
startswith(argv[i], "-gz") ||
|
||||
strstr(argv[i], "stack-protector") ||
|
||||
strstr(argv[i], "sanitize") ||
|
||||
startswith(argv[i], "-fvect-cost") ||
|
||||
startswith(argv[i], "-fvect-cost")) {
|
||||
if (isgcc && ccversion >= 6) {
|
||||
AddFlag(argv[i]);
|
||||
}
|
||||
} else if (startswith(argv[i], "-fdiagnostic-color=")) {
|
||||
colorflag = argv[i];
|
||||
} else if (startswith(argv[i], "-R") ||
|
||||
!strcmp(argv[i], "-fsave-optimization-record")) {
|
||||
if (isclang) AddFlag(argv[i]);
|
||||
} else if (isclang &&
|
||||
(!strcmp(argv[i], "-gstabs") || !strcmp(argv[i], "-ftrapv") ||
|
||||
!strcmp(argv[i], "-fsignaling-nans") ||
|
||||
!strcmp(argv[i], "-fcx-limited-range") ||
|
||||
!strcmp(argv[i], "-fno-fp-int-builtin-inexact") ||
|
||||
!strcmp(argv[i], "-Wno-unused-but-set-variable") ||
|
||||
!strcmp(argv[i], "-Wunsafe-loop-optimizations") ||
|
||||
!strcmp(argv[i], "-mdispatch-scheduler") ||
|
||||
!strcmp(argv[i], "-ftracer") ||
|
||||
!strcmp(argv[i], "-frounding-math") ||
|
||||
!strcmp(argv[i], "-fmerge-constants") ||
|
||||
!strcmp(argv[i], "-fmodulo-sched") ||
|
||||
!strcmp(argv[i], "-fopt-info-vec") ||
|
||||
!strcmp(argv[i], "-fopt-info-vec-missed") ||
|
||||
!strcmp(argv[i], "-fmodulo-sched-allow-regmoves") ||
|
||||
!strcmp(argv[i], "-freschedule-modulo-scheduled-loops") ||
|
||||
!strcmp(argv[i], "-fipa-pta") ||
|
||||
!strcmp(argv[i], "-fsched2-use-superblocks") ||
|
||||
!strcmp(argv[i], "-fbranch-target-load-optimize") ||
|
||||
!strcmp(argv[i], "-fdelete-dead-exceptions") ||
|
||||
!strcmp(argv[i], "-funsafe-loop-optimizations") ||
|
||||
!strcmp(argv[i], "-mmitigate-rop") ||
|
||||
!strcmp(argv[i], "-fno-align-jumps") ||
|
||||
!strcmp(argv[i], "-fno-align-labels") ||
|
||||
!strcmp(argv[i], "-fno-align-loops") ||
|
||||
!strcmp(argv[i], "-fivopts") ||
|
||||
!strcmp(argv[i], "-fschedule-insns") ||
|
||||
!strcmp(argv[i], "-fno-semantic-interposition") ||
|
||||
!strcmp(argv[i], "-mno-fentry") ||
|
||||
!strcmp(argv[i], "-fversion-loops-for-strides") ||
|
||||
!strcmp(argv[i], "-femit-struct-debug-baseonly") ||
|
||||
!strcmp(argv[i], "-ftree-loop-vectorize") ||
|
||||
!strcmp(argv[i], "-gdescribe-dies") ||
|
||||
!strcmp(argv[i], "-flimit-function-alignment") ||
|
||||
!strcmp(argv[i], "-ftree-loop-im") ||
|
||||
!strcmp(argv[i], "-fno-instrument-functions") ||
|
||||
!strcmp(argv[i], "-fstack-clash-protection") ||
|
||||
!strcmp(argv[i], "-mfpmath=sse+387") ||
|
||||
!strcmp(argv[i], "-Wa,--noexecstack") ||
|
||||
!strcmp(argv[i], "-freg-struct-return") ||
|
||||
!strcmp(argv[i], "-mcall-ms2sysv-xlogues") ||
|
||||
startswith(argv[i], "-ffixed-") ||
|
||||
startswith(argv[i], "-fcall-saved") ||
|
||||
startswith(argv[i], "-fcall-used") ||
|
||||
startswith(argv[i], "-fgcse-") ||
|
||||
strstr(argv[i], "shrink-wrap") ||
|
||||
strstr(argv[i], "schedule-insns2") ||
|
||||
startswith(argv[i], "-fvect-cost-model=") ||
|
||||
startswith(argv[i], "-fsimd-cost-model=") ||
|
||||
startswith(argv[i], "-fopt-info") ||
|
||||
startswith(argv[i], "-mstringop-strategy=") ||
|
||||
startswith(argv[i], "-mpreferred-stack-boundary=") ||
|
||||
strstr(argv[i], "gnu-unique") ||
|
||||
startswith(argv[i], "-Wframe-larger-than=") ||
|
||||
strstr(argv[i], "whole-program") ||
|
||||
startswith(argv[i], "-Wa,--size-check=") ||
|
||||
startswith(argv[i], "-Wa,--listing"))) {
|
||||
/* ignore flag so clang won't whine */
|
||||
} else {
|
||||
AddFlag(argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (iscc) {
|
||||
if (isclang) {
|
||||
AddFlag("-fno-integrated-as");
|
||||
AddFlag("-Wno-unused-command-line-argument");
|
||||
AddFlag("-Wno-incompatible-pointer-types-discards-qualifiers");
|
||||
}
|
||||
AddFlag("-no-canonical-prefixes");
|
||||
if (!IsTerminalInarticulate()) {
|
||||
AddFlag(firstnonnull(colorflag, "-fdiagnostics-color=always"));
|
||||
}
|
||||
if (wantpg && !wantnopg) {
|
||||
AddFlag("-pg");
|
||||
AddFlag("-D__PG__");
|
||||
if (wantnop && !isclang) {
|
||||
AddFlag("-mnop-mcount");
|
||||
AddFlag("-D__MNOP_MCOUNT__");
|
||||
}
|
||||
if (wantrecord) {
|
||||
AddFlag("-mrecord-mcount");
|
||||
AddFlag("-D__MRECORD_MCOUNT__");
|
||||
}
|
||||
if (wantfentry) {
|
||||
AddFlag("-mfentry");
|
||||
AddFlag("-D__MFENTRY__");
|
||||
}
|
||||
}
|
||||
if (wantasan) {
|
||||
AddFlag("-fsanitize=address");
|
||||
AddFlag("-D__FSANITIZE_ADDRESS__");
|
||||
}
|
||||
if (wantubsan) {
|
||||
AddFlag("-fsanitize=undefined");
|
||||
AddFlag("-fno-data-sections");
|
||||
}
|
||||
}
|
||||
|
||||
AddFlag(NULL);
|
||||
|
||||
if (outpath) {
|
||||
outdir = xdirname(outpath);
|
||||
if (!isdirectory(outdir)) {
|
||||
makedirs(outdir, 0755);
|
||||
}
|
||||
}
|
||||
|
||||
write(2, command.p, command.n);
|
||||
|
||||
sigfillset(&mask);
|
||||
sigprocmask(SIG_BLOCK, &mask, &savemask);
|
||||
if ((pid = vfork()) == -1) exit(errno);
|
||||
if (!pid) {
|
||||
sigprocmask(SIG_SETMASK, &savemask, NULL);
|
||||
execv(cc, flags.p);
|
||||
_exit(127);
|
||||
}
|
||||
while (waitpid(pid, &ws, 0) == -1) {
|
||||
if (errno != EINTR) exit(errno);
|
||||
}
|
||||
|
||||
if (WIFEXITED(ws)) {
|
||||
return WEXITSTATUS(ws);
|
||||
} else {
|
||||
return 128 + WTERMSIG(ws);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue