diff options
Diffstat (limited to 'base')
-rw-r--r-- | base/base_cpudep.c | 221 | ||||
-rw-r--r-- | base/base_error.c | 78 | ||||
-rw-r--r-- | base/base_hash.c | 274 | ||||
-rw-r--r-- | base/base_matrix.c | 151 | ||||
-rw-r--r-- | base/base_memory.c | 91 | ||||
-rw-r--r-- | base/base_rect.c | 75 | ||||
-rw-r--r-- | base/base_rune.c | 168 | ||||
-rw-r--r-- | base/util_getopt.c | 116 | ||||
-rw-r--r-- | base/util_strlcat.c | 35 | ||||
-rw-r--r-- | base/util_strlcpy.c | 32 | ||||
-rw-r--r-- | base/util_strsep.c | 11 |
11 files changed, 1252 insertions, 0 deletions
diff --git a/base/base_cpudep.c b/base/base_cpudep.c new file mode 100644 index 00000000..0db2e331 --- /dev/null +++ b/base/base_cpudep.c @@ -0,0 +1,221 @@ +/* +run-time cpu feature detection code +mm, alphabet soup... + +Glenn Kennard <d98gk@efd.lth.se> +*/ + +#include <fitz.h> + +/* global run-time constant */ +unsigned fz_cpuflags = 0; + +#ifndef HAVE_CPUDEP + +void fz_accelerate(void) +{ +} + +void fz_cpudetect(void) +{ +} + +#else + +#include <signal.h> /* signal/sigaction */ +#include <setjmp.h> /* sigsetjmp/siglongjmp */ + +#ifdef WIN32 +#define sigjmp_buf jmp_buf +#define sigsetjmp(a,b) setjmp(a) +#define siglongjmp longjmp +#endif + +typedef struct { + void (*test)(void); + const unsigned flag; + const char *name; +} featuretest; + + +#if defined(ARCH_X86) || defined(ARCH_X86_64) + +/* need emms?? */ +static void mmx(void) +{ __asm__ ("pand %mm0, %mm0\n\t"); } + +static void m3dnow(void) +{ __asm__ ("pavgusb %mm0, %mm0\n\t"); } + +static void mmxext(void) /* aka Extended 3DNow! */ +{ __asm__ ("pmaxsw %mm0, %mm0\n\t"); } + +static void sse(void) +{ __asm__ ("andps %xmm0, %xmm0\n\t"); } + +static void sse2(void) +{ __asm__ ("andpd %xmm0, %xmm0\n\t"); } + +/* static void sse3(void) */ +/* { __asm__ ("haddps %%xmm0, %%xmm0\n\t" : : : "%xmm0"); } */ + +#ifdef ARCH_X86_64 +static void amd64(void) +{ __asm__ ("and %rax, %rax\n\t"); } +#endif + + +static const featuretest features[] = { + { mmx, HAVE_MMX, "mmx" }, + { m3dnow, HAVE_3DNOW, "3dnow" }, + { mmxext, HAVE_MMXEXT, "mmxext" }, + { sse, HAVE_SSE, "sse" }, + { sse2, HAVE_SSE2, "sse2" }, +/* { sse3, HAVE_SSE3, "sse3" }, */ +#ifdef ARCH_X86_64 + { amd64, HAVE_AMD64, "amd64" } +#endif +}; + +#endif + + +#if defined(ARCH_SPARC) +/* assembler must have -xarch=v8plusa passed to it (v9a for 64 bit binaries) */ +static void vis(void) +{ __asm__ ("fand %f8, %f8, %f8\n\t"); } + +static const featuretest features[] = { + { vis, HAVE_VIS, "vis" } +}; + +#endif + + +#if defined(ARCH_PPC) + +static void altivec(void) +{ __asm__ ("vand v0, v0, v0\n\t"); } + + +static const featuretest features[] = { + { altivec, HAVE_ALTIVEC, "altivec" }, +}; + +#endif + +static sigjmp_buf jmpbuf; +static volatile sig_atomic_t canjump; + +static void +sigillhandler(int sig) +{ + if (!canjump) { + signal(sig, SIG_DFL); + raise(sig); + } + + canjump = 0; + siglongjmp(jmpbuf, 1); +} + +static int +enabled(char *env, const char *ext) +{ + int len; + char *s; + if (!env) + return 1; + len = strlen(ext); + while ((s = strstr(env, ext))) + { + s += len; + if (*s == ' ' || *s == ',' || *s == '\0') + return 1; + } + return 0; +} + +static void +dumpflags(void) +{ + unsigned f = fz_cpuflags; + int i, n; + + fputs("detected cpu features:", stdout); + n = 0; + for (i = 0; i < sizeof(features) / sizeof(featuretest); i++) + { + if (f & features[i].flag) + { + fputc(' ', stdout); + fputs(features[i].name, stdout); + n ++; + } + } + if (!n) + fputs(" none", stdout); + fputc('\n', stdout); +} + +void fz_cpudetect(void) +{ + static int hasrun = 0; + + unsigned flags = 0; + int i; + void (*oldhandler)(int) = NULL; + void (*tmphandler)(int); + char *env; + + if (hasrun) + return; + hasrun = 1; + + env = getenv("CPUACCEL"); + + for (i = 0; i < sizeof(features) / sizeof(featuretest); i++) + { + canjump = 0; + + tmphandler = signal(SIGILL, sigillhandler); + if (!oldhandler) + oldhandler = tmphandler; + + if (sigsetjmp(jmpbuf, 1)) + { + /* test failed - disable feature */ + flags &= ~features[i].flag; + continue; + } + + canjump = 1; + + features[i].test(); + + /* if we got here the test succeeded */ + if (enabled(env, features[i].name)) + flags |= features[i].flag; + else + flags &= ~features[i].flag; + } + + /* restore previous signal handler */ + signal(SIGILL, oldhandler); + + fz_cpuflags = flags; + +#if defined(ARCH_X86) || defined(ARCH_X86_64) + __asm__ __volatile__ ("emms\n\t"); +#endif + + dumpflags(); +} + +static __attribute__((constructor, used)) void fzcpudetect(void) +{ + fz_cpudetect(); +} + +#endif + diff --git a/base/base_error.c b/base/base_error.c new file mode 100644 index 00000000..926c48dc --- /dev/null +++ b/base/base_error.c @@ -0,0 +1,78 @@ +#include <fitz.h> + +void +fz_warn(char *fmt, ...) +{ + va_list ap; + fprintf(stderr, "warning: "); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +fz_error * +fz_throw1(char *fmt, ...) +{ + va_list ap; + fz_error *eo; + + eo = fz_malloc(sizeof(fz_error)); + if (!eo) return fz_outofmem; + + eo->refs = 1; + strlcpy(eo->func, "unknown", sizeof eo->func); + strlcpy(eo->file, "unknown", sizeof eo->file); + eo->line = 0; + + va_start(ap, fmt); + vsnprintf(eo->msg, sizeof eo->msg, fmt, ap); + eo->msg[sizeof(eo->msg) - 1] = '\0'; + va_end(ap); + + return eo; +} + +fz_error * +fz_throw0(const char *func, const char *file, int line, char *fmt, ...) +{ + va_list ap; + fz_error *eo; + + eo = fz_malloc(sizeof(fz_error)); + if (!eo) return fz_outofmem; + + eo->refs = 1; + strlcpy(eo->func, func, sizeof eo->func); + strlcpy(eo->file, file, sizeof eo->file); + eo->line = line; + + va_start(ap, fmt); + vsnprintf(eo->msg, sizeof eo->msg, fmt, ap); + eo->msg[sizeof(eo->msg) - 1] = '\0'; + va_end(ap); + + if (getenv("BOMB")) + fz_abort(eo); + + return eo; +} + +void +fz_droperror(fz_error *eo) +{ + if (eo->refs > 0) + eo->refs--; + if (eo->refs == 0) + fz_free(eo); +} + +void +fz_abort(fz_error *eo) +{ + fflush(stdout); + fprintf(stderr, "%s:%d: %s(): %s\n", eo->file, eo->line, eo->func, eo->msg); + fflush(stderr); + abort(); +} + diff --git a/base/base_hash.c b/base/base_hash.c new file mode 100644 index 00000000..65bc7130 --- /dev/null +++ b/base/base_hash.c @@ -0,0 +1,274 @@ +/* Linear probe hash table. + * 2004 (C) Tor Andersson. + * BSD license. + * + * Simple hashtable with open adressing linear probe. + * Unlike text book examples, removing entries works + * correctly in this implementation so it wont start + * exhibiting bad behaviour if entries are inserted + * and removed frequently. + */ + +#include <fitz.h> + +enum { MAXKEYLEN = 16 }; + +typedef struct fz_hashentry_s fz_hashentry; + +struct fz_hashentry_s +{ + unsigned char key[MAXKEYLEN]; + void *val; +}; + +struct fz_hashtable_s +{ + int keylen; + int size; + int load; + fz_hashentry *ents; +}; + +static unsigned hash(unsigned char *s, int len) +{ + unsigned hash = 0; + int i; + for (i = 0; i < len; i++) + { + hash += s[i]; + hash += (hash << 10); + hash ^= (hash >> 6); + } + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + return hash; +} + +fz_error * +fz_newhash(fz_hashtable **tablep, int initialsize, int keylen) +{ + fz_hashtable *table; + + assert(keylen <= MAXKEYLEN); + + table = *tablep = fz_malloc(sizeof(fz_hashtable)); + if (!table) + return fz_outofmem; + + table->keylen = keylen; + table->size = initialsize; + table->load = 0; + + table->ents = fz_malloc(sizeof(fz_hashentry) * table->size); + if (!table->ents) + { + fz_free(table); + *tablep = nil; + return fz_outofmem; + } + + memset(table->ents, 0, sizeof(fz_hashentry) * table->size); + + return nil; +} + +void +fz_emptyhash(fz_hashtable *table) +{ + table->load = 0; + memset(table->ents, 0, sizeof(fz_hashentry) * table->size); +} + +int +fz_hashlen(fz_hashtable *table) +{ + return table->size; +} + +void * +fz_hashgetkey(fz_hashtable *table, int idx) +{ + return table->ents[idx].key; +} + +void * +fz_hashgetval(fz_hashtable *table, int idx) +{ + return table->ents[idx].val; +} + +void +fz_drophash(fz_hashtable *table) +{ + fz_free(table->ents); + fz_free(table); +} + +fz_error * +fz_resizehash(fz_hashtable *table, int newsize) +{ + fz_error *error; + fz_hashentry *newents; + fz_hashentry *oldents; + int oldload; + int oldsize; + int i; + + oldsize = table->size; + oldload = table->load; + oldents = table->ents; + + if (newsize < oldload * 8 / 10) + return fz_throw("rangecheck: resize hash too small"); + + newents = fz_malloc(sizeof(fz_hashentry) * newsize); + if (!newents) + return fz_outofmem; + + table->size = newsize; + table->load = 0; + table->ents = newents; + memset(table->ents, 0, sizeof(fz_hashentry) * table->size); + + for (i = 0; i < oldsize; i++) + { + if (oldents[i].val) + { + error = fz_hashinsert(table, oldents[i].key, oldents[i].val); + if (error) + { + table->size = oldsize; + table->load = oldload; + table->ents = oldents; + fz_free(newents); + return error; + } + } + } + + fz_free(oldents); + return nil; +} + +void * +fz_hashfind(fz_hashtable *table, void *key) +{ + fz_hashentry *ents = table->ents; + unsigned size = table->size; + unsigned pos = hash(key, table->keylen) % size; + + while (1) + { + if (!ents[pos].val) + return nil; + + if (memcmp(key, &ents[pos].key, table->keylen) == 0) + return ents[pos].val; + + pos = (pos + 1) % size; + } +} + +fz_error * +fz_hashinsert(fz_hashtable *table, void *key, void *val) +{ + fz_error *error; + fz_hashentry *ents; + unsigned size; + unsigned pos; + + if (table->load > table->size * 8 / 10) + { + error = fz_resizehash(table, table->size * 2); + if (error) + return error; + } + + ents = table->ents; + size = table->size; + pos = hash(key, table->keylen) % size; + + while (1) + { + if (!ents[pos].val) + { + memcpy(ents[pos].key, key, table->keylen); + ents[pos].val = val; + table->load ++; + return nil; + } + + if (memcmp(key, &ents[pos].key, table->keylen) == 0) + return fz_throw("rangecheck: overwrite hash slot"); + + pos = (pos + 1) % size; + } + + return nil; +} + +fz_error * +fz_hashremove(fz_hashtable *table, void *key) +{ + fz_hashentry *ents = table->ents; + unsigned size = table->size; + unsigned pos = hash(key, table->keylen) % size; + unsigned hole, look, code; + + while (1) + { + if (!ents[pos].val) + return fz_throw("rangecheck: remove inexistant hash entry"); + + if (memcmp(key, &ents[pos].key, table->keylen) == 0) + { + ents[pos].val = nil; + + hole = pos; + look = (hole + 1) % size; + + while (ents[look].val) + { + code = hash(ents[look].key, table->keylen) % size; + if ((code <= hole && hole < look) || + (look < code && code <= hole) || + (hole < look && look < code)) + { + ents[hole] = ents[look]; + ents[look].val = nil; + hole = look; + } + + look = (look + 1) % size; + } + + table->load --; + return nil; + } + + pos = (pos + 1) % size; + } +} + +void +fz_debughash(fz_hashtable *table) +{ + int i, k; + + printf("cache load %d / %d\n", table->load, table->size); + + for (i = 0; i < table->size; i++) + { + if (!table->ents[i].val) + printf("table % 4d: empty\n", i); + else + { + printf("table % 4d: key=", i); + for (k = 0; k < MAXKEYLEN; k++) + printf("%02x", ((char*)table->ents[i].key)[k]); + printf(" val=$%p\n", table->ents[i].val); + } + } +} + diff --git a/base/base_matrix.c b/base/base_matrix.c new file mode 100644 index 00000000..e24196f9 --- /dev/null +++ b/base/base_matrix.c @@ -0,0 +1,151 @@ +#include <fitz.h> + +void fz_invert3x3(float *dst, float *m) +{ + float det; + int i; + +#define M3(m,i,j) (m)[3*i+j] +#define D2(a,b,c,d) (a * d - b * c) +#define D3(a1,a2,a3,b1,b2,b3,c1,c2,c3) \ + (a1 * D2(b2,b3,c2,c3)) - \ + (b1 * D2(a2,a3,c2,c3)) + \ + (c1 * D2(a2,a3,b2,b3)) + + det = D3(M3(m,0,0), M3(m,1,0), M3(m,2,0), + M3(m,0,1), M3(m,1,1), M3(m,2,1), + M3(m,0,2), M3(m,1,2), M3(m,2,2)); + if (det == 0) + det = 1.0; + det = 1.0 / det; + + M3(dst,0,0) = M3(m,1,1) * M3(m,2,2) - M3(m,1,2) * M3(m,2,1); + M3(dst,0,1) = -M3(m,0,1) * M3(m,2,2) + M3(m,0,2) * M3(m,2,1); + M3(dst,0,2) = M3(m,0,1) * M3(m,1,2) - M3(m,0,2) * M3(m,1,1); + + M3(dst,1,0) = -M3(m,1,0) * M3(m,2,2) + M3(m,1,2) * M3(m,2,0); + M3(dst,1,1) = M3(m,0,0) * M3(m,2,2) - M3(m,0,2) * M3(m,2,0); + M3(dst,1,2) = -M3(m,0,0) * M3(m,1,2) + M3(m,0,2) * M3(m,1,0); + + M3(dst,2,0) = M3(m,1,0) * M3(m,2,1) - M3(m,1,1) * M3(m,2,0); + M3(dst,2,1) = -M3(m,0,0) * M3(m,2,1) + M3(m,0,1) * M3(m,2,0); + M3(dst,2,2) = M3(m,0,0) * M3(m,1,1) - M3(m,0,1) * M3(m,1,0); + + for (i = 0; i < 9; i++) + dst[i] *= det; +} + +fz_matrix +fz_concat(fz_matrix one, fz_matrix two) +{ + fz_matrix dst; + dst.a = one.a * two.a + one.b * two.c; + dst.b = one.a * two.b + one.b * two.d; + dst.c = one.c * two.a + one.d * two.c; + dst.d = one.c * two.b + one.d * two.d; + dst.e = one.e * two.a + one.f * two.c + two.e; + dst.f = one.e * two.b + one.f * two.d + two.f; + return dst; +} + +fz_matrix +fz_identity(void) +{ + fz_matrix m; + m.a = 1; m.b = 0; + m.c = 0; m.d = 1; + m.e = 0; m.f = 0; + return m; +} + +fz_matrix +fz_scale(float sx, float sy) +{ + fz_matrix m; + m.a = sx; m.b = 0; + m.c = 0; m.d = sy; + m.e = 0; m.f = 0; + return m; +} + +fz_matrix +fz_rotate(float theta) +{ + fz_matrix m; + float s = sin(theta * M_PI / 180.0); + float c = cos(theta * M_PI / 180.0); + m.a = c; m.b = s; + m.c = -s; m.d = c; + m.e = 0; m.f = 0; + return m; +} + +fz_matrix +fz_translate(float tx, float ty) +{ + fz_matrix m; + m.a = 1; m.b = 0; + m.c = 0; m.d = 1; + m.e = tx; m.f = ty; + return m; +} + +fz_matrix +fz_invertmatrix(fz_matrix src) +{ + fz_matrix dst; + float rdet = 1.0 / (src.a * src.d - src.b * src.c); + dst.a = src.d * rdet; + dst.b = -src.b * rdet; + dst.c = -src.c * rdet; + dst.d = src.a * rdet; + dst.e = -src.e * dst.a - src.f * dst.c; + dst.f = -src.e * dst.b - src.f * dst.d; + return dst; +} + +int +fz_isrectilinear(fz_matrix m) +{ + return (fabs(m.b) < FLT_EPSILON && fabs(m.c) < FLT_EPSILON) || + (fabs(m.a) < FLT_EPSILON && fabs(m.d) < FLT_EPSILON); +} + +float +fz_matrixexpansion(fz_matrix m) +{ + return sqrt(fabs(m.a * m.d - m.b * m.c)); +} + +fz_point +fz_transformpoint(fz_matrix m, fz_point p) +{ + fz_point t; + t.x = p.x * m.a + p.y * m.c + m.e; + t.y = p.x * m.b + p.y * m.d + m.f; + return t; +} + +fz_rect +fz_transformaabb(fz_matrix m, fz_rect r) +{ + fz_point s, t, u, v; + + if (fz_isinfiniterect(r)) + return r; + + s.x = r.x0; s.y = r.y0; + t.x = r.x0; t.y = r.y1; + u.x = r.x1; u.y = r.y1; + v.x = r.x1; v.y = r.y0; + s = fz_transformpoint(m, s); + t = fz_transformpoint(m, t); + u = fz_transformpoint(m, u); + v = fz_transformpoint(m, v); + r.x0 = MIN4(s.x, t.x, u.x, v.x); + r.y0 = MIN4(s.y, t.y, u.y, v.y); + r.x1 = MAX4(s.x, t.x, u.x, v.x); + r.y1 = MAX4(s.y, t.y, u.y, v.y); + return r; +} + diff --git a/base/base_memory.c b/base/base_memory.c new file mode 100644 index 00000000..48988dbc --- /dev/null +++ b/base/base_memory.c @@ -0,0 +1,91 @@ +#include <fitz.h> + +/* Make this thread local storage if you wish. */ + +static void *stdmalloc(fz_memorycontext *mem, int n) +{ +#if 0 + void *p = malloc(n); + if (!p) + fprintf(stderr, "failed to malloc %d bytes\n", n); + return p; +#else + return malloc(n); +#endif +} + +static void *stdrealloc(fz_memorycontext *mem, void *p, int n) +{ +#if 0 + void *np = realloc(p, n); + if (np == nil) + fprintf(stderr, "realloc failed %d nytes", n); + else if (np == p) + fprintf(stderr, "realloc kept %d\n", n); + else + fprintf(stderr, "realloc moved %d\n", n); + return np; +#else + return realloc(p, n); +#endif +} + +static void stdfree(fz_memorycontext *mem, void *p) +{ + free(p); +} + +static fz_memorycontext defmem = { stdmalloc, stdrealloc, stdfree }; +static fz_memorycontext *curmem = &defmem; + +fz_error fz_koutofmem = { + -1, + {"out of memory"}, + {"<malloc>"}, + {"memory.c"}, + 0 +}; + +fz_memorycontext * +fz_currentmemorycontext() +{ + return curmem; +} + +void +fz_setmemorycontext(fz_memorycontext *mem) +{ + curmem = mem; +} + +void * +fz_malloc(int n) +{ + fz_memorycontext *mem = fz_currentmemorycontext(); + return mem->malloc(mem, n); +} + +void * +fz_realloc(void *p, int n) +{ + fz_memorycontext *mem = fz_currentmemorycontext(); + return mem->realloc(mem, p, n); +} + +void +fz_free(void *p) +{ + fz_memorycontext *mem = fz_currentmemorycontext(); + mem->free(mem, p); +} + +char * +fz_strdup(char *s) +{ + int len = strlen(s); + char *ns = fz_malloc(len + 1); + if (ns) + strcpy(ns, s); + return ns; +} + diff --git a/base/base_rect.c b/base/base_rect.c new file mode 100644 index 00000000..18acb952 --- /dev/null +++ b/base/base_rect.c @@ -0,0 +1,75 @@ +#include <fitz.h> + +fz_rect fz_infiniterect = { 1, 1, -1, -1 }; +fz_rect fz_emptyrect = { 0, 0, 0, 0 }; + +static fz_irect infinite = { 1, 1, -1, -1 }; +static fz_irect empty = { 0, 0, 0, 0 }; + +fz_irect +fz_roundrect(fz_rect f) +{ + fz_irect i; + i.x0 = fz_floor(f.x0); + i.y0 = fz_floor(f.y0); + i.x1 = fz_ceil(f.x1); + i.y1 = fz_ceil(f.y1); + return i; +} + +fz_rect +fz_intersectrects(fz_rect a, fz_rect b) +{ + fz_rect r; + if (fz_isinfiniterect(a)) return b; + if (fz_isinfiniterect(b)) return a; + r.x0 = MAX(a.x0, b.x0); + r.y0 = MAX(a.y0, b.y0); + r.x1 = MIN(a.x1, b.x1); + r.y1 = MIN(a.y1, b.y1); + return (r.x1 < r.x0 || r.y1 < r.y0) ? fz_emptyrect : r; +} + +fz_rect +fz_mergerects(fz_rect a, fz_rect b) +{ + fz_rect r; + if (fz_isinfiniterect(a) || fz_isinfiniterect(b)) + return fz_infiniterect; + if (fz_isemptyrect(a)) return b; + if (fz_isemptyrect(b)) return a; + r.x0 = MIN(a.x0, b.x0); + r.y0 = MIN(a.y0, b.y0); + r.x1 = MAX(a.x1, b.x1); + r.y1 = MAX(a.y1, b.y1); + return r; +} + +fz_irect +fz_intersectirects(fz_irect a, fz_irect b) +{ + fz_irect r; + if (fz_isinfiniterect(a)) return b; + if (fz_isinfiniterect(b)) return a; + r.x0 = MAX(a.x0, b.x0); + r.y0 = MAX(a.y0, b.y0); + r.x1 = MIN(a.x1, b.x1); + r.y1 = MIN(a.y1, b.y1); + return (r.x1 < r.x0 || r.y1 < r.y0) ? empty : r; +} + +fz_irect +fz_mergeirects(fz_irect a, fz_irect b) +{ + fz_irect r; + if (fz_isinfiniterect(a) || fz_isinfiniterect(b)) + return infinite; + if (fz_isemptyrect(a)) return b; + if (fz_isemptyrect(b)) return a; + r.x0 = MIN(a.x0, b.x0); + r.y0 = MIN(a.y0, b.y0); + r.x1 = MAX(a.x1, b.x1); + r.y1 = MAX(a.y1, b.y1); + return r; +} + diff --git a/base/base_rune.c b/base/base_rune.c new file mode 100644 index 00000000..4aa81df3 --- /dev/null +++ b/base/base_rune.c @@ -0,0 +1,168 @@ +enum +{ + UTFmax = 3, /* maximum bytes per rune */ + Runesync = 0x80, /* cannot represent part of a UTF sequence (<) */ + Runeself = 0x80, /* rune and UTF sequences are the same (<) */ + Runeerror = 0x80 /* decoding error in UTF */ +}; + +enum +{ + Bit1 = 7, + Bitx = 6, + Bit2 = 5, + Bit3 = 4, + Bit4 = 3, + + T1 = ((1<<(Bit1+1))-1) ^ 0xFF, /* 0000 0000 */ + Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */ + T2 = ((1<<(Bit2+1))-1) ^ 0xFF, /* 1100 0000 */ + T3 = ((1<<(Bit3+1))-1) ^ 0xFF, /* 1110 0000 */ + T4 = ((1<<(Bit4+1))-1) ^ 0xFF, /* 1111 0000 */ + + Rune1 = (1<<(Bit1+0*Bitx))-1, /* 0000 0000 0111 1111 */ + Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0111 1111 1111 */ + Rune3 = (1<<(Bit3+2*Bitx))-1, /* 1111 1111 1111 1111 */ + + Maskx = (1<<Bitx)-1, /* 0011 1111 */ + Testx = Maskx ^ 0xFF, /* 1100 0000 */ + + Bad = Runeerror +}; + +int +chartorune(int *rune, char *str) +{ + int c, c1, c2; + int l; + + /* + * one character sequence + * 00000-0007F => T1 + */ + c = *(unsigned char*)str; + if(c < Tx) { + *rune = c; + return 1; + } + + /* + * two character sequence + * 0080-07FF => T2 Tx + */ + c1 = *(unsigned char*)(str+1) ^ Tx; + if(c1 & Testx) + goto bad; + if(c < T3) { + if(c < T2) + goto bad; + l = ((c << Bitx) | c1) & Rune2; + if(l <= Rune1) + goto bad; + *rune = l; + return 2; + } + + /* + * three character sequence + * 0800-FFFF => T3 Tx Tx + */ + c2 = *(unsigned char*)(str+2) ^ Tx; + if(c2 & Testx) + goto bad; + if(c < T4) { + l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3; + if(l <= Rune2) + goto bad; + *rune = l; + return 3; + } + + /* + * bad decoding + */ +bad: + *rune = Bad; + return 1; +} + +int +runetochar(char *str, int *rune) +{ + int c; + + /* + * one character sequence + * 00000-0007F => 00-7F + */ + c = *rune; + if(c <= Rune1) { + str[0] = c; + return 1; + } + + /* + * two character sequence + * 0080-07FF => T2 Tx + */ + if(c <= Rune2) { + str[0] = T2 | (c >> 1*Bitx); + str[1] = Tx | (c & Maskx); + return 2; + } + + /* + * three character sequence + * 0800-FFFF => T3 Tx Tx + */ + str[0] = T3 | (c >> 2*Bitx); + str[1] = Tx | ((c >> 1*Bitx) & Maskx); + str[2] = Tx | (c & Maskx); + return 3; +} + +int +runelen(int c) +{ + int rune; + char str[10]; + + rune = c; + return runetochar(str, &rune); +} + +int +runenlen(int *r, int nrune) +{ + int nb, c; + + nb = 0; + while(nrune--) { + c = *r++; + if(c <= Rune1) + nb++; + else + if(c <= Rune2) + nb += 2; + else + nb += 3; + } + return nb; +} + +int +fullrune(char *str, int n) +{ + int c; + + if(n > 0) { + c = *(unsigned char*)str; + if(c < Tx) + return 1; + if(n > 1) + if(c < T3 || n > 2) + return 1; + } + return 0; +} + diff --git a/base/util_getopt.c b/base/util_getopt.c new file mode 100644 index 00000000..c870e206 --- /dev/null +++ b/base/util_getopt.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 1987 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)getopt.c 4.13 (Berkeley) 2/23/91"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * get option letter from argument vector + */ +int opterr = 1, /* if error message should be printed */ + optind = 1, /* index into parent argv vector */ + optopt; /* character checked for validity */ +char *optarg; /* argument associated with option */ + +#define BADCH (int)'?' +#define EMSG "" + +int getopt(int nargc, char * const * nargv, const char *ostr) +{ + static char *place = EMSG; /* option letter processing */ + register char *oli; /* option letter list index */ + char *p; + + if (!*place) { /* update scanning pointer */ + if (optind >= nargc || *(place = nargv[optind]) != '-') { + place = EMSG; + return(EOF); + } + if (place[1] && *++place == '-') { /* found "--" */ + ++optind; + place = EMSG; + return(EOF); + } + } /* option letter okay? */ + if ((optopt = (int)*place++) == (int)':' || + !(oli = strchr(ostr, optopt))) { + /* + * if the user didn't specify '-' as an option, + * assume it means EOF. + */ + if (optopt == (int)'-') + return(EOF); + if (!*place) + ++optind; + if (opterr) { + if (!(p = strrchr(*nargv, '/'))) + p = *nargv; + else + ++p; + (void)fprintf(stderr, "%s: illegal option -- %c\n", + p, optopt); + } + return(BADCH); + } + if (*++oli != ':') { /* don't need argument */ + optarg = NULL; + if (!*place) + ++optind; + } + else { /* need an argument */ + if (*place) /* no white space */ + optarg = place; + else if (nargc <= ++optind) { /* no arg */ + place = EMSG; + if (!(p = strrchr(*nargv, '/'))) + p = *nargv; + else + ++p; + if (opterr) + (void)fprintf(stderr, + "%s: option requires an argument -- %c\n", + p, optopt); + return(BADCH); + } + else /* white space */ + optarg = nargv[optind]; + place = EMSG; + ++optind; + } + return(optopt); /* dump back option letter */ +} diff --git a/base/util_strlcat.c b/base/util_strlcat.c new file mode 100644 index 00000000..c659b73a --- /dev/null +++ b/base/util_strlcat.c @@ -0,0 +1,35 @@ +/* Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ + +#include <string.h> + +int strlcat(char *dst, const char *src, int siz) +{ + register char *d = dst; + register const char *s = src; + register int n = siz; + int dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (*d != '\0' && n-- != 0) + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return dlen + strlen(s); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return dlen + (s - src); /* count does not include NUL */ +} + diff --git a/base/util_strlcpy.c b/base/util_strlcpy.c new file mode 100644 index 00000000..73416ae1 --- /dev/null +++ b/base/util_strlcpy.c @@ -0,0 +1,32 @@ +/* Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ + +#include <string.h> + +int strlcpy(char *dst, const char *src, int siz) +{ + register char *d = dst; + register const char *s = src; + register int n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) { + do { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} + diff --git a/base/util_strsep.c b/base/util_strsep.c new file mode 100644 index 00000000..e54903ce --- /dev/null +++ b/base/util_strsep.c @@ -0,0 +1,11 @@ +#include <string.h> + +char *strsep(char **stringp, const char *delim) +{ + char *ret = *stringp; + if (ret == NULL) return NULL; + if ((*stringp = strpbrk(*stringp, delim)) != NULL) + *((*stringp)++) = '\0'; + return ret; +} + |