blob: b6f65e94159561199142c16b2c78d704d8f66ae2 [file] [log] [blame]
/*
Copyright 2002-2003 John Plevyak, All Rights Reserved
*/
#include "d.h"
uint prime2[] = {
1, 3, 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191,
16381, 32749, 65521, 131071, 262139, 524287, 1048573, 2097143,
4194301, 8388593, 16777213, 33554393, 67108859, 134217689,
268435399, 536870909
};
int verbose_level = 0;
int debug_level = 0;
int test_level = 0;
char *
d_dup_pathname_str(char *s) {
char *e = s;
if (!s)
return strdup("");
if (*e == '"') {
e++; while (*e && *e != '"') e++;
return dup_str(s + 1, e);
} else
return dup_str(s, s+strlen(s));
}
char *
dup_str(char *s, char *e) {
int l = e-s;
char *ss = (char*)MALLOC(l+1);
memcpy(ss, s, l);
ss[l] = 0;
return ss;
}
uint
strhashl(char *s, int l) {
uint h = 0, g;
int i = 0;
for (;i < l;i++,s++) {
h = (h << 4) + *s;
if ((g = h & 0xf0000000))
h = (h ^ (g >> 24)) ^ g;
}
return h;
}
int
buf_read(char *pathname, char **buf, int *len) {
struct stat sb;
int fd;
*buf = 0;
*len = 0;
fd = open(pathname, O_RDONLY);
if (fd <= 0)
return -1;
memset(&sb, 0, sizeof(sb));
fstat(fd, &sb);
*len = sb.st_size;
*buf = (char*)MALLOC(*len + 2);
(*buf)[*len] = 0; /* terminator */
(*buf)[*len + 1] = 0; /* sentinal */
read(fd, *buf, *len);
close(fd);
return *len;
}
char *
sbuf_read(char *pathname) {
char *buf;
int len;
if (buf_read(pathname, &buf, &len) < 0)
return NULL;
return buf;
}
void
d_fail(char *str, ...) {
char nstr[256];
va_list ap;
va_start(ap, str);
snprintf(nstr, 255, "fail: %s\n", str);
vfprintf(stderr, nstr, ap);
va_end(ap);
exit(1);
}
void
vec_add_internal(void *v, void *elem) {
AbstractVec *av = (AbstractVec*)v;
if (!av->n) {
av->v = av->e;
} else if (av->v == av->e) {
av->v = (void**)MALLOC(INITIAL_VEC_SIZE * sizeof(void *));
memcpy(av->v, av->e, av->n * sizeof(void *));
} else
if ((av->n & (INITIAL_VEC_SIZE - 1)) == 0) {
int l = av->n, nl = (1 + INITIAL_VEC_SHIFT);
l = l >> INITIAL_VEC_SHIFT;
while (!(l&1)) { l = l >> 1; nl++; }
l = l >> 1;
if (!av->n || !l) {
nl = 1 << nl;
av->v = (void**)REALLOC(av->v, nl * sizeof(void *));
}
}
av->v[av->n++] = elem;
}
int
vec_eq(void *v, void *vv) {
AbstractVec *av = (AbstractVec*)v;
AbstractVec *avv = (AbstractVec*)vv;
uint i;
if (av->n != avv->n)
return 0;
for (i = 0; i < av->n; i++)
if (av->v[i] != avv->v[i])
return 0;
return 1;
}
void *
stack_push_internal(AbstractStack *s, void *elem) {
int n = s->cur - s->start;
if (s->start == s->initial) {
s->cur = (void**)MALLOC(n * 2 * sizeof(void*));
memcpy(s->cur, s->start, n * sizeof(void*));
} else
s->cur = (void**)REALLOC(s->start, n * 2 * sizeof(void*));
s->end = s->start = s->cur;
s->cur += n;
s->end += n * 2;
*s->cur++ = elem;
return elem;
}
int
set_add(void *av, void *t) {
AbstractVec *v = (AbstractVec*)av, vv;
int j, n = v->n;
uint i;
if (n) {
ulong h = ((ulong)t);
h = h % n;
for (i = h, j = 0;
i < v->n && j < SET_MAX_SEQUENTIAL;
i = ((i + 1) % n), j++)
{
if (!v->v[i]) {
v->v[i] = t;
return 1;
} else if (v->v[i] == t)
return 0;
}
}
if (!n) {
vv.v = NULL;
v->i = INITIAL_SET_SIZE_INDEX;
} else {
vv.v = v->v;
vv.n = v->n;
v->i = v->i + 1;
}
v->n = prime2[v->i];
v->v = (void**)MALLOC(v->n * sizeof(void *));
memset(v->v, 0, v->n * sizeof(void *));
if (vv.v) {
set_union(av, &vv);
FREE(vv.v);
}
return set_add(v, t);
}
void *
set_add_fn(void *av, void *t, hash_fns_t *fns) {
AbstractVec *v = (AbstractVec*)av, vv;
uint32 tt = fns->hash_fn(t, fns);
int j, n = v->n;
uint i;
if (n) {
uint h = tt % n;
for (i = h, j = 0;
i < v->n && j < SET_MAX_SEQUENTIAL;
i = ((i + 1) % n), j++)
{
if (!v->v[i]) {
v->v[i] = t;
return t;
} else {
if (!fns->cmp_fn(v->v[i], t, fns))
return v->v[i];
}
}
}
if (!n) {
vv.v = NULL;
v->i = INITIAL_SET_SIZE_INDEX;
} else {
vv.v = v->v;
vv.n = v->n;
v->i = v->i + 1;
}
v->n = prime2[v->i];
v->v = (void**)MALLOC(v->n * sizeof(void *));
memset(v->v, 0, v->n * sizeof(void *));
if (vv.v) {
set_union_fn(av, &vv, fns);
FREE(vv.v);
}
return set_add_fn(v, t, fns);
}
int
set_union(void *av, void *avv) {
AbstractVec *vv = (AbstractVec*)avv;
uint i, changed = 0;
for (i = 0; i < vv->n; i++)
if (vv->v[i])
changed = set_add(av, vv->v[i]) || changed;
return changed;
}
void
set_union_fn(void *av, void *avv, hash_fns_t *fns) {
AbstractVec *vv = (AbstractVec*)avv;
uint i;
for (i = 0; i < vv->n; i++)
if (vv->v[i])
set_add_fn(av, vv->v[i], fns);
}
void
set_to_vec(void *av) {
AbstractVec *v = (AbstractVec*)av, vv;
uint i;
vv.n = v->n;
vv.v = v->v;
if (v->v == v->e) {
memcpy(vv.e, v->e, sizeof(v->e));
vv.v = vv.e;
}
v->n = 0;
v->v = 0;
for (i = 0; i < vv.n; i++)
if (vv.v[i])
vec_add_internal(v, vv.v[i]);
FREE(vv.v);
}
void
int_list_diff(int *a, int *b, int *c) {
while (1) {
if (*b < 0)
break;
Lagainc:
if (*c < 0) {
while (*b >= 0)
*a++ = *b++;
break;
}
Lagainb:
if (*b == *c) {
b++;
c++;
continue;
}
if (*b < *c) {
*a++ = *b++;
if (*b < 0)
break;
goto Lagainb;
}
if (*c < *b) {
c++;
goto Lagainc;
}
}
*a++ = -1;
}
void
int_list_intersect(int *a, int *b, int *c) {
while (1) {
if (*b < 0)
break;
Lagainc:
if (*c < 0)
break;
Lagainb:
if (*b == *c) {
*a++ = *b++;
c++;
continue;
}
if (*b < *c) {
b++;
if (*b < 0)
break;
goto Lagainb;
}
if (*c < *b) {
c++;
goto Lagainc;
}
}
*a++ = -1;
}
int *
int_list_dup(int *aa) {
int *a = aa, *b, *bb;
while (*a != -1) { a++; }
bb = b = (int*)MALLOC((a - aa + 1) * sizeof(int));
a = aa;
while (*a != -1) { *b++ = *a++; }
*b++ = -1;
return bb;
}
#define ESC(_c) *ss++ = '\\'; *ss++ = _c; break;
char *
escape_string(char *s) {
char *ss = (char*)MALLOC((strlen(s) + 1) * 4), *sss = ss;
for (; *s; s++) {
switch (*s) {
case '\b': ESC('b');
case '\f': ESC('f');
case '\n': ESC('n');
case '\r': ESC('r');
case '\t': ESC('t');
case '\v': ESC('v');
case '\a': ESC('a');
case '\\':
case '\"':
*ss++ = '\\';
*ss++ = *s; break;
default:
if (isprint(*s)) {
*ss++ = *s;
} else {
*ss++ = '\\';
*ss++ = 'x';
*ss++ = tohex2(*s);
*ss++ = tohex1(*s);
}
break;
}
}
*ss = 0;
return sss;
}
void d_free(void *x) { FREE(x); }