summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/Makefile.am2
-rw-r--r--common/binfile.c334
-rw-r--r--common/binfile.h110
-rw-r--r--common/compat.c458
-rw-r--r--common/compat.h177
-rw-r--r--common/repfile.c113
-rw-r--r--common/repfile.h52
-rw-r--r--common/usuals.h61
-rw-r--r--common/xstring.c104
-rw-r--r--common/xstring.h70
10 files changed, 1481 insertions, 0 deletions
diff --git a/common/Makefile.am b/common/Makefile.am
new file mode 100644
index 0000000..0686d9d
--- /dev/null
+++ b/common/Makefile.am
@@ -0,0 +1,2 @@
+EXTRA_DIST = compat.c compat.h xstring.c xstring.h usuals.h binfile.h binfile.c repfile.h repfile.c
+
diff --git a/common/binfile.c b/common/binfile.c
new file mode 100644
index 0000000..fa0a120
--- /dev/null
+++ b/common/binfile.c
@@ -0,0 +1,334 @@
+ /*
+ * AUTHOR
+ * N. Nielsen
+ *
+ * LICENSE
+ * This software is in the public domain.
+ *
+ * The software is provided "as is", without warranty of any kind,
+ * express or implied, including but not limited to the warranties
+ * of merchantability, fitness for a particular purpose, and
+ * noninfringement. In no event shall the author(s) be liable for any
+ * claim, damages, or other liability, whether in an action of
+ * contract, tort, or otherwise, arising from, out of, or in connection
+ * with the software or the use or other dealings in the software.
+ *
+ * SUPPORT
+ * Send bug reports to: <nielsen@memberwebs.com>
+ */
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+#include "binfile.h"
+
+#define BF_FILE 0x00000010
+#define BF_ERROR 0x00000040
+
+/* bfctx: ---------------------------------------------------
+ * This is the structure that becomes a BFILE
+ * to the outside world
+ */
+typedef struct _bfctx
+{
+ union
+ {
+ FILE* file; /* Valid when working with a FILE */
+ void* data; /* Valid when working with memory */
+ } d;
+ size_t cur; /* Current position */
+ size_t len; /* Size of the memory buffer */
+ int flags;
+}
+bfctx;
+
+
+/* bfWriteRaw: -----------------------------------------------
+ * Write data to appropriate buffer/file
+ */
+int bfWriteRaw(BFILE h, const void* data, size_t len)
+{
+ bfctx* ctx = (bfctx*)h;
+
+ /* file */
+ if(ctx->flags & BF_FILE)
+ {
+ len = fwrite(data, len, 1, ctx->d.file);
+ ctx->cur += len;
+ return len;
+ }
+
+ /* memory */
+ else
+ {
+ /* Check if enough space */
+ if((ctx->cur + len) > ctx->len)
+ {
+ /* If we ran out of space try and reallocate */
+ if(ctx->flags & BF_REALLOC)
+ {
+ void* old = ctx->d.data;
+
+ ctx->len = ctx->len + (((len / 1024) + 1) * 1024);
+ ctx->d.data = realloc(ctx->d.data, ctx->len);
+
+ if(!ctx->d.data)
+ free(old);
+ }
+
+ /*
+ * If there's no more space and we can't
+ * reallocate then it's an error
+ */
+ if(!ctx->d.data || !(ctx->flags & BF_REALLOC))
+ {
+ ctx->flags |= BF_ERROR;
+ return 0;
+ }
+
+ }
+
+ /* write the data in */
+ memcpy(((unsigned char*)ctx->d.data) + ctx->cur, data, len);
+ ctx->cur += len;
+ return len;
+ }
+}
+
+
+/* bfReadRaw: ------------------------------------------------------
+ * Read data from either buffer or file
+ */
+int bfReadRaw(BFILE h, void* data, size_t len)
+{
+ bfctx* ctx = (bfctx*)h;
+
+ /* file */
+ if(ctx->flags & BF_FILE)
+ {
+ len = fread(data, 1, len, ctx->d.file);
+ ctx->cur += len;
+ return len;
+ }
+
+ /* memory */
+ else
+ {
+ if((ctx->len - ctx->cur) < len)
+ len = ctx->len - ctx->cur;
+
+ memcpy(data, ((unsigned char*)ctx->d.data) + ctx->cur, len);
+ ctx->cur += len;
+ return len;
+ }
+}
+
+
+/* bfSeek: ---------------------------------------------------------
+ * Seek forward in either buffer or file
+ */
+int bfSeek(bfctx* ctx, long offset)
+{
+ /* file */
+ if(ctx->flags & BF_FILE)
+ {
+ int ret = fseek(ctx->d.file, offset, SEEK_CUR);
+ if(ret == 0)
+ ctx->cur += offset;
+ return ret;
+ }
+
+ /* memory */
+ else
+ {
+ if((long)(ctx->len - ctx->cur) < offset)
+ return 1;
+ ctx->cur += offset;
+
+ return 0;
+ }
+}
+
+
+/* bfError: -------------------------------------------------
+ * Check for errors on output
+ */
+int bfError(BFILE h)
+{
+ bfctx* ctx = (bfctx*)h;
+ if(ctx->flags & BF_FILE)
+ return ferror(ctx->d.file);
+ else
+ return ctx->flags & BF_ERROR;
+}
+
+
+/* bfStartFile: -----------------------------------------------
+ * Get a BFILE based on a FILE output
+ * file should be opened for appropriate input or output
+ */
+BFILE bfStartFile(FILE* file)
+{
+ bfctx* ctx = (bfctx*)malloc(sizeof(bfctx));
+ if(!ctx) return 0;
+ memset(ctx, 0, sizeof(bfctx));
+
+ ctx->d.file = file;
+ ctx->flags = BF_FILE;
+ return ctx;
+}
+
+/* bfStartMem: -------------------------------------------------
+ * Get a BFILE based on memory
+ * If flags have BF_REALLOC set then NULL can be passed
+ * and/or we can reallocate the buffer
+ */
+BFILE bfStartMem(void* mem, size_t len, int flags)
+{
+ bfctx* ctx = (bfctx*)malloc(sizeof(bfctx));
+ if(!ctx) return 0;
+ memset(ctx, 0, sizeof(bfctx));
+
+ ctx->len = len;
+ ctx->flags = flags;
+ ctx->flags &= ~(BF_FILE | BF_ERROR);
+ ctx->d.data = mem;
+
+ return ctx;
+}
+
+/* bfClose: -----------------------------------------------------
+ * Close a BFILE
+ * Returns either the file or memory buffer, and returns size
+ * in the len argument
+ */
+void bfClose(BFILE h)
+{
+ if(h)
+ free(h);
+}
+
+/* bfInternal: --------------------------------------------------
+ * Get the internal file handle or memory pointer for this
+ * binfile
+ */
+void* bfInternal(BFILE h)
+{
+ bfctx* ctx = (bfctx*)h;
+ if(ctx->flags & BF_FILE)
+ return ctx->d.file;
+ else
+ return ctx->d.data;
+}
+
+/* bfCount: ----------------------------------------------------
+ * Returns the number of bytes written or read to this binfile
+ */
+size_t bfCount(BFILE h)
+{
+ bfctx* ctx = (bfctx*)h;
+ return ctx->cur;
+}
+
+/* bfWriteEnd: -------------------------------------------------
+ * Puts down an end of tags marker in the binfile
+ */
+int bfWriteEnd(BFILE h)
+{
+ bfval opt;
+ int c;
+
+ opt.id = BINTYPE_END;
+ opt.len = 0;
+ opt.type = BINTYPE_END;
+ c = bfWriteRaw(h, &opt, sizeof(opt));
+
+ return bfError(h) ? 0 : c;
+}
+
+/* bfWriteValue: -----------------------------------------------
+ * Writes a tagged value to the binfile
+ */
+int bfWriteValue(BFILE h, const bfval* val, const void* data)
+{
+ int c = bfWriteRaw(h, val, sizeof(bfval));
+ c += bfWriteRaw(h, data, val->len);
+ return bfError(h) ? 0 : c;
+}
+
+/* bfReadValueInfo: --------------------------------------------
+ * Gets the next tag (without data) and returns the length
+ * of the memory required to hold it.
+ */
+int bfReadValueInfo(BFILE h, bfval* val)
+{
+ int c = bfReadRaw(h, val, sizeof(bfval));
+ return c == sizeof(bfval) && !bfError(h);
+}
+
+/* bfReadValueData: ---------------------------------------------
+ * Gets the data for a value. val should be same one returned
+ * from bfReadValueInfo
+ */
+int bfReadValueData(BFILE h, const bfval* val, void* data)
+{
+ size_t c;
+ if((c = bfReadRaw(h, data, val->len)) != val->len ||
+ bfError(h))
+ return 0;
+
+ /* Special handling for these guys */
+ switch(val->type)
+ {
+ case BINTYPE_ASCII:
+ {
+ char* str = (char*)data;
+ str[val->len] = 0;
+ }
+ break;
+
+ case BINTYPE_INT32:
+ case BINTYPE_INT16:
+ /* TODO: do endianness here */
+ break;
+ };
+
+ return c;
+}
+
+/* bfSkipValueData: ------------------------------------------------
+ * Skips the data for a tagged value
+ */
+int bfSkipValueData(BFILE h, const bfval* val)
+{
+ bfctx* ctx = (bfctx*)h;
+ return bfSeek(ctx, val->len) == 0;
+}
+
+
+/* bfWriteString: --------------------------------------------------
+ * Convenience function for writing out strings to file
+ */
+int bfWriteString(BFILE h, short id, const char* data)
+{
+ bfval val;
+ val.id = id;
+ val.type = BINTYPE_ASCII;
+ val.len = strlen(data);
+
+ return bfWriteValue(h, &val, (void*)data);
+}
+
+/* bfWriteInt: -----------------------------------------------------
+ * Convenience function for writing out 4 byte integers to file
+ */
+int bfWriteInt(BFILE h, short id, int data)
+{
+ bfval val;
+ val.id = id;
+ val.type = BINTYPE_INT32;
+ val.len = BINSIZE_INT32;
+
+ /* TODO: take care of endianess here */
+ return bfWriteValue(h, &val, &data);
+}
+
diff --git a/common/binfile.h b/common/binfile.h
new file mode 100644
index 0000000..3b86b8f
--- /dev/null
+++ b/common/binfile.h
@@ -0,0 +1,110 @@
+/*
+ * AUTHOR
+ * N. Nielsen
+ *
+ * LICENSE
+ * This software is in the public domain.
+ *
+ * The software is provided "as is", without warranty of any kind,
+ * express or implied, including but not limited to the warranties
+ * of merchantability, fitness for a particular purpose, and
+ * noninfringement. In no event shall the author(s) be liable for any
+ * claim, damages, or other liability, whether in an action of
+ * contract, tort, or otherwise, arising from, out of, or in connection
+ * with the software or the use or other dealings in the software.
+ *
+ * SUPPORT
+ * Send bug reports to: <nielsen@memberwebs.com>
+ */
+
+#ifndef __BINFILE_H__
+#define __BINFILE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _WIN32
+#pragma pack(push, ops)
+#endif
+
+#pragma pack(1)
+
+/* bfval: ----------------------------------------------------------
+ * A tagged value to be written/read from a binfile
+ */
+typedef struct _bfval
+{
+ short id; /* The tag id */
+ short type; /* The data type */
+ size_t len; /* The length in bytes */
+}
+bfval;
+
+#pragma pack()
+
+#ifdef _WIN32
+#pragma pack(pop, ops)
+#endif
+
+
+/* BFILE: --------------------------------------------------------
+ * The binfile open handle
+ */
+typedef void* BFILE;
+
+
+
+#define BINTYPE_NONE (short)0x0000
+#define BINTYPE_INT16 (short)0x0001
+#define BINTYPE_INT32 (short)0x0002
+#define BINTYPE_ASCII (short)0x0005
+#define BINTYPE_DATA (short)0x0010
+#define BINTYPE_END (short)0xFFFF
+
+#define BINSIZE_INT32 4 /* sizeof(int) */
+#define BINSIZE_INT16 2 /* sizeof(short) */
+
+#define BF_REALLOC 0x00000001
+
+/* Open a binfile based on a disk FILE */
+BFILE bfStartFile(FILE* file);
+/* Open a binfile based on memory */
+BFILE bfStartMem(void* mem, size_t len, int flags);
+
+
+/* Write raw data to a binfile at current position */
+int bfWriteRaw(BFILE h, const void* data, size_t len);
+/* Read raw data from a binfile at the current position */
+int bfReadRaw(BFILE h, void* data, size_t len);
+
+/* Check if an error occured during reading/writing */
+int bfError(BFILE h);
+
+/* Write a bfval to binfile */
+int bfWriteValue(BFILE h, const bfval* opt, const void* data);
+/* Write a string to a binfile */
+int bfWriteString(BFILE h, short id, const char* data);
+/* Write a 4 byte integer to a binfile */
+int bfWriteInt(BFILE h, short id, int data);
+/* Write the end tag marker */
+int bfWriteEnd(BFILE h);
+
+/* Read the tag information for a value */
+int bfReadValueInfo(BFILE h, bfval* opt);
+/* Read the data for a value */
+int bfReadValueData(BFILE h, const bfval* opt, void* data);
+/* Skip the data for the current value */
+int bfSkipValueData(BFILE h, const bfval* opt);
+
+size_t bfCount(BFILE h);
+void* bfInternal(BFILE h);
+
+/* Close a binfile */
+void bfClose(BFILE h);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BINFILE_H__ */
diff --git a/common/compat.c b/common/compat.c
new file mode 100644
index 0000000..ff8d527
--- /dev/null
+++ b/common/compat.c
@@ -0,0 +1,458 @@
+/*
+ * AUTHOR
+ * N. Nielsen
+ *
+ * LICENSE
+ * This software is in the public domain.
+ *
+ * The software is provided "as is", without warranty of any kind,
+ * express or implied, including but not limited to the warranties
+ * of merchantability, fitness for a particular purpose, and
+ * noninfringement. In no event shall the author(s) be liable for any
+ * claim, damages, or other liability, whether in an action of
+ * contract, tort, or otherwise, arising from, out of, or in connection
+ * with the software or the use or other dealings in the software.
+ *
+ * SUPPORT
+ * Send bug reports to: <nielsen@memberwebs.com>
+ */
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include "compat.h"
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifndef HAVE_TOLOWER
+int tolower(int c)
+{
+ if('A' <= c && c <= 'Z')
+ c += 'a' - 'A';
+ return c;
+}
+#define HAVE_TOLOWER
+#endif
+
+
+#ifndef HAVE_STRDUP
+
+#ifndef HAVE_MALLOC
+#error Need a working malloc.
+#endif
+
+char* strdup(const char* str)
+{
+ char* dup = (char*)malloc((strlen(str) + 1) * sizeof(char));
+ if(dup)
+ strcpy(dup, str);
+ return dup;
+}
+#define HAVE_STRDUP
+#endif
+
+
+#ifndef HAVE_STRNDUP
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+char* strndup(const char* str, size_t cnt)
+{
+ char* buff = malloc(sizeof(char) * (cnt + 1));
+ if(buff)
+ {
+ memcpy(buff, str, sizeof(char) * cnt);
+ buff[cnt] = 0;
+ }
+ return buff;
+}
+#endif
+
+
+#ifndef HAVE_STRCASESTR
+char* strcasestr(const char* buff, const char* str)
+{
+ const char* ptr = buff;
+
+ while (*ptr != 0x00)
+ {
+ const char* one = ptr;
+ const char* two = str;
+
+ while (tolower(*one) == tolower(*two))
+ {
+ one++;
+ two++;
+ if (*two == 0x00)
+ return (char*) ptr;
+ }
+ ptr++;
+ }
+ return NULL;
+}
+#endif
+
+#ifndef HAVE_STRLCPY
+
+#ifndef HAVE_STRNCPY
+#error neither strncpy or strlcpy found
+#endif
+
+void strlcpy(char* dest, const char* src, size_t count)
+{
+ strncpy(dest, src, count);
+ dest[count - 1] = 0;
+}
+#endif
+
+#ifndef HAVE_STRLCAT
+
+#ifndef HAVE_STRNCAT
+#error neither strncat or strlcat found
+#endif
+
+void strlcat(char* dest, const char* src, size_t count)
+{
+ strncat(dest, src, count);
+ dest[count - 1] = 0;
+}
+#endif
+
+
+#ifndef HAVE_VASPRINTF
+
+#ifndef HAVE_VSNPRINTF
+#error neither vasprintf or vsnprintf found
+#endif
+
+int vasprintf(char** ret, const char* format, va_list vl)
+{
+ size_t size = 32;
+ int c;
+ *ret = NULL;
+
+ do
+ {
+ // Double the buffer size for next time around
+ size += size;
+
+ if(*ret)
+ free(*ret);
+
+ *ret = (char*)malloc(sizeof(char) * size);
+
+ if(!(*ret))
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ c = vsnprintf(*ret, size, format, vl);
+ }
+ while(c < 0);
+
+ return c;
+}
+
+#endif
+
+
+/*
+ * We need to get a better check for this one.
+ * Basically have to make a variable __progname if none
+ * exist
+ */
+
+#ifndef HAVE_UNISTD_H
+
+char* __progname = 0;
+char prognamebuf[256];
+
+void fixprogname()
+{
+ if(__progname == 0)
+ {
+ const char* beg = strrchr(_pgmptr, '\\');
+ const char* temp = strrchr(_pgmptr, '/');
+ beg = (beg > temp) ? beg : temp;
+ beg = (beg) ? beg + 1 : _pgmptr;
+
+ temp = strrchr(_pgmptr, '.');
+ temp = (temp > beg) ? temp : _pgmptr + strlen(_pgmptr);
+
+ if((temp - beg) > 255)
+ temp = beg + 255;
+
+ strncpy(prognamebuf, beg, temp - beg);
+ prognamebuf[temp - beg] = 0;
+ __progname = prognamebuf;
+ }
+}
+#endif
+
+
+
+#ifndef HAVE_GETOPT
+
+int opterr = 1, /* if error message should be printed */
+ optind = 1, /* index into parent argv vector */
+ optopt, /* character checked for validity */
+ optreset; /* reset getopt */
+char* optarg;
+
+#define BADCH (int)'?'
+#define BADARG (int)':'
+#define EMSG ""
+
+/*
+ * getopt --
+ * Parse argc/argv argument vector.
+ */
+int getopt(int nargc, char* const* nargv, const char* ostr)
+{
+ static char* place = EMSG; /* option letter processing */
+ char *oli; /* option letter list index */
+
+ fixprogname();
+
+ if(optreset || !*place) /* update scanning pointer */
+ {
+ optreset = 0;
+ if(optind >= nargc || *(place = nargv[optind]) != '-')
+ {
+ place = EMSG;
+ return (-1);
+ }
+
+ if (place[1] && *++place == '-') /* found "--" */
+ {
+ ++optind;
+ place = EMSG;
+ return (-1);
+ }
+ } /* option letter okay? */
+
+ if ((optopt = (int)*place++) == (int)':' ||
+ !(oli = strchr(ostr, optopt)))
+ {
+ /*
+ * if the user didn't specify '-' as an option,
+ * assume it means -1.
+ */
+ if(optopt == (int)'-')
+ return (-1);
+ if(!*place)
+ ++optind;
+ if(opterr && *ostr != ':' && optopt != BADCH)
+ (void)fprintf(stderr, "%s: illegal option -- %c\n", __progname, 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 (*ostr == ':')
+ return (BADARG);
+ if(opterr)
+ (void)fprintf(stderr, "%s: option requires an argument -- %c\n", __progname, optopt);
+ return(BADCH);
+ }
+ else /* white space */
+ optarg = nargv[optind];
+
+ place = EMSG;
+ ++optind;
+ }
+ return (optopt); /* dump back option letter */
+}
+#endif
+
+
+#ifndef HAVE_ERR_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+static FILE *err_file; /* file to use for error output */
+static void (*err_exit)(int);
+
+/*
+ * This is declared to take a `void *' so that the caller is not required
+ * to include <stdio.h> first. However, it is really a `FILE *', and the
+ * manual page documents it as such.
+ */
+void err_set_file(void *fp)
+{
+ if (fp)
+ err_file = fp;
+ else
+ err_file = stderr;
+}
+
+void err_set_exit(void (*ef)(int))
+{
+ err_exit = ef;
+}
+
+void err(int eval, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ verrc(eval, errno, fmt, ap);
+ va_end(ap);
+}
+
+void verr(int eval, const char *fmt, va_list ap)
+{
+ verrc(eval, errno, fmt, ap);
+}
+
+void errc(int eval, int code, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ verrc(eval, code, fmt, ap);
+ va_end(ap);
+}
+
+void verrc(int eval, int code, const char *fmt, va_list ap)
+{
+ fixprogname();
+ if (err_file == 0)
+ err_set_file((FILE *)0);
+ fprintf(err_file, "%s: ", __progname);
+ if (fmt != NULL) {
+ vfprintf(err_file, fmt, ap);
+ fprintf(err_file, ": ");
+ }
+ fprintf(err_file, "%s\n", strerror(code));
+ if (err_exit)
+ err_exit(eval);
+ exit(eval);
+}
+
+void errx(int eval, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ verrx(eval, fmt, ap);
+ va_end(ap);
+}
+
+void verrx(int eval, const char *fmt, va_list ap)
+{
+ fixprogname();
+ if (err_file == 0)
+ err_set_file((FILE *)0);
+ fprintf(err_file, "%s: ", __progname);
+ if (fmt != NULL)
+ vfprintf(err_file, fmt, ap);
+ fprintf(err_file, "\n");
+ if (err_exit)
+ err_exit(eval);
+ exit(eval);
+}
+
+void warn(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vwarnc(errno, fmt, ap);
+ va_end(ap);
+}
+
+void vwarn(const char *fmt, va_list ap)
+{
+ vwarnc(errno, fmt, ap);
+}
+
+void warnc(int code, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vwarnc(code, fmt, ap);
+ va_end(ap);
+}
+
+void vwarnc(int code, const char *fmt, va_list ap)
+{
+ fixprogname();
+ if (err_file == 0)
+ err_set_file((FILE *)0);
+ fprintf(err_file, "%s: ", __progname);
+ if (fmt != NULL)
+ {
+ vfprintf(err_file, fmt, ap);
+ fprintf(err_file, ": ");
+ }
+ fprintf(err_file, "%s\n", strerror(code));
+}
+
+void warnx(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vwarnx(fmt, ap);
+ va_end(ap);
+}
+
+void vwarnx(const char *fmt, va_list ap)
+{
+ fixprogname();
+ if(err_file == 0)
+ err_set_file((FILE*)0);
+ fprintf(err_file, "%s: ", __progname);
+ if(fmt != NULL)
+ vfprintf(err_file, fmt, ap);
+ fprintf(err_file, "\n");
+}
+
+#endif
+
+
+
+#ifndef HAVE_STRLWR
+
+char* strlwr(char *string)
+{
+ char * cp;
+ for (cp=string; *cp; ++cp)
+ {
+ if('A' <= *cp && *cp <= 'Z')
+ *cp += 'a' - 'A';
+ }
+ return(string);
+}
+
+#endif
+
+
+
+#ifndef HAVE_REALLOCF
+
+void* reallocf(void* ptr, size_t size)
+{
+ void* ret = realloc(ptr, size);
+
+ if(!ret && size)
+ free(ptr);
+
+ return ret;
+}
+
+#endif
+
diff --git a/common/compat.h b/common/compat.h
new file mode 100644
index 0000000..09934db
--- /dev/null
+++ b/common/compat.h
@@ -0,0 +1,177 @@
+/*
+ * AUTHOR
+ * N. Nielsen
+ *
+ * LICENSE
+ * This software is in the public domain.
+ *
+ * The software is provided "as is", without warranty of any kind,
+ * express or implied, including but not limited to the warranties
+ * of merchantability, fitness for a particular purpose, and
+ * noninfringement. In no event shall the author(s) be liable for any
+ * claim, damages, or other liability, whether in an action of
+ * contract, tort, or otherwise, arising from, out of, or in connection
+ * with the software or the use or other dealings in the software.
+ *
+ * SUPPORT
+ * Send bug reports to: <nielsen@memberwebs.com>
+ */
+
+#ifndef _COMPAT_H_
+#define _COMPAT_H_
+
+/* Force use of win32 configuration if compiling there */
+#ifdef _WIN32
+#include "../config.win32.h"
+#else
+#ifdef HAVE_CONFIG_H
+#include "../config.h"
+#endif
+#endif
+
+#ifndef HAVE_STDARG_H
+#error ERROR: Must have a working <stdarg.h> header
+#else
+#include <stdarg.h>
+#endif
+
+
+#ifndef HAVE_STAT
+#ifdef _WIN32
+#define S_IFDIR _S_IFDIR
+#define HAVE_STAT
+#else
+#error ERROR: Must have a working 'stat' function
+#endif
+#endif
+
+#ifndef HAVE_GETCWD
+#ifdef _WIN32
+#include <direct.h>
+#define getcwd _getcwd
+#define HAVE_GETCWD
+#else
+#error ERROR: Must have a working 'getcwd' function
+#endif
+#endif
+
+#ifndef HAVE_CHDIR
+#ifdef _WIN32
+#include <direct.h>
+#define chdir _chdir
+#define HAVE_CHDIR
+#else
+#error ERROR: Must have a working 'chdir' function
+#endif
+#endif
+
+#ifndef HAVE_TOLOWER
+int tolower(int c);
+#endif
+
+#ifndef HAVE_STRDUP
+char* strdup(const char* str);
+#endif
+
+#ifndef HAVE_STRNDUP
+char* strndup(const char* str, size_t cnt);
+#endif
+
+#ifndef HAVE_STRCASESTR
+char* strcasestr(const char* big, const char* little);
+#endif
+
+#ifndef HAVE_STRCASECMP
+#ifdef HAVE_STRICMP
+#define strcasecmp stricmp
+#else
+#error ERROR: Must have either 'strcasecmp' or 'stricmp'
+#endif
+#endif
+
+#ifndef HAVE_STRCASECMP
+#ifdef HAVE_STRICMP
+#define strncasecmp strnicmp
+#else
+#error ERROR: Must have either 'strncasecmp' or 'strnicmp'
+#endif
+#endif
+
+
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+#ifndef __cplusplus
+typedef unsigned char bool;
+#define false 0x00
+#define true 0x01
+#endif
+
+#ifndef HAVE_BYTE
+typedef unsigned char byte;
+#define HAVE_BYTE
+#endif
+
+#ifndef HAVE_UINT
+typedef unsigned int uint;
+#define HAVE_UINT
+#endif
+
+#ifndef HAVE_STRLCPY
+void strlcpy(char* dest, const char* src, size_t count);
+#endif
+
+#ifndef HAVE_STRLCAT
+void strlcat(char* dest, const char* src, size_t count);
+#endif
+
+#ifndef HAVE_VSNPRINTF
+
+#ifdef _WIN32
+#define vsnprintf _vsnprintf
+#define HAVE_VSNPRINTF
+#else
+#ifndef HAVE_VASPRINTF
+#error ERROR: Must have a working 'vsnprintf' or 'vasprintf' function
+#endif
+#endif
+#endif
+
+#ifndef HAVE_VASPRINTF
+int vasprintf(char** ret, const char* format, va_list vl);
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifndef HAVE_GETOPT
+extern char* optarg;
+extern int optind, opterr, optopt;
+int getopt(int nargc, char* const* nargv, const char* ostr);
+#endif
+
+#ifndef HAVE_ERR_H
+#include <stdarg.h>
+void err_set_file(void *fp);
+void err_set_exit(void (*ef)(int));
+void err(int eval, const char *fmt, ...);
+void verr(int eval, const char *fmt, va_list ap);
+void errc(int eval, int code, const char *fmt, ...);
+void verrc(int eval, int code, const char *fmt, va_list ap);
+void errx(int eval, const char *fmt, ...);
+void verrx(int eval, const char *fmt, va_list ap);
+void warn(const char *fmt, ...);
+void vwarn(const char *fmt, va_list ap);
+void warnc(int code, const char *fmt, ...);
+void vwarnc(int code, const char *fmt, va_list ap);
+void warnx(const char *fmt, ...);
+void vwarnx(const char *fmt, va_list ap);
+#endif
+
+#ifndef HAVE_REALLOCF
+void* reallocf(void* ptr, size_t size);
+#endif
+
+#endif \ No newline at end of file
diff --git a/common/repfile.c b/common/repfile.c
new file mode 100644
index 0000000..eec6ca2
--- /dev/null
+++ b/common/repfile.c
@@ -0,0 +1,113 @@
+/*
+ * AUTHOR
+ * N. Nielsen
+ *
+ * LICENSE
+ * This software is in the public domain.
+ *
+ * The software is provided "as is", without warranty of any kind,
+ * express or implied, including but not limited to the warranties
+ * of merchantability, fitness for a particular purpose, and
+ * noninfringement. In no event shall the author(s) be liable for any
+ * claim, damages, or other liability, whether in an action of
+ * contract, tort, or otherwise, arising from, out of, or in connection
+ * with the software or the use or other dealings in the software.
+ *
+ * SUPPORT
+ * Send bug reports to: <nielsen@memberwebs.com>
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "common/usuals.h"
+#include "common/compat.h"
+#include "common/binfile.h"
+#include "common/repfile.h"
+
+/* errmsg: -----------------------------------------------------------
+ * Display an rlib error on the console
+ */
+int errmsg(int ret, r_script* script)
+{
+ const char* msg;
+
+ switch(ret)
+ {
+ case R_NOMEM:
+ msg = "out of memory";
+ break;
+ case R_SYNTAX:
+ msg = "syntax error:";
+ break;
+ case R_REGEXP:
+ msg = "reg expression error:";
+ break;
+ case R_LOOP:
+ msg = "an endless loop was encountered ";
+ break;
+ case R_USER:
+ msg = "stop: ";
+ break;
+ case R_IOERR:
+ msg = "read or write error";
+ break;
+ case R_INVARG:
+ ASSERT(0 && "This error should be taken care of by programmer");
+ msg = "internal programmer error";
+ break;
+ default:
+ msg = "unknown error";
+ break;
+ }
+
+ if(script && script->error)
+ {
+ if(script->errline > 0)
+ warnx("%s %s (at line %d)", msg, script->error, script->errline);
+ else
+ warnx("%s %s", msg, script->error);
+ }
+ else
+ {
+ warnx(msg);
+ }
+
+ return ret;
+}
+
+/* repscriptheader: -------------------------------------------------
+ * The top of every compiled rep file has this signature
+ */
+typedef struct _repscriptheader
+{
+ uint sig; /* 'rep0' */
+ uint version; /* Note this is the file version */
+}
+repscriptheader;
+
+const uint kReplSig = '0per';
+const uint kReplVer = 0x00023100;
+
+/* repfWriteHeader: -------------------------------------------------
+ * Write out a valid header
+ */
+bool repfWriteHeader(BFILE h)
+{
+ repscriptheader head;
+ head.sig = kReplSig;
+ head.version = kReplVer;
+
+ bfWriteRaw(h, &head, sizeof(head));
+ return !bfError(h);
+}
+
+/* repfReadHeader: --------------------------------------------------
+ * Read and validate rep file header
+ */
+bool repfReadHeader(BFILE h)
+{
+ repscriptheader head;
+ memset(&head, 0, sizeof(head));
+ bfReadRaw(h, &head, sizeof(head));
+ return head.sig == kReplSig && head.version == kReplVer;
+}
diff --git a/common/repfile.h b/common/repfile.h
new file mode 100644
index 0000000..5d0ff95
--- /dev/null
+++ b/common/repfile.h
@@ -0,0 +1,52 @@
+/*
+ * AUTHOR
+ * N. Nielsen
+ *
+ * LICENSE
+ * This software is in the public domain.
+ *
+ * The software is provided "as is", without warranty of any kind,
+ * express or implied, including but not limited to the warranties
+ * of merchantability, fitness for a particular purpose, and
+ * noninfringement. In no event shall the author(s) be liable for any
+ * claim, damages, or other liability, whether in an action of
+ * contract, tort, or otherwise, arising from, out of, or in connection
+ * with the software or the use or other dealings in the software.
+ *
+ * SUPPORT
+ * Send bug reports to: <nielsen@memberwebs.com>
+ */
+
+#ifndef __REPL_H__
+#define __REPL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include "lib/rlib.h"
+#include "common/usuals.h"
+#include "common/compat.h"
+#include "common/binfile.h"
+
+/* Write rlib errors to console */
+int errmsg(int ret, r_script* script);
+
+/* Read and validate a rep compiled script header */
+bool repfReadHeader(BFILE h);
+/* Write a valid rep compiled script header */
+bool repfWriteHeader(BFILE h);
+
+/* Some binfile tags */
+#define REPVAL_BUFSIZE 0x0008
+#define REPVAL_PARSEMODE 0x0009
+#define REPVAL_BINARYMODE 0x000A
+#define REPVAL_SCRIPT 0x0020
+#define REPVAL_VERSION 0x0030
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __REPL_H__ */
diff --git a/common/usuals.h b/common/usuals.h
new file mode 100644
index 0000000..7317f99
--- /dev/null
+++ b/common/usuals.h
@@ -0,0 +1,61 @@
+/*
+ * AUTHOR
+ * N. Nielsen
+ *
+ * LICENSE
+ * This software is in the public domain.
+ *
+ * The software is provided "as is", without warranty of any kind,
+ * express or implied, including but not limited to the warranties
+ * of merchantability, fitness for a particular purpose, and
+ * noninfringement. In no event shall the author(s) be liable for any
+ * claim, damages, or other liability, whether in an action of
+ * contract, tort, or otherwise, arising from, out of, or in connection
+ * with the software or the use or other dealings in the software.
+ *
+ * SUPPORT
+ * Send bug reports to: <nielsen@memberwebs.com>
+ */
+
+#ifndef __USUALS_H__20000613
+#define __USUALS_H__20000613
+
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#define zero(v) (memset(&(v), 0, sizeof((v))))
+#define countof(a) (sizeof(a) / sizeof(a[0]))
+
+#ifndef max
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef ASSERT
+#include <assert.h>
+#define ASSERT assert
+#endif
+
+#ifndef ASSERT_PTR
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#define ASSERT_PTR_LEN(p, len) ASSERT(!(IsBadReadPtr((p), len) || IsBadWritePtr((p), len)))
+#else
+#define ASSERT_PTR_LEN(p, len) ASSERT((p) != 0)
+#endif
+
+#define ASSERT_PTR(p) ASSERT_PTR_LEN(p, sizeof(*(p)))
+
+#endif
+
+
+#endif //__USUALS_H__20000613 \ No newline at end of file
diff --git a/common/xstring.c b/common/xstring.c
new file mode 100644
index 0000000..31a363f
--- /dev/null
+++ b/common/xstring.c
@@ -0,0 +1,104 @@
+/*
+ * AUTHOR
+ * N. Nielsen
+ *
+ * LICENSE
+ * This software is in the public domain.
+ *
+ * The software is provided "as is", without warranty of any kind,
+ * express or implied, including but not limited to the warranties
+ * of merchantability, fitness for a particular purpose, and
+ * noninfringement. In no event shall the author(s) be liable for any
+ * claim, damages, or other liability, whether in an action of
+ * contract, tort, or otherwise, arising from, out of, or in connection
+ * with the software or the use or other dealings in the software.
+ *
+ * SUPPORT
+ * Send bug reports to: <nielsen@memberwebs.com>
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "compat.h"
+#include "xstring.h"
+
+
+/* memins: -------------------------------------------------------------
+ * Insert bytes at location
+ */
+void memins(void* buff, size_t cbuff, const void* ins, size_t cins)
+{
+ memmove((unsigned char*)buff + cins, buff, cbuff);
+ memcpy(buff, ins, cins);
+}
+
+
+/* memrep: ------------------------------------------------------------
+ * Replace a number of bytes at a certain location with yet
+ * another number of bytes
+ */
+void* memrep(void* buff, size_t len, size_t cold, const void* ins, size_t cnew)
+{
+ memmove((unsigned char*)buff + cnew, (unsigned char*)buff + cold, len - cold);
+ memcpy(buff, ins, cnew);
+ return (unsigned char*)buff + cnew;
+}
+
+
+/* starlen: -----------------------------------------------------------
+ * Returns the length of a null terminated string array
+ */
+size_t starlen(const char* array)
+{
+ size_t cnt = 0;
+ while(array[0] || array[1])
+ {
+ array += strlen(array);
+ cnt++;
+ }
+
+ return cnt;
+}
+
+
+/* starend: -----------------------------------------------------------
+ * Gets the end of a string array
+ */
+char* starend(const char* array)
+{
+ while(array[0])
+ array += strlen(array) + 1;
+
+ return (char*)array;
+}
+
+
+/* starnadd: ----------------------------------------------------------
+ * Add a value to a string array
+ */
+char* starnadd(char** parray, const char* str, size_t len)
+{
+ char* last = starend(*parray);
+ if(!strrsrv(*parray, (last - *parray) + len + 2))
+ return NULL;
+
+ // It's possible we were relocated
+ last = starend(*parray);
+
+ strncpy(last, str, len);
+ last += len;
+ last[0] = last[1] = 0;
+ return last;
+}
+
+
+/* starnext: ----------------------------------------------------------
+ * Get the next value in a string array
+ */
+const char* starnext(const char* prev)
+{
+ prev += strlen(prev) + 1;
+ return prev[0] ? prev : NULL;
+}
+
diff --git a/common/xstring.h b/common/xstring.h
new file mode 100644
index 0000000..3be4116
--- /dev/null
+++ b/common/xstring.h
@@ -0,0 +1,70 @@
+/*
+ * AUTHOR
+ * N. Nielsen
+ *
+ * VERSION
+ * 2.1.2b
+ *
+ * LICENSE
+ * This software is in the public domain.
+ *
+ * The software is provided "as is", without warranty of any kind,
+ * express or implied, including but not limited to the warranties
+ * of merchantability, fitness for a particular purpose, and
+ * noninfringement. In no event shall the author(s) be liable for any
+ * claim, damages, or other liability, whether in an action of
+ * contract, tort, or otherwise, arising from, out of, or in connection
+ * with the software or the use or other dealings in the software.
+ *
+ * SUPPORT
+ * Send bug reports to: <nielsen@memberwebs.com>
+ */
+
+#ifndef __XSTRING_H__
+#define __XSTRING_H__
+
+#include <stdarg.h>
+
+/* Insert bytes at a memory location */
+void memins(void* buff, size_t cbuff, const void* ins, size_t cins);
+
+/* Insert string into a string */
+#define strins(buff, ins) \
+ memins((byte*)buff, strlen(buff) + 1, (byte*)ins, strlen(ins))
+
+/* Replace a number of bytes with other bytes at a memory location */
+void* memrep(void* buff, size_t len, size_t cold, const void* ins, size_t cnew);
+
+/* Replace a number of chars with a string */
+#define strrep(s, cold, ins) \
+ (char*)memrep(s, sizeof(char) * (strlen(s) + 1), cold, ins, strlen(ins))
+#define strnrep(s, cold, ins, cins) \
+ (char*)memrep(s, sizeof(char) * (strlen(s) + 1), cold, ins, cins)
+
+/* Reserve memory in a string. (NOTE: buff must be allocated with malloc) */
+#define strrsrv(buff, cnt) \
+ (buff = (char*)realloc(buff, sizeof(char) * ((cnt) + 1)))
+
+
+
+/* Get the length of a null terminated string array */
+size_t starlen(const char* array);
+
+/* Get the end of a null terminated string array */
+char* starend(const char* array);
+
+/* Add a string to the end of a null terminated string array */
+char* starnadd(char** parray, const char* str, size_t len);
+#define staradd(parray, str) \
+ starnadd(parray, str, strlen(str))
+
+/* Get next value in a null terminated string array */
+const char* starnext(const char* prev);
+
+/* Clear a null terminated string array */
+#define starclr(arr) \
+ (arr[0] = arr[1] = 0)
+
+
+
+#endif //__XSTRING_H__ \ No newline at end of file