I wonder what you have to say about this code. It's almost finished, but there are a number of problems - all functions work, except for calling redo with an empty argument. The reasons for some errors are not clear to me. Write if you have comments or ideas.
import core.stdc.stdio;
version (Posix)
{
extern (C)
{
import core.stdc.errno : errno, EAGAIN, ECHILD;
import core.stdc.inttypes : PRIx64;
import core.stdc.limits: PATH_MAX;
import core.stdc.stdarg;
import core.stdc.stdio;
import core.stdc.stdlib : malloc, exit, getenv, strtol;
import core.stdc.string : memcpy, memset, strchr, strcmp, strncpy, strdup, strlen, strncmp, strrchr;
import core.sys.posix.fcntl;
import core.sys.posix.sys.stat;
import core.sys.posix.sys.types : off_t, ssize_t;
import core.sys.posix.unistd;
import core.sys.posix.sys.wait : waitpid, WNOHANG;
int access(const char* pathname, int mode);
int close(int fd);
int dprintf(int fd, scope const char* format, ...) nothrow @nogc;
int mkstemp(scope const(char*) tmplt) nothrow @nogc;
int openat(int dirfd, scope const(char*) pathname, int flags) nothrow @nogc;
ssize_t pread(int fd, void* buf, size_t count, off_t offset) @nogc;
int setenv(scope const(char*) name, scope const(char*) value, int overwrite);
int printf (scope const(char*) format, ...) nothrow @nogc;
version(X86_64)
{
// from <fcntl.h>
enum O_DIRECTORY = 0x10000;
}
extern (D) int __WTERMSIG( int status ) { return status & 0x7F; }
extern (D) int WEXITSTATUS( int status ) { return ( status & 0xFF00 ) >> 8; }
extern (D) bool WIFEXITED( int status ) { return __WTERMSIG( status ) == 0; }
struct sha256
{
ulong len;
uint[8] h;
ubyte[64] buf;
}
uint ror(uint n, int k) pure nothrow @nogc
{
return (n >> k) | (n << (32 - k));
}
uint Ch(uint x, uint y, uint z) pure nothrow @nogc
{
return (z ^ (x & (y ^ z)));
}
uint Maj(uint x, uint y, uint z) pure nothrow @nogc
{
return ((x & y) | (z & (x | y)));
}
uint S0(uint x) pure nothrow @nogc
{
return (ror(x, 2) ^ ror(x, 13) ^ ror(x, 22));
}
uint S1(uint x) pure nothrow @nogc
{
return (ror(x, 6) ^ ror(x, 11) ^ ror(x, 25));
}
uint R0(uint x) pure nothrow @nogc
{
return (ror(x, 7) ^ ror(x, 18) ^ (x >> 3));
}
uint R1(uint x) pure nothrow @nogc
{
return (ror(x, 17) ^ ror(x, 19) ^ (x >> 10));
}
static const uint[64] K = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
];
static void processblock(sha256* s, const(ubyte*) buf)
{
uint[64] W;
uint t1, t2, a, b, c, d, e, f, g, h;
int i;
for (i = 0; i < 16; i++)
{
W[i] = cast(uint) buf[4*i]<<24;
W[i] |= cast(uint) buf[4*i+1]<<16;
W[i] |= cast(uint) buf[4*i+2]<<8;
W[i] |= buf[4*i+3];
}
for (; i < 64; i++)
{
W[i] = R1(W[i-2]) + W[i-7] + R0(W[i-15]) + W[i-16];
}
a = s.h[0];
b = s.h[1];
c = s.h[2];
d = s.h[3];
e = s.h[4];
f = s.h[5];
g = s.h[6];
h = s.h[7];
for (i = 0; i < 64; i++)
{
t1 = h + S1(e) + Ch(e, f, g) + K[i] + W[i];
t2 = S0(a) + Maj(a, b, c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
s.h[0] += a;
s.h[1] += b;
s.h[2] += c;
s.h[3] += d;
s.h[4] += e;
s.h[5] += f;
s.h[6] += g;
s.h[7] += h;
}
static void pad(sha256* s)
{
ubyte r = s.len % 64;
s.buf[r++] = 0x80;
if (r > 56)
{
memset(cast(ubyte*) s.buf.ptr + r, 0, 64 - r);
r = 0;
processblock(s, cast(ubyte*) s.buf.ptr);
}
memset(cast(ubyte*) s.buf.ptr + r, 0, 56 - r);
s.len *= 8;
s.buf[56] = cast(ubyte) (s.len >> 56);
s.buf[57] = cast(ubyte) (s.len >> 48);
s.buf[58] = cast(ubyte) (s.len >> 40);
s.buf[59] = cast(ubyte) (s.len >> 32);
s.buf[60] = cast(ubyte) (s.len >> 24);
s.buf[61] = cast(ubyte) (s.len >> 16);
s.buf[62] = cast(ubyte) (s.len >> 8);
s.buf[63] = cast(ubyte) s.len;
processblock(s, cast(ubyte*) s.buf.ptr);
}
static void sha256_init(sha256* s)
{
s.len = 0;
s.h[0] = 0x6a09e667;
s.h[1] = 0xbb67ae85;
s.h[2] = 0x3c6ef372;
s.h[3] = 0xa54ff53a;
s.h[4] = 0x510e527f;
s.h[5] = 0x9b05688c;
s.h[6] = 0x1f83d9ab;
s.h[7] = 0x5be0cd19;
}
static void sha256_sum(sha256* s, ubyte* md)
{
int i;
pad(s);
for (i = 0; i < 8; i++)
{
md[4*i] = cast(ubyte) (s.h[i] >> 24);
md[4*i+1] = cast(ubyte) (s.h[i] >> 16);
md[4*i+2] = cast(ubyte) (s.h[i] >> 8);
md[4*i+3] = cast(ubyte) (s.h[i]);
}
}
static void sha256_update(sha256* s, const(void*) m, ulong len)
{
ubyte* p = cast(ubyte*) m;
uint r = s.len % 64;
s.len += len;
if (r)
{
if (len < 64 - r)
{
memcpy(cast(ubyte*) s.buf.ptr + r, p, len);
return;
}
memcpy(cast(ubyte*) s.buf.ptr + r, p, 64 - r);
len -= 64 - r;
p += 64 - r;
processblock(s, cast(ubyte*) s.buf.ptr);
}
for (; len >= 64; len -= 64, p += 64)
{
processblock(s, cast(ubyte*) p);
}
memcpy(cast(ubyte*) s.buf.ptr, p, len);
}
__gshared int dir_fd = -1;
__gshared int dep_fd = -1;
__gshared int poolwr_fd = -1;
__gshared int poolrd_fd = -1;
__gshared int level = -1;
__gshared int implicit_jobs = 1;
__gshared int kflag, jflag, xflag, fflag, sflag;
static void redo_ifcreate(int fd, char* target)
{
dprintf(fd, "-%s\n", target);
}
static char* check_dofile(const char *fmt, ...)
{
static char[PATH_MAX] dofile;
va_list ap;
va_start(ap, fmt);
vsnprintf(cast(char*) dofile.ptr, dofile.sizeof, fmt, ap);
va_end(ap);
if (access(cast(char*) dofile.ptr, F_OK) == 0)
{
return cast(char*) dofile.ptr;
}
else
{
redo_ifcreate(dep_fd, cast(char*) dofile.ptr);
return cast(char*) 0;
}
}
static char* find_dofile(char* target)
{
char[PATH_MAX] updir;
char* u = cast(char*) updir.ptr;
char* dofile, s;
stat_t st, ost;
dofile = check_dofile("./%s.do", target);
if (dofile)
{
return dofile;
}
*u++ = '.';
*u++ = '/';
*u = 0;
st.st_dev = 0;
ost.st_dev = 0;
st.st_ino = 0;
ost.st_ino = 0;
while (1)
{
ost = st;
if (stat(cast(char*) updir.ptr, &st) < 0)
{
return cast(char*) 0;
}
if ((ost.st_dev == st.st_dev) && (ost.st_ino == st.st_ino))
{
break;
}
s = target;
while (*s)
{
if (*s++ == '.')
{
dofile = check_dofile("%sdefault.%s.do", cast(char*) updir.ptr, s);
if (dofile)
{
return dofile;
}
}
}
dofile = check_dofile("%sdefault.do", cast(char*) updir.ptr);
if (dofile)
{
return dofile;
}
*u++ = '.';
*u++ = '.';
*u++ = '/';
*u = 0;
}
return cast(char*) 0;
}
static int envfd(const char* name)
{
long fd;
char* s = getenv(name);
if (!s)
{
return -1;
}
fd = strtol(s, null, 10);
if ((fd < 0) || (fd > 255))
{
fd = -1;
}
return cast(int) fd;
}
static void setenvfd(const char* name, int i)
{
char[16] buf;
snprintf(cast(char*) buf.ptr, buf.sizeof, "%d", i);
setenv(name, cast(char*) buf.ptr, 1);
}
static char* hashfile(int fd)
{
static char[16] hex = "0123456789abcdef";
static char[65] asciihash;
sha256 ctx;
off_t off = 0;
char[4096] buf;
char* a;
char[32] hash;
int i;
ssize_t r;
sha256_init(&ctx);
while ((r = pread(fd, cast(char*) buf.ptr, buf.sizeof, off)) > 0)
{
sha256_update(&ctx, cast(char*) buf, r);
off += r;
}
sha256_sum(&ctx, cast(ubyte*) hash);
for (i = 0, a = cast(char*) asciihash.ptr; i < 32; i++)
{
*a++ = hex[hash[i] / 16];
*a++ = hex[hash[i] % 16];
}
*a = 0;
return cast(char*) asciihash.ptr;
}
static char* datefile(int fd)
{
static char[17] hexdate;
stat_t st;
fstat(fd, &st);
snprintf(cast(char*) hexdate.ptr, hexdate.sizeof, cast(char*) ("%016" ~ cast(string) PRIx64), cast(ulong) st.st_ctime);
return cast(char*) hexdate.ptr;
}
static int keepdir()
{
int fd = open(".", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
if (fd < 0)
{
perror("dir open");
exit(-1);
}
return fd;
}
static char* targetchdir(char* target)
{
char* base = strrchr(target, '/');
if (base)
{
int fd;
*base = 0;
fd = openat(dir_fd, target, O_RDONLY | O_DIRECTORY);
if (fd < 0)
{
perror("openat dir");
exit(111);
}
*base = '/';
if (fchdir(fd) < 0)
{
perror("chdir");
exit(111);
}
close(fd);
return base + 1;
}
else
{
fchdir(dir_fd);
return target;
}
}
static char* targetdep(char* target)
{
static char[PATH_MAX] buf;
snprintf(cast(char*) buf.ptr, buf.sizeof, ".dep.%s", target);
return cast(char*) buf.ptr;
}
static char* targetlock(char* target)
{
static char[PATH_MAX] buf;
snprintf(cast(char*) buf.ptr, buf.sizeof, ".lock.%s", target);
return cast(char*) buf.ptr;
}
static int sourcefile(char* target)
{
if (access(targetdep(target), F_OK) == 0)
{
return 0;
}
if (fflag < 0)
{
return access(target, F_OK) == 0;
}
return (find_dofile(target) == cast(char*) 0);
}
static int check_deps(char* target)
{
char* depfile;
FILE* f;
int ok = 1;
int fd;
int old_dir_fd = dir_fd;
target = targetchdir(target);
if (sourcefile(target))
{
return 1;
}
if (fflag > 0)
{
return 0;
}
depfile = targetdep(target);
f = fopen(depfile, "r");
if (!f)
{
return 0;
}
dir_fd = keepdir();
while (ok && !feof(f))
{
char[4096] line;
char* hash = cast(char*) line.ptr + 1;
char* timestamp = cast(char*) line.ptr + 1 + 64 + 1;
char* filename = cast(char*) line.ptr + 1 + 64 + 1 + 16 + 1;
if (fgets(cast(char*) line.ptr, line.sizeof, f))
{
line[strlen(cast(char*) line.ptr)-1] = 0;
switch (line[0])
{
case '-':
if (access(cast(char*) line.ptr + 1, F_OK) == 0)
{
ok = 0;
}
break;
case '=':
fd = open(filename, O_RDONLY);
if (fd < 0)
{
ok = 0;
}
else
{
if (strncmp(timestamp, datefile(fd), 16) != 0 && strncmp(hash, hashfile(fd), 64) != 0)
{
ok = 0;
}
close(fd);
}
if (ok && strcmp(target, filename) != 0)
{
ok = check_deps(filename);
fchdir(dir_fd);
}
break;
case '!':
default:
ok = 0;
}
}
else
{
if (!feof(f))
{
ok = 0;
break;
}
}
}
fclose(f);
close(dir_fd);
dir_fd = old_dir_fd;
return ok;
}
void vacate(int implicit)
{
if (implicit)
{
implicit_jobs++;
}
else
{
write(poolwr_fd, cast(char*) "\0".ptr, 1);
}
}
struct job
{
job* next;
pid_t pid;
int lock_fd;
char* target, temp_depfile, temp_target;
int implicit;
}
__gshared job* jobhead;
static void insert_job(job* jobn)
{
jobn.next = jobhead;
jobhead = jobn;
}
static void remove_job(job* jobn)
{
if (jobhead == jobn)
{
jobhead = jobhead.next;
}
else
{
job* j = jobhead;
while (j.next != jobn)
{
j = j.next;
}
j.next = j.next.next;
}
}
static job* find_job(pid_t pid)
{
job* j;
for (j = jobhead; j; j = j.next)
{
if (j.pid == pid)
{
return j;
}
}
return cast(job*) 0;
}
__gshared char[PATH_MAX] uprel = "\0";
void compute_uprel()
{
char* u = cast(char*) uprel.ptr;
char* dp = getenv("REDO_DIRPREFIX");
*u = 0;
while (dp && *dp) {
*u++ = '.';
*u++ = '.';
*u++ = '/';
*u = 0;
dp = strchr(dp + 1, '/');
}
}
static int write_dep(int dep_fd, const(char*) file)
{
int fd = open(file, O_RDONLY);
if (fd < 0)
{
return 0;
}
dprintf(dep_fd, "=%s %s %s%s\n", hashfile(fd), datefile(fd), (*file == '/' ? "" : cast(char*) uprel.ptr), file);
close(fd);
return 0;
}
int new_waitjob(int lock_fd, int implicit)
{
pid_t pid;
pid = fork();
if (pid < 0) {
perror("fork");
vacate(implicit);
exit(-1);
} else if (pid == 0) {
lockf(lock_fd, F_LOCK, 0);
close(lock_fd);
exit(0);
} else {
job* job;
if (!job)
{
exit(-1);
}
job.target = cast(char*) 0;
job.pid = pid;
job.lock_fd = lock_fd;
job.implicit = implicit;
insert_job(job);
}
return cast(char*) 0;
}
static char* redo_basename(char* dofile, char* target)
{
static char[PATH_MAX] buf = "\0";
int stripext = 0;
char* s;
if (strncmp(dofile, "default.", 8) == 0)
{
for (stripext = -1, s = dofile; *s; s++)
{
if (*s == '.')
{
stripext++;
}
}
}
strncpy(cast(char*) buf.ptr, target, buf.sizeof);
while (stripext--> 0)
{
if (strchr(cast(char*) buf.ptr, '.'))
{
char* e = strchr(cast(char*) buf.ptr, '\0');
while (*--e != '.')
{
*e = 0;
}
*e = 0;
}
}
return cast(char*) buf.ptr;
}
static void run_script(char* target, int implicit)
{
char[15] temp_depfile = cast(char[]) ".depend.XXXXXX\0";
char[15] temp_target_base = cast(char[]) ".target.XXXXXX\0";
char[PATH_MAX] temp_target = "\0",
rel_target = "\0",
cwd = "\0";
char* orig_target = target;
int old_dep_fd = dep_fd;
int target_fd;
char* dofile, dirprefix;
pid_t pid;
target = targetchdir(target);
dofile = find_dofile(target);
if (!dofile)
{
fprintf(stderr, "no dofile for %s.\n", target);
exit(1);
}
int lock_fd = open(targetlock(target), O_WRONLY | O_TRUNC | O_CREAT, 0x1b6);
if (lockf(lock_fd, F_TLOCK, 0) < 0)
{
if (errno == EAGAIN)
{
fprintf(stderr, "redo: %s already building, waiting.\n", orig_target);
new_waitjob(lock_fd, implicit);
return;
}
else
{
perror("lockf");
exit(111);
}
}
dep_fd = mkstemp(cast(char*) temp_depfile.ptr);
target_fd = mkstemp(cast(char*) temp_target_base.ptr);
fprintf(stderr, "redo%*.*s %s # %s\n", level*2, level*2, cast(char*) " ".ptr, orig_target, dofile);
write_dep(dep_fd, dofile);
getcwd(cast(char*) cwd.ptr, cwd.sizeof);
dirprefix = strchr(cast(char*) cwd.ptr, '\0');
dofile += 2;
while (strncmp(dofile, "../", 3) == 0)
{
chdir("..");
dofile += 3;
while (*--dirprefix != '/')
{}
}
if (*dirprefix)
{
dirprefix++;
}
snprintf(cast(char*) temp_target.ptr, temp_target.sizeof, "%s%s%s", dirprefix, (*dirprefix ? cast(char*) "/".ptr : cast(char*) "".ptr), cast(char*) temp_target_base.ptr);
snprintf(cast(char*) rel_target.ptr, rel_target.sizeof, "%s%s%s", dirprefix, (*dirprefix ? cast(char*) "/".ptr : cast(char*) "".ptr), target);
setenv("REDO_DIRPREFIX", dirprefix, 1);
pid = fork();
if (pid < 0)
{
perror("fork");
vacate(implicit);
exit(-1);
} else if (pid == 0) {
char* basename = redo_basename(dofile, cast(char*) rel_target.ptr);
if (old_dep_fd > 0)
{
close(old_dep_fd);
}
close(lock_fd);
setenvfd("REDO_DEP_FD", dep_fd);
setenvfd("REDO_LEVEL", level + 1);
if (sflag > 0)
{
dup2(target_fd, 1);
}
else
{
close(target_fd);
}
if (access(dofile, X_OK) != 0)
{
execl(
cast(char*) "/bin/sh".ptr,
cast(char*) "/bin/sh".ptr,
(xflag > 0) ? (cast(char*) "-ex".ptr) : (cast(char*) "-e".ptr),
dofile,
cast(char*) rel_target.ptr,
basename,
cast(char*) temp_target.ptr,
cast(char*) 0
);
}
else
{
execl(
dofile,
dofile,
cast(char*) rel_target.ptr,
basename,
cast(char*) temp_target.ptr,
cast(char*) 0
);
}
vacate(implicit);
exit(-1);
} else {
job* job;
if (!job)
{
exit(-1);
}
close(target_fd);
close(dep_fd);
dep_fd = old_dep_fd;
job.pid = pid;
job.lock_fd = lock_fd;
job.target = orig_target;
job.temp_depfile = strdup(cast(char*) temp_depfile.ptr);
job.temp_target = strdup(cast(char*) temp_target_base.ptr);
job.implicit = implicit;
insert_job(job);
}
}
static int try_procure()
{
if (implicit_jobs > 0)
{
implicit_jobs--;
return 1;
}
else
{
if (poolrd_fd < 0)
{
return 0;
}
fcntl(poolrd_fd, F_SETFL, O_NONBLOCK);
char[1] buf;
return read(poolrd_fd, &buf, 1) > 0;
}
}
static int procure()
{
if (implicit_jobs > 0)
{
implicit_jobs--;
return 1;
}
else
{
fcntl(poolrd_fd, F_SETFL, 0);
char[1] buf;
return read(poolrd_fd, &buf, 1) > 0;
}
}
void create_pool()
{
poolrd_fd = envfd(cast(char*) "REDO_RD_FD".ptr);
poolwr_fd = envfd(cast(char*) "REDO_WR_FD".ptr);
if (poolrd_fd < 0 || poolwr_fd < 0)
{
int jobs = envfd(cast(char*) "JOBS".ptr);
if (jobs > 1)
{
int i;
int[2] fds;
pipe(fds);
poolrd_fd = fds[0];
poolwr_fd = fds[1];
for (i = 0; i < jobs-1; i++)
{
vacate(0);
}
setenvfd(cast(char*) "REDO_RD_FD".ptr, poolrd_fd);
setenvfd(cast(char*) "REDO_WR_FD".ptr, poolwr_fd);
}
else
{
poolrd_fd = -1;
poolwr_fd = -1;
}
}
}
static void redo_ifchange(int targetc, char** targetv)
{
pid_t pid;
int status;
job* job;
int targeti = 0;
char[4096] buf = void;
char* skip = cast(char*) buf.ptr;
create_pool();
for (targeti = 0; targeti < targetc; targeti++)
{
skip[targeti] = cast(char) check_deps(targetv[targeti]);
printf("steps %d - %s\n", targetv[targeti]);
}
printf("targetc = %d\n", targetc);
targeti = 0;
while (1)
{
int procured = 0;
if (targeti < targetc)
{
char* target = cast(char*) targetv[targeti];
if (skip[targeti])
{
targeti++;
continue;
}
int implicit = implicit_jobs > 0;
if (try_procure())
{
procured = 1;
targeti++;
run_script(target, implicit);
}
}
printf("error here\n");
pid = waitpid(-1, &status, procured ? WNOHANG : 0);
printf("pid = %d", pid);
if (pid == 0)
{
continue;
}
if (pid < 0)
{
if (errno == ECHILD && targeti < targetc)
{
continue;
}
else
{
break;
}
}
if (WIFEXITED(status))
{
status = WEXITSTATUS(status);
}
printf("error in find job\n");
job = find_job(pid);
if (!job)
{
exit(-1);
}
printf("error in remove job\n");
remove_job(job);
if (job.target)
{
if (status > 0)
{
remove(job.temp_depfile);
remove(job.temp_target);
}
else
{
stat_t st;
char* target = targetchdir(job.target);
char* depfile = targetdep(target);
int dfd;
dfd = open(job.temp_depfile, O_WRONLY | O_APPEND);
if (stat(job.temp_target, &st) == 0)
{
rename(job.temp_target, target);
write_dep(dfd, target);
}
else
{
remove(job.temp_target);
redo_ifcreate(dfd, target);
}
close(dfd);
rename(job.temp_depfile, depfile);
remove(targetlock(target));
}
}
close(job.lock_fd);
vacate(job.implicit);
if ((kflag < 0) && (status > 0))
{
printf("failed with status %d\n", status);
exit(status);
}
}
}
static void record_deps(int targetc, char** targetv)
{
int targeti = 0;
int fd;
dep_fd = envfd("REDO_DEP_FD");
if (dep_fd < 0)
{
return;
}
fchdir(dir_fd);
for (targeti = 0; targeti < targetc; targeti++)
{
fd = open(targetv[targeti], O_RDONLY);
if (fd < 0)
{
continue;
}
write_dep(dep_fd, targetv[targeti]);
close(fd);
}
}
int main(int argc, char** argv)
{
char* program;
int opt = 0, i = 0;
dep_fd = envfd(cast(char*) "REDO_DEP_FD".ptr);
level = envfd(cast(char*) "REDO_LEVEL".ptr);
if (level < 0)
{
level = 0;
}
char* progname = strrchr(cast(char*) argv[0], cast(char*) '/');
if (progname !is null)
{
program = progname;
program++;
}
else
{
program = argv[0];
}
while ((opt = getopt(argc, argv, "+kxfsj:C:")) != -1)
{
switch (opt)
{
case 'k':
setenvfd(cast(char*) "REDO_KEEP_GOING".ptr, 1);
break;
case 'x':
setenvfd(cast(char*) "REDO_TRACE".ptr, 1);
break;
case 'f':
setenvfd(cast(char*) "REDO_FORCE".ptr, 1);
break;
case 's':
setenvfd(cast(char*) "REDO_STDOUT".ptr, 1);
break;
case 'j':
setenv(cast(char*) "JOBS".ptr, optarg, 1);
break;
case 'C':
if (chdir(optarg) < 0)
{
perror("chdir");
exit(-1);
}
break;
default:
fprintf(stderr, "usage: %s [-kfsx] [-jN] [-Cdir] [TARGETS...]\n", program);
exit(1);
break;
}
}
argc -= optind;
argv += optind;
fflag = envfd(cast(char*) "REDO_FORCE".ptr);
kflag = envfd(cast(char*) "REDO_KEEP_GOING".ptr);
xflag = envfd(cast(char*) "REDO_TRACE".ptr);
sflag = envfd(cast(char*) "REDO_STDOUT".ptr);
dir_fd = keepdir();
if (strcmp(program, cast(char*) "redo".ptr) == 0)
{
char* all = cast(char*) "all".ptr;
char*[1] argv_def = [all];
if (argc == 0)
{
argc = 1;
argv = argv_def.ptr;
printf("%s", argv[0]);
}
fflag = 1;
printf("%s", argv);
redo_ifchange(argc, argv);
procure();
} else if (strcmp(program, cast(char*) "redo-ifchange".ptr) == 0) {
compute_uprel();
redo_ifchange(argc, argv);
record_deps(argc, argv);
procure();
} else if (strcmp(program, cast(char*) "redo-ifcreate".ptr) == 0) {
for (i = 0; i < argc; i++)
{
redo_ifcreate(dep_fd, argv[i]);
}
} else if (strcmp(program, cast(char*) "redo-always".ptr) == 0) {
dprintf(dep_fd, "!\n");
} else if (strcmp(program, cast(char*) "redo-hash".ptr) == 0) {
for (i = 0; i < argc; i++)
{
write_dep(1, cast(const(char*)) argv[i]);
}
} else {
fprintf(stderr, "not implemented %s\n", program);
exit(-1);
}
return 0;
}
}
}