diff options
Diffstat (limited to 'common/compat.c')
-rw-r--r-- | common/compat.c | 458 |
1 files changed, 458 insertions, 0 deletions
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 + |