aboutsummaryrefslogtreecommitdiffstats
path: root/sdk/other
diff options
context:
space:
mode:
Diffstat (limited to 'sdk/other')
-rw-r--r--sdk/other/Makefile.in22
-rw-r--r--sdk/other/atob.c47
-rw-r--r--sdk/other/bcd.c125
-rw-r--r--sdk/other/bind.conf1
-rw-r--r--sdk/other/ccount.c45
-rw-r--r--sdk/other/confdir.c105
-rw-r--r--sdk/other/config.c437
-rw-r--r--sdk/other/config.h67
-rw-r--r--sdk/other/env.c36
-rw-r--r--sdk/other/env.h31
-rw-r--r--sdk/other/expand.c36
-rw-r--r--sdk/other/fatal.c23
-rw-r--r--sdk/other/filename.c74
-rw-r--r--sdk/other/files.h52
-rw-r--r--sdk/other/fncat.c30
-rw-r--r--sdk/other/getargv.c57
-rw-r--r--sdk/other/hex.c44
-rw-r--r--sdk/other/isftype.c22
-rw-r--r--sdk/other/make.conf2
-rw-r--r--sdk/other/memalloc.c35
-rw-r--r--sdk/other/memdup.c22
-rw-r--r--sdk/other/memfree.c38
-rw-r--r--sdk/other/memory.h103
-rw-r--r--sdk/other/mempool.c49
-rw-r--r--sdk/other/memrelease.c43
-rw-r--r--sdk/other/memreq.c59
-rw-r--r--sdk/other/picture.c112
-rw-r--r--sdk/other/search.c46
-rw-r--r--sdk/other/strblank.c24
-rw-r--r--sdk/other/strcopy.c61
-rw-r--r--sdk/other/strcvt.h56
-rw-r--r--sdk/other/strdiff.c24
-rw-r--r--sdk/other/string.h65
-rw-r--r--sdk/other/strint.c51
-rw-r--r--sdk/other/strpos.c46
-rw-r--r--sdk/other/strreq.c39
-rw-r--r--sdk/other/strtrim.c45
-rw-r--r--sdk/other/token.c50
-rw-r--r--sdk/other/xval.c28
39 files changed, 2252 insertions, 0 deletions
diff --git a/sdk/other/Makefile.in b/sdk/other/Makefile.in
new file mode 100644
index 0000000..17dd18a
--- /dev/null
+++ b/sdk/other/Makefile.in
@@ -0,0 +1,22 @@
+#
+# Template to build our "other" object modules(libother.a)
+# $Id: Makefile.in 1.2 Wed, 19 Mar 1997 12:44:53 -0500 dyfet $
+# Copyright (c) 1997 by Tycho Softworks.
+#
+
+OBJS = memalloc.o memdup.o memfree.o mempool.o memrelease.o \
+ memreq.o config.o confdir.o bcd.o env.o atob.o strint.o \
+ expand.o picture.o xval.o hex.o strcopy.o strdiff.o \
+ strblank.o strpos.o strreq.o strtrim.o ccount.o filename.o \
+ isftype.o getargv.o search.o token.o fatal.o fncat.o
+
+.c.o:
+ $(CC) $(CFLAGS) $(OPTIMIZE) -I.. -o $@ -c $<
+ $(AR) r ../lib/libother.a $@
+
+all: $(OBJS)
+ ranlib ../lib/libother.a
+
+clean:
+ rm *.o
+
diff --git a/sdk/other/atob.c b/sdk/other/atob.c
new file mode 100644
index 0000000..1535f7a
--- /dev/null
+++ b/sdk/other/atob.c
@@ -0,0 +1,47 @@
+/*
+ * Convert ASCII text into binary value.
+ * $Id: atob.c 1.2 Wed, 19 Mar 1997 12:44:53 -0500 dyfet $
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and use, see product license.
+ *
+ * Functions:
+ * atob() - convert null terminated ASCII string to boolean value.
+ */
+
+#include <other/strcvt.h>
+
+/*
+ * Convert null terminated ASCII string to boolean value.
+ *
+ * Abstract:
+ * The input string can be numeric; such as "0" or "1", or alpha;
+ * such as "T" for true, "F" for false, or "Y" or "N". Only the
+ * first character of the string is examined. Upper/lower case is
+ * ignored.
+ *
+ * Parameters:
+ * str - null terminated ASCII string.
+ *
+ * Returns:
+ * logical value of input string.
+ *
+ * Exceptions:
+ * Any unrecognized string value, or a NULL string, return FALSE.
+ */
+
+bool atob(const char *str)
+{
+ if(!str)
+ return FALSE;
+
+ switch(*str)
+ {
+ case '0':
+ case 'f':
+ case 'F':
+ case 'n':
+ case 'N':
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/sdk/other/bcd.c b/sdk/other/bcd.c
new file mode 100644
index 0000000..3bd6144
--- /dev/null
+++ b/sdk/other/bcd.c
@@ -0,0 +1,125 @@
+/*
+ * Convert ASCII numbers to or from BCD representations.
+ * $Id: bcd.c 1.2 Wed, 19 Mar 1997 12:44:53 -0500 dyfet $
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For condititions of distribution and use, see product license.
+ *
+ * Abstract:
+ * BCD is a format for storing packed decimal data within a nibble.
+ * We assume "big endian" BCD, in that the high nibble contains the
+ * first digit within a byte. Any unused digits are filled with the
+ * nibble value of $F. This module provides the services needed to
+ * convert BCD data to and from ASCII strings.
+ *
+ * Functions:
+ * str2bcd() - convert ASCII string to packed bcd.
+ * bcd2str() - convert packed bcd to ASCII string.
+ */
+
+#include <other/strcvt.h>
+
+/*
+ * Convert null terminated ASCII string to packed bcd data.
+ *
+ * Abstract:
+ * An ASCII input string is converted to binary packed decimal
+ * data. Any unused digits are filled with $f. The size specified
+ * for digits is filled, either with available digits from the input
+ * string, or with $f nibbles once no more digits are available.
+ *
+ * Paramaters:
+ * bcd - pointer to start of bcd data to store.
+ * str - null terminated input string.
+ * max - maximum number of digits in bcd data.
+ *
+ * Returns:
+ * pointer to first non-BCD digit in input string.
+ *
+ * Exceptions:
+ * If NULL input string, returns NULL. If more digits exist in
+ * the input string than are available in bcd storage (data
+ * overflow), the remaining digits are ignored.
+ */
+
+char *str2bcd(uchar *bcd, char *str, int max)
+{
+ uchar packed = 0xff;
+ bool low = FALSE;
+
+ if(!str)
+ return NULL;
+
+ while(isdigit(*str))
+ {
+ packed = packed / 16;
+ packed |= ((*(str++) - '0') * 16);
+ if(low)
+ {
+ *(bcd++) = packed;
+ packed = 0xff;
+ if(!--max)
+ return str;
+
+ low = FALSE;
+ }
+ else
+ low = TRUE;
+ }
+ if(low)
+ {
+ *(bcd++) = packed;
+ --max;
+ }
+ while(max--)
+ *(bcd++) = 0xff;
+
+ return str;
+}
+
+/*
+ * Convert binary coded data to ASCII text.
+ *
+ * Abstract:
+ * A block of bcd data of up to a specified length is read, each
+ * digit being converted to an ASCII character code. If a $f is
+ * found before 'len' digits are examined, then the program
+ * completes with a shorter number.
+ *
+ * Paramaters:
+ * str - start of output string to receive converted data.
+ * bcd - bcd data input.
+ * len - maximum number of bcd digits.
+ *
+ * Return:
+ * pointer to next available bcd number in memory (or past end of
+ * bcd data block). The output string (str) is also given a null
+ * terminating byte.
+ *
+ * Exceptions:
+ * A NULL bcd pointer returns a NULL string.
+ */
+
+uchar *bcd2str(char *str, uchar *bcd, int len)
+{
+ uchar nib1, nib2;
+ if(!bcd)
+ return NULL;
+
+ while(len--)
+ {
+ nib1 = *bcd / 16;
+ nib2 = *bcd % 16;
+ if(nib1 < 16)
+ *(str++) = nib1 + '0';
+ else
+ break;
+ if(nib2 < 16)
+ *(str++) = nib2 + '0';
+ else
+ break;
+ ++bcd;
+ }
+ *str = 0;
+ return bcd;
+}
+
diff --git a/sdk/other/bind.conf b/sdk/other/bind.conf
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/sdk/other/bind.conf
@@ -0,0 +1 @@
+
diff --git a/sdk/other/ccount.c b/sdk/other/ccount.c
new file mode 100644
index 0000000..ec53a98
--- /dev/null
+++ b/sdk/other/ccount.c
@@ -0,0 +1,45 @@
+/*
+ * Count character occurances in string.
+ * $Id: ccount.c 1.2 Wed, 19 Mar 1997 12:44:53 -0500 dyfet $
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and use see product license.
+ *
+ * Functions:
+ * ccount() - count characters in string.
+ */
+
+#include <other/string.h>
+
+/*
+ * Count character occurances in ASCII string.
+ *
+ * Abstract:
+ * A list of possible characters to look for is passed to ccount,
+ * along with the null terminated ASCII string to look for those
+ * characters within.
+ *
+ * Parameters:
+ * str - string to examine and count occurances in.
+ * list - list (null terminated) of characters to search for.
+ *
+ * Exceptions:
+ * Either a NULL list or string is considered to hold no found
+ * characters (returns 0).
+ */
+
+int ccount(const char *str, const char *list)
+{
+ int count = 0;
+
+ if(!str || !list)
+ return 0;
+
+ while(NULL != (str = strpbrk(str, list)))
+ {
+ ++count;
+ ++str;
+ }
+ return count;
+}
+
+
diff --git a/sdk/other/confdir.c b/sdk/other/confdir.c
new file mode 100644
index 0000000..cabc475
--- /dev/null
+++ b/sdk/other/confdir.c
@@ -0,0 +1,105 @@
+/*
+ * Routines to access directory of section names in a config file.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and use see product license.
+ *
+ * Abstract:
+ * These routines may be used to scan the 'directory' of [] section
+ * names within a config file, much like the MS-DOS find_first() and
+ * find_next() directory routines.
+ *
+ * Functions:
+ * this_config() - internal routine to return section name.
+ * first_config() - goto first named [] section within the config file.
+ * next_config() - skip to the next named [] section.
+ */
+
+#include <other/config.h>
+#include <other/string.h>
+#include <other/env.h>
+
+#ifndef LBUF
+#define LBUF 1024
+#endif
+
+/*
+ * Internal program to support parsing of found section name.
+ */
+
+static char *this_config(CONFIG *cfg)
+{
+ char *p;
+
+ if(feof(cfg->cfg_fp))
+ return NULL;
+
+ if(cfg->cfg_lbuf[0] != '[')
+ return NULL;
+
+ cfg->cfg_flag = TRUE;
+ p = strtok(cfg->cfg_lbuf, "[]\n\r");
+ return p;
+}
+
+/*
+ * Automatically seek the very first [] section within a config file.
+ *
+ * Paramaters:
+ * cfg - config object pointer.
+ *
+ * Returns:
+ * Name string of first [] name in config file.
+ *
+ * Exceptions:
+ * If no [] section in config file, NULL cfg pointer, or file
+ * error, returns NULL.
+ */
+
+char *first_config(CONFIG *cfg)
+{
+ if(!cfg)
+ return NULL;
+
+ fseek(cfg->cfg_fp, 0l, SEEK_SET);
+ return next_config(cfg);
+}
+
+/*
+ * Skip to the next named [] section within a config file.
+ *
+ * Paramaters:
+ * cfg - config object pointer.
+ *
+ * Returns:
+ * Name string of next named [] section in config file.
+ *
+ * Exceptions:
+ * Returns NULL if cfg invalid or end of file reached.
+ *
+ */
+
+char *next_config(CONFIG *cfg)
+{
+ if(!cfg)
+ return NULL;
+
+ if(feof(cfg->cfg_fp))
+ return NULL;
+
+ for(;;)
+ {
+ fgets(cfg->cfg_lbuf, LBUF - 1, cfg->cfg_fp);
+ if(feof(cfg->cfg_fp))
+ return NULL;
+
+ if(cfg->cfg_lbuf[0] == '[')
+ return this_config(cfg);
+ }
+}
+
+
+
+
+
+
diff --git a/sdk/other/config.c b/sdk/other/config.c
new file mode 100644
index 0000000..e274b85
--- /dev/null
+++ b/sdk/other/config.c
@@ -0,0 +1,437 @@
+/*
+ * Routines to access and parse standard text config files.
+ * $Id: config.c 1.2 Wed, 19 Mar 1997 12:44:53 -0500 dyfet $
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and use see product license.
+ *
+ * Abstract:
+ * These routines are used to open and parse human readable '.conf'
+ * files, such as those which may be stored in the /etc directory.
+ * The .conf file is parsed as a sectioned text file, with the name
+ * for each logical section appearing in []'s. Entries within each
+ * section are typically in the format 'keyword = value', though
+ * there are exceptions for multi-line fixed size lists, in
+ * the form 'keyword = { list }', and repeated lines. Comments may
+ * also appear within .conf files.
+ *
+ * Functions:
+ * sys_config() - find and open a /etc or /etc/prior .conf file.
+ * open_config() - open any text file as a config file.
+ * read_config() - read a keyword = value pair from current section.
+ * seek_config() - seek a named [] section within the config file.
+ * get_config() - tests current input for a specified keyword.
+ * usr_config() - user specific resource config file.
+ */
+
+#include <other/config.h>
+#include <other/strcvt.h>
+#include <other/string.h>
+#include <other/env.h>
+#include <std/process.h>
+
+/*
+ * When searching for 'system' .conf files, which are normally held in
+ * /etc, also search in /etc/prior. This is used so that a human
+ * readable .conf file can momentarily be moved into '/etc/prior' and
+ * still be usable while a GUI system management program is in the middle
+ * building a new .conf file.
+ */
+
+#ifndef CFGPATH
+#define CFGPATH "/etc:/etc/prior"
+#endif
+
+/*
+ * Maximum working space for single or multi-line input records being
+ * parsed.
+ */
+
+#ifndef LBUF
+#define LBUF 1024
+#endif
+
+#ifndef SUFFIX
+#define SUFFIX ".conf"
+#endif
+
+/*
+ * Open a system .conf file, as found in the system config directories.
+ *
+ * Abstract:
+ * This function finds a .conf file in either the /etc or /etc/prior
+ * directory. /etc/prior is searched if the current .conf file is
+ * not found (in /etc), as may happen if it is in the middle of
+ * being re-built by a management application. This provides an
+ * initial function which may be used to open most .conf files.
+ *
+ * Paramaters:
+ * cfg_name - 'base' filename of system .conf file to open.
+ *
+ * Returns:
+ * pointer to active CONFIG object for specified filename.
+ *
+ * Exceptions:
+ * If the file is not found, a NULL pointer is returned.
+ */
+
+CONFIG *sys_config(const char *cfg_name)
+{
+ char cfgname[PATH_MAX + 1];
+
+ strcpy(cfgname, cfg_name);
+ strcat(cfgname, SUFFIX);
+ return open_config(search(CFGPATH, cfgname));
+}
+
+/*
+ * Open any specified filename as a .conf file.
+ *
+ * Abstract:
+ * This function opens the specified file as a 'config' file for use
+ * in config file parsing routines. Any filename may be specified
+ * and opened as a config file with this routine.
+ *
+ * Paramaters:
+ * config_name - full pathname of a .conf file to open.
+ *
+ * Returns:
+ * pointer to a newly allocated CONFIG parsing object for the
+ * specified filename.
+ *
+ * Exceptions:
+ * If the file is not found, a NULL pointer is returned.
+ */
+
+
+CONFIG *open_config(const char *config_name)
+{
+ CONFIG *new;
+ char *env;
+
+ if(NULL == (new = (CONFIG *)malloc(sizeof(CONFIG) + LBUF)))
+ return NULL;
+
+ if(NULL == (new->cfg_fp = fopen(config_name, "r")))
+ {
+ free(new);
+ return NULL;
+ }
+ new->cfg_flag = FALSE;
+ return new;
+}
+
+/*
+ * Close an open config file and destroy the CONFIG parser object.
+ */
+
+void close_config(CONFIG *cfg)
+{
+ if(!cfg)
+ return;
+
+ fclose(cfg->cfg_fp);
+ free(cfg);
+}
+
+/* Read a line of ASCII text input from an open config file.
+ *
+ * Abstract:
+ * This routine extracts a line of input from an open config file.
+ * The input line extracted and returned is a "keyword = value" line
+ * found within the current [] section. If the end of the current
+ * [] section has been reached, then no further input is returned.
+ *
+ * Lines which contain comments are automatically skipped. Comments
+ * include those lines which begin with a '#' or ';' character.
+ * Empty lines are also automatically skipped.
+ *
+ * Special {} subsections may also be used to specify language
+ * variant .conf values. When these subsection identifiers are found
+ * and the current language found in the ENV (LANG=) does not match
+ * the language for the specified {} section, the entire {} section
+ * is skipped.
+ *
+ * The input line retreived automatically has lead and trailing
+ * whitespaces removed.
+ *
+ * Paramaters:
+ * cfg - a 'config' parser object.
+ *
+ * Returns:
+ * ASCII text for 'keyword = value' item from config file.
+ *
+ * Exceptions:
+ * A NULL is returned when the current [] section has been completed,
+ * when at the end of the file, or if any error occurs while reading.
+ */
+
+char *read_config(CONFIG *cfg)
+{
+ char *p, *q;
+ int skip = 0;
+
+ if(!cfg)
+ return NULL;
+
+ if(!cfg->cfg_flag)
+ return NULL;
+
+ for(;;)
+ {
+ fgets(cfg->cfg_lbuf, LBUF - 1, cfg->cfg_fp);
+ if(feof(cfg->cfg_fp) || cfg->cfg_lbuf[0] == '[' || ferror(cfg->cfg_fp))
+ {
+ cfg->cfg_flag = FALSE;
+ return NULL;
+ }
+ p = strtrim(cfg->cfg_lbuf, __SPACES);
+
+ if(*p == '{')
+ {
+ skip = 1;
+ p = strtok(p, "{}| \t");
+ while(p)
+ {
+ if(!stricmp(p, "all"))
+ skip = 0;
+ if(!stricmp(p, language()))
+ skip = 0;
+ p = strtok(NULL, "{}| \t");
+ }
+ continue;
+ }
+
+ if(!*p || *p == '!' || *p == '#' || *p == ';' || skip)
+ continue;
+
+ return p;
+ }
+}
+
+/*
+ * Seek a named [] section within the .conf file to begin input.
+ *
+ * Abstract:
+ * The named section is found within the .conf file. Once
+ * found, all read_config() input will be returned from the
+ * specified [] section. Section names are case insensitive.
+ *
+ * Paramaters:
+ * cfg - config object pointer.
+ * seek_name - name of config [] section to find.
+ *
+ * Returns:
+ * TRUE if the section name is found in the .conf file , FALSE if
+ * not.
+ *
+ * Exceptions:
+ * If a NULL cfg or seek_name is passed, the search always fails.
+ * If a file error is found, the search always fails. The maximum
+ * size of a [] section name that is tested is 22 characters.
+ */
+
+bool seek_config(CONFIG *cfg, const char *seek_name)
+{
+ char group[25];
+ int len;
+
+ if(!cfg || !seek_name)
+ return FALSE;
+
+ cfg->cfg_flag = FALSE; /* mark as outside old [] section */
+
+ len = strlen(seek_name);
+ if (len > 22)
+ len = 22;
+
+ memset(group, 0, sizeof(group));
+
+ if(*seek_name != '[')
+ strcpy(group, "[");
+
+ strncat(group, seek_name, len);
+
+ if(*seek_name != '[' && strlen(seek_name) < 23)
+ strcat(group, "]");
+
+ fseek(cfg->cfg_fp, 0l, SEEK_SET);
+ len = strlen(group);
+ for(;;)
+ {
+ fgets(cfg->cfg_lbuf, LBUF - 1, cfg->cfg_fp);
+ if(feof(cfg->cfg_fp) || ferror(cfg->cfg_fp))
+ return FALSE;
+
+ if(!strnicmp(group, cfg->cfg_lbuf, len))
+ {
+ cfg->cfg_flag = TRUE;
+ return TRUE;
+ }
+ }
+}
+
+/*
+ * Parse and test a keyword value pair from current config input.
+ *
+ * Abstract:
+ * This routine is commonly used to search the current input line
+ * that is returned by read_config() for a specified keyword. The
+ * current input line is assumed to be in the form 'keyword = value'.
+ * lead and trailing spaces around the '=' are ignored, as is keyword
+ * case. White spaces within a keyword are also ignored.
+ *
+ * Assuming the keyword requested is found in the current input line,
+ * the 'value' string is returned. If the keyword being tested is
+ * a multi-line keyword = { list }, then all lines for the value are
+ * scanned and loaded into the config line buffer. If the special
+ * '+' entry is found in the config file, then the keyword is assumed
+ * to be a continuation of the last one found.
+ *
+ * A value is normally stripped of all lead and trailing spaces. If
+ * these need to be preserved, then the value may be put in single
+ * or double quotes.
+ *
+ * Since get_config() only looks at the current input line buffered
+ * by read_config(), a test for every possible keyword the application
+ * may need should be performed after each successful read_config()
+ * for a given [] section.
+ *
+ * Paramaters:
+ * cfg - config object pointer.
+ * keyword - keyword to test for.
+ *
+ * Returns:
+ * Value string if keyword is found in current input line, else NULL.
+ *
+ * Exceptions:
+ * If a NULL pointer or keyword is used, a NULL value is returned.
+ */
+
+char *get_config(CONFIG *cfg, const char *keyword)
+{
+ char *cbuf;
+ char *out, *p;
+ int pos = 0;
+ bool found = FALSE;
+
+ if(!cfg || !keyword)
+ return NULL;
+
+ cbuf = cfg->cfg_lbuf;
+
+ if(*cbuf == '+') /* alternate multi-line syntax */
+ {
+ if(!stricmp(cfg->cfg_test, keyword))
+ return strltrim(++cbuf, __SPACES);
+ else
+ return NULL;
+ }
+
+ while((pos < 33) && *cbuf && (*cbuf != '='))
+ {
+ if((*cbuf != ' ') && (*cbuf != '_') && (*cbuf != '\t'))
+ cfg->cfg_test[pos++] = *(cbuf++);
+ else
+ ++cbuf;
+ }
+ cfg->cfg_test[pos] = 0;
+ out = p = strltrim(++cbuf, __SPACES);
+ switch(*p)
+ {
+ case '{':
+ cbuf = p;
+ while(!found)
+ {
+ while(*(++p))
+ {
+ if(*p == '}')
+ {
+ found = TRUE;
+ *p = 0;
+ }
+ else
+ *(cbuf++) = *p;
+ }
+
+ if(!found)
+ {
+ p = cbuf;
+ fgets(p, LBUF - 1 + (int)(cfg->cfg_lbuf - p), cfg->cfg_fp);
+ if(feof(cfg->cfg_fp) || *p == '[')
+ {
+ cfg->cfg_flag = FALSE;
+ *p = 0;
+ break;
+ }
+ *(cbuf++) = '\n';
+ p = strtrim(p, __SPACES);
+ }
+ }
+ *cbuf = 0;
+ out = strltrim(++out, __SPACES);
+ break;
+ case '\'':
+ case '\"':
+ while(*(++p))
+ {
+ if(*p == *out)
+ {
+ *p = 0;
+ break;
+ }
+ }
+ out = strltrim(++out, __SPACES);
+ break;
+ }
+ if(!stricmp(cfg->cfg_test, keyword))
+ return out;
+ else
+ return NULL;
+}
+
+/*
+ * Find config file in user's home directory.
+ *
+ * Abstract:
+ * In addition to searching for a master config file in /etc, many
+ * applications may support an optional user specific 'rc' or config
+ * file in the user's own home directory, which, if found, may
+ * override global defaults. This ability is easily supported with
+ * the usr_config() service, which looks for a named .config file
+ * in the user's home.
+ *
+ * Paramaters:
+ * Filename of '.config' file to look for in a user's home directory,
+ * without the leading '.'.
+ *
+ * Returns:
+ * Config object pointer if file is found in user's home, otherwise
+ * a NULL pointer.
+ *
+ * Exceptions:
+ * A NULL filename will result in a NULL object being returned.
+ */
+
+CONFIG *usr_config(const char *name)
+{
+ char path[NAME_MAX + 1];
+
+ if(!name)
+ return NULL;
+
+ strcpy(path, homedir());
+ fncat(path, ".");
+ strcat(path, name);
+ return open_config(path);
+}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sdk/other/config.h b/sdk/other/config.h
new file mode 100644
index 0000000..4d76d1a
--- /dev/null
+++ b/sdk/other/config.h
@@ -0,0 +1,67 @@
+/*
+ * Portable human readable config text file parsing routines.
+ * $Id: config.h 1.2 Wed, 19 Mar 1997 12:44:53 -0500 dyfet $
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and use see product license.
+ *
+ * Abstract:
+ * The config routines allow locating, opening, and parsing of
+ * human readable .conf files. These .conf files are broken into
+ * seperate named [] sections, each of which may be individually
+ * located and examined, and config data. Config data is usually
+ * in the form of a 'keyword = value' statement.
+ *
+ * Data types:
+ * CONFIG - object line parse buffer for an open config file.
+ */
+
+#ifndef __OTHER_CONFIG_H__
+#define __OTHER_CONFIG_H__
+
+#ifndef __OTHER_STRING_H__
+#include <other/string.h>
+#endif
+
+#ifndef __OTHER_FILES_H__
+#include <other/files.h>
+#endif
+
+typedef struct
+{
+ bool cfg_flag;
+ FILE *cfg_fp;
+ char cfg_test[33];
+ char cfg_lbuf[ EMPTY ];
+} CONFIG;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __NAMESPACE
+#define open_config __NAMESPACE(open_config)
+#define sys_config __NAMESPACE(sys_config)
+#define usr_config __NAMESPACE(usr_config)
+#define first_config __NAMESPACE(first_config)
+#define next_config __NAMESPACE(next_config)
+#define seek_config __NAMESPACE(seek_config)
+#define read_config __NAMESPACE(read_config)
+#define close_config __NAMESPACE(close_config)
+#define get_config __NAMESPACE(get_config)
+#endif
+
+CONFIG *open_config(const char *name);
+CONFIG *sys_config(const char *name);
+CONFIG *usr_config(const char *name);
+char *first_config(CONFIG *cfg);
+char *next_config(CONFIG *cfg);
+bool seek_config(CONFIG *cfg, const char *name);
+char *read_config(CONFIG *cfg);
+void close_config(CONFIG *cfg);
+char *get_config(CONFIG *cfg, const char *option);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/sdk/other/env.c b/sdk/other/env.c
new file mode 100644
index 0000000..cf3dfb0
--- /dev/null
+++ b/sdk/other/env.c
@@ -0,0 +1,36 @@
+/*
+ * Common values found in process environment space.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * See conditions of distribution and reuse see product license.
+ */
+
+#include <other/env.h>
+#include <std/string.h>
+
+char *homedir(void)
+{
+ char *env = getenv("HOME");
+
+ if(!env)
+ env = "/";
+
+ return env;
+}
+
+char *language(void)
+{
+ static char lbuf[32] = "default";
+
+ char *env = getenv("LANG");
+
+ if(env)
+ {
+ strncpy(lbuf, env, 31);
+ lbuf[31] = 0;
+ strtok(lbuf, "._");
+ }
+ return lbuf;
+}
+
+
diff --git a/sdk/other/env.h b/sdk/other/env.h
new file mode 100644
index 0000000..96b70e3
--- /dev/null
+++ b/sdk/other/env.h
@@ -0,0 +1,31 @@
+/*
+ * Portable process environment routines.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#ifndef __OTHER_ENV_H__
+#define __OTHER_ENV_H__
+
+#ifndef __STD_PROCESS_H__
+#include <std/process.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __NAMESPACE
+#define homedir __NAMESPACE(homedir)
+#define language __NAMESPACE(language)
+#endif
+
+char *homedir(void);
+char *language(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/sdk/other/expand.c b/sdk/other/expand.c
new file mode 100644
index 0000000..8005957
--- /dev/null
+++ b/sdk/other/expand.c
@@ -0,0 +1,36 @@
+/*
+ * String expansion and normalization of 'plain text' line data.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <std/string.h>
+
+char *expand(const char *s)
+{
+ static char buf[320];
+
+ int pos = 0;
+
+ while(*s)
+ {
+ if(*s == '\t')
+ {
+ buf[pos++] = ' ';
+ while(pos % 8)
+ buf[pos++] = ' ';
+ }
+ else if (*s > 31)
+ buf[pos++] = *s;
+ else
+ {
+ buf[pos++] = '^';
+ buf[pos++] = *s + '@';
+ }
+ ++s;
+ }
+ buf[pos] = 0;
+ return buf;
+}
+
diff --git a/sdk/other/fatal.c b/sdk/other/fatal.c
new file mode 100644
index 0000000..fd3ef54
--- /dev/null
+++ b/sdk/other/fatal.c
@@ -0,0 +1,23 @@
+/*
+ * Print error message to stderr and exit with status code.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <other/string.h>
+#include <std/files.h>
+#include <std/process.h>
+#include <stdarg.h>
+
+void fatal(int excode, const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ exit(excode);
+}
+
+
diff --git a/sdk/other/filename.c b/sdk/other/filename.c
new file mode 100644
index 0000000..2a7275e
--- /dev/null
+++ b/sdk/other/filename.c
@@ -0,0 +1,74 @@
+/*
+ * Portable file and directory name functions.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <other/files.h>
+#include <std/string.h>
+#include <std/math.h>
+
+char *dirname(char *path)
+{
+ char *p = basename(path);
+ if(p == path)
+ return ".";
+
+ *(--p) = 0;
+ return path;
+}
+
+char *basename(const char *path)
+{
+ char *p = strrchr(path, '/');
+#if defined(_MSDOS) || defined(_OS2) || defined(_WIN32)
+ char *p1 = strrchr(path, '\\');
+ p = max(p, p1);
+#endif
+
+ if(p)
+ return ++p;
+ else
+ return (char *)path;
+}
+
+char *extfname(const char *path)
+{
+ char *e = strrchr(pathfname(path), '.');
+
+ if(e)
+ return e;
+ else
+ return "";
+}
+
+bool ispath(const char *p)
+{
+ if(strchr(p, '/'))
+ return TRUE;
+#if defined(_MSDOS) || defined(_OS2) || defined(_WIN32)
+ if(strchr(p, '\\'))
+ return TRUE;
+#endif
+ return FALSE;
+}
+
+bool isroot(const char *p)
+{
+#if defined(_MSDOS) || defined(_OS2) || defined(_WIN32)
+ if(!strncmp(p, "\\\\", 2))
+ return TRUE;
+
+ if(p[1] == ':')
+ return TRUE;
+#else
+ if(*p == '/')
+ return TRUE;
+#endif
+ return FALSE;
+}
+
+
+
+
diff --git a/sdk/other/files.h b/sdk/other/files.h
new file mode 100644
index 0000000..7e9f421
--- /dev/null
+++ b/sdk/other/files.h
@@ -0,0 +1,52 @@
+/*
+ * Portable support for file manipulation and access related functions.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#ifndef __OTHER_FILES_H__
+#define __OTHER_FILES_H__
+
+#ifndef __STD_FILES_H__
+#include <std/files.h>
+#endif
+
+#define isdir(fpath) isftype(fpath, S_IFDIR)
+#define isfile(fpath) isftype(fpath, S_IFREG)
+#define islink(fpath) isftype(fpath, S_IFLNK)
+#define isfifo(fpath) isftype(fpath, S_IFIFO)
+#define pathfname(fn) basename(fn)
+#define rewind(fd) lseek(fd, (off_t)0, SEEK_SET)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __NAMESPACE
+#define isnewfile __NAMESPACE(isnewfile)
+#define isftype __NAMESPACE(isftype)
+#define ispath __NAMESPACE(ispath)
+#define isroot __NAMESPACE(isroot)
+#define fncat __NAMESPACE(fncat)
+#define search __NAMESPACE(search)
+#define basename __NAMESPACE(basename)
+#define dirname __NAMESPACE(dirname)
+#define extfname __NAMESPACE(extfname)
+#endif
+
+bool isnewfile(const char *from, const char *to);
+bool isftype(const char *fpath, int ftype);
+bool ispath(const char *fpath);
+bool isroot(const char *fpath);
+char *fncat(char *prefix, const char *suffix);
+char *search(const char *path, const char *fname);
+char *basename(const char *path);
+char *dirname(char *path);
+char *extfname(const char *path);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/sdk/other/fncat.c b/sdk/other/fncat.c
new file mode 100644
index 0000000..1d8e3e7
--- /dev/null
+++ b/sdk/other/fncat.c
@@ -0,0 +1,30 @@
+/*
+ * Concatenate filenames.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse review product license.
+ */
+
+#include <std/files.h>
+#include <other/string.h>
+
+char *fncat(char *prefix, const char *suffix)
+{
+ char *t = tail(prefix);
+
+ if(!*prefix)
+ {
+ strcpy(prefix, suffix);
+ return prefix;
+ };
+
+ if(*(--t) != '/')
+ {
+ *(++t) = '/';
+ *(++t) = 0;
+ }
+
+ strcat(prefix, suffix);
+ return prefix;
+}
+
diff --git a/sdk/other/getargv.c b/sdk/other/getargv.c
new file mode 100644
index 0000000..bae4d4f
--- /dev/null
+++ b/sdk/other/getargv.c
@@ -0,0 +1,57 @@
+/*
+ * Portable routines to create argv[] argument lists for exec and spawn.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <other/string.h>
+
+int getargv(char *base[], char *cbuf)
+{
+ int arg = 0;
+ int qflag = 0;
+ int sflag = 1;
+
+ while(*cbuf)
+ {
+ switch(*cbuf)
+ {
+ case ' ':
+ case '\t':
+ if(qflag)
+ break;
+ if(!sflag)
+ {
+ *cbuf = 0;
+ sflag = 1;
+ }
+ break;
+ case '\"':
+ if(!qflag)
+ {
+ *cbuf = 0;
+ base[arg++] = cbuf + 1;
+ sflag = 0;
+ qflag = 1;
+ }
+ else
+ {
+ *cbuf = 0;
+ sflag = 1;
+ qflag = 0;
+ }
+ break;
+ default:
+ if(sflag)
+ {
+ base[arg++] = cbuf;
+ sflag = 0;
+ }
+ }
+ ++cbuf;
+ }
+ base[arg] = NULL;
+ return arg;
+}
+
diff --git a/sdk/other/hex.c b/sdk/other/hex.c
new file mode 100644
index 0000000..ae5ccec
--- /dev/null
+++ b/sdk/other/hex.c
@@ -0,0 +1,44 @@
+/*
+ * Hex digit conversion functions.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <other/strcvt.h>
+
+char hex(int digit)
+{
+ if(digit < 10)
+ return '0' + digit;
+ else
+ return '7' + digit;
+};
+
+char *hexbyte(uchar v)
+{
+ static char h[3];
+
+ h[0] = hex(v / 16);
+ h[1] = hex(v % 16);
+ h[2] = 0;
+ return h;
+};
+
+char *hexshort(ushort v)
+{
+ static char h[5];
+
+ strcpy(h, hexbyte((uchar)(v / 256)));
+ strcpy(h + 2, hexbyte((uchar)(v % 256)));
+ return h;
+};
+
+char *hexlong(ulong v)
+{
+ static char h[9];
+
+ strcpy(h, hexshort((ushort)(v / 65536)));
+ strcpy(h + 4, hexshort((ushort)(v % 65536)));
+ return h;
+};
diff --git a/sdk/other/isftype.c b/sdk/other/isftype.c
new file mode 100644
index 0000000..bee42ca
--- /dev/null
+++ b/sdk/other/isftype.c
@@ -0,0 +1,22 @@
+/*
+ * File type testing routine.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <std/files.h>
+
+bool isftype(const char *path, int ftype)
+{
+ struct stat ino;
+
+ if(stat(path, &ino))
+ return FALSE;
+
+ if((ino.st_mode & S_IFMT) == ftype)
+ return TRUE;
+
+ return FALSE;
+}
+
diff --git a/sdk/other/make.conf b/sdk/other/make.conf
new file mode 100644
index 0000000..e8b05bd
--- /dev/null
+++ b/sdk/other/make.conf
@@ -0,0 +1,2 @@
+fn_find_file MEMORY_H_MISSING $inc/memory.h
+
diff --git a/sdk/other/memalloc.c b/sdk/other/memalloc.c
new file mode 100644
index 0000000..6d31108
--- /dev/null
+++ b/sdk/other/memalloc.c
@@ -0,0 +1,35 @@
+/*
+ * Advanced memory pool allocation scheme.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse consult product license.
+ */
+
+#include <other/memory.h>
+#include <std/math.h>
+
+void *memalloc(MEMPOOL *mem, int len)
+{
+ _MEMFREE *free = mem->mem_free;
+ _MEMCELL *cell = NULL;
+
+ len = align(len, __OBJALIGN);
+
+ while(free)
+ {
+ if(free->size == len)
+ {
+ cell = free->list;
+ break;
+ }
+ free = free->next;
+ }
+
+ if(cell)
+ {
+ free->list = cell->next;
+ return cell;
+ }
+
+ return memreq(mem, len);
+}
diff --git a/sdk/other/memdup.c b/sdk/other/memdup.c
new file mode 100644
index 0000000..af1f3cf
--- /dev/null
+++ b/sdk/other/memdup.c
@@ -0,0 +1,22 @@
+/*
+ * Duplicate object into a memory pool.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <std/string.h>
+#include <other/memory.h>
+
+void *memdup(void *obj, size_t size)
+{
+ void *new = (void *)malloc(size);
+
+ if(!new)
+ return NULL;
+
+ memcpy(new, obj, size);
+ return new;
+}
+
+
diff --git a/sdk/other/memfree.c b/sdk/other/memfree.c
new file mode 100644
index 0000000..1939f14
--- /dev/null
+++ b/sdk/other/memfree.c
@@ -0,0 +1,38 @@
+/*
+ * Advanced free space deallocation for memory pools.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <other/memory.h>
+#include <std/math.h>
+
+void memfree(MEMPOOL *mem, void *obj, int len)
+{
+ _MEMFREE *free = mem->mem_free;
+ _MEMCELL *cell = (_MEMCELL *)obj;
+ len = align(len, __OBJALIGN);
+
+ while(free)
+ {
+ if(free->size == len)
+ break;
+
+ free = free->next;
+ }
+
+ if(!free)
+ {
+ free = memreq(mem, sizeof(_MEMFREE));
+ free->list = NULL;
+ free->next = mem->mem_free;
+ mem->mem_free = free;
+ }
+
+ if(free)
+ {
+ cell->next = free->list;
+ free->list = cell;
+ }
+}
diff --git a/sdk/other/memory.h b/sdk/other/memory.h
new file mode 100644
index 0000000..902edd2
--- /dev/null
+++ b/sdk/other/memory.h
@@ -0,0 +1,103 @@
+/*
+ * Portable memory manipulation and management routines.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#ifndef __OTHER_MEMORY_H__
+#define __OTHER_MEMORY_H__
+
+#ifndef __STD_TYPES_H__
+#include <std/types.h>
+#endif
+
+#ifndef MEMORY_H_MISSING
+#include <memory.h>
+#endif
+
+#ifndef __MEMALIGN
+#define __MEMALIGN sizeof(ptr_t)
+#endif
+
+#ifndef __OBJALIGN
+#define __OBJALIGN __MEMALIGN
+#endif
+
+struct _mempool;
+struct _mempage;
+struct _memfree;
+struct _memcell;
+
+typedef struct _mempool
+{
+ int mem_psize;
+ int mem_pcount;
+ int mem_pused;
+ void *(*mem_pfault)(struct _mempool *mem, int reqsize);
+ struct _memfree *mem_free;
+ struct _mempage *mem_reuse;
+ struct _mempage *mem_last;
+} MEMPOOL;
+
+typedef struct _mempage
+{
+ struct _mempage *page_next;
+ int page_used;
+ uchar page[ EMPTY ];
+} MEMPAGE;
+
+typedef struct _memfree
+{
+ struct _memfree *next;
+ struct _memcell *list;
+ int size;
+} _MEMFREE;
+
+typedef struct _memcell
+{
+ void *next;
+} _MEMCELL;
+
+#define memfault(mem, fault) mem->mem_pfault = fault;
+#define memfirst(mem) ((MEMPAGE *)((char *)(mem) - sizeof(MEMPAGE)))
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __NAMESPACE
+#define mempool __NAMESPACE(mempool)
+#define memreuse __NAMESPACE(memreuse)
+#define memrelease __NAMESPACE(memrelease)
+#define memreq __NAMESPACE(memreq)
+#define memlreq __NAMESPACE(memlreq)
+#define strreq __NAMESPACE(strreq)
+#define strlreq __NAMESPACE(strlreq)
+#define memdup __NAMESPACE(memdup)
+#define memalloc __NAMESPACE(memalloc)
+#define memfree __NAMESPACE(memfree)
+#endif
+
+MEMPOOL *mempool(int psize, int pcount);
+void memreuse(MEMPOOL *mem);
+void memrelease(MEMPOOL *mem);
+void *memreq(MEMPOOL *mem, size_t memsize);
+void *memlreq(MEMPOOL *mem, size_t memsize);
+char *strreq(MEMPOOL *mem, const char *str);
+char *strlreq(MEMPOOL *mem, const char *str);
+void *memdup(void *, size_t);
+
+/* more advanced allocation schemes */
+
+void *memalloc(MEMPOOL *mem, int memsize);
+void memfree(MEMPOOL *mem, void *obj, int memsize);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/sdk/other/mempool.c b/sdk/other/mempool.c
new file mode 100644
index 0000000..ef27638
--- /dev/null
+++ b/sdk/other/mempool.c
@@ -0,0 +1,49 @@
+/*
+ * Memory pool creation.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <other/memory.h>
+#include <std/files.h>
+#include <std/math.h>
+#include <std/process.h>
+
+static void *fault(MEMPOOL *mem, int request)
+{
+ fputs("* mempool: memory pool exhausted\n", stderr);
+ exit(EX_SOFTWARE);
+}
+
+MEMPOOL *mempool(int psize, int pcount)
+{
+ char *page;
+ MEMPAGE *first;
+ MEMPOOL *pool;
+
+ psize = align(psize, __MEMALIGN);
+ if(NULL == (page = (char *)malloc(psize)))
+ return NULL;
+
+ first = (MEMPAGE *)page;
+ pool = (MEMPOOL *)(page + sizeof(MEMPAGE));
+
+ first->page_next = NULL;
+ first->page_used = sizeof(MEMPOOL);
+
+ pool->mem_psize = psize - sizeof(MEMPAGE);
+ pool->mem_pcount = pcount;
+ pool->mem_pused = 1;
+ pool->mem_pfault = fault;
+ pool->mem_reuse = NULL;
+ pool->mem_last = first;
+ pool->mem_free = NULL;
+ return pool;
+}
+
+
+
+
+
+
diff --git a/sdk/other/memrelease.c b/sdk/other/memrelease.c
new file mode 100644
index 0000000..144bff6
--- /dev/null
+++ b/sdk/other/memrelease.c
@@ -0,0 +1,43 @@
+/*
+ * Relallocate and release memory pools.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <other/memory.h>
+
+void memrelease(MEMPOOL *mem)
+{
+ MEMPAGE *page = memfirst(mem);
+ MEMPAGE *next;
+
+ while(page)
+ {
+ next = page->page_next;
+ free(page);
+ page = next;
+ }
+}
+
+void memreuse(MEMPOOL *mem)
+{
+ MEMPAGE *page = memfirst(mem);
+ MEMPAGE *next;
+
+ page = page->page_next;
+ while(page)
+ {
+ next = page->page_next;
+ free(page);
+ page = next;
+ }
+ mem->mem_pused = 1;
+ mem->mem_free = NULL;
+ page = mem->mem_last = memfirst(mem);
+ page->page_used = 0;
+ page->page_next = NULL;
+}
+
+
+
diff --git a/sdk/other/memreq.c b/sdk/other/memreq.c
new file mode 100644
index 0000000..16f8433
--- /dev/null
+++ b/sdk/other/memreq.c
@@ -0,0 +1,59 @@
+/*
+ * Copy strings and objects into a memory pool.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <other/memory.h>
+#include <std/math.h>
+
+static void *memrequest(MEMPOOL *mem, MEMPAGE *page, size_t len)
+{
+ int psize = mem->mem_psize;
+ void *obj;
+
+ /* align objects to ptr field size */
+
+ len = align(len, __OBJALIGN);
+
+ if(len > mem->mem_psize)
+ return (*mem->mem_pfault)(mem, len);
+
+ while(page)
+ {
+ if(page->page_used + len <= psize)
+ {
+ obj = &page->page[page->page_used];
+ page->page_used += len;
+ return obj;
+ }
+ page = page->page_next;
+ }
+
+ if(mem->mem_pused >= mem->mem_pcount)
+ return (*mem->mem_pfault)(mem, len);
+
+ ++mem->mem_pused;
+ page = (MEMPAGE *)malloc(psize + sizeof(MEMPAGE));
+ if(!page)
+ return (*mem->mem_pfault)(mem, len);
+
+ mem->mem_last->page_next = page;
+ mem->mem_last = page;
+ page->page_used = len;
+ page->page_next = NULL;
+ return page->page;
+}
+
+void *memlreq(MEMPOOL *mem, size_t len)
+{
+ return memrequest(mem, mem->mem_last, len);
+}
+
+void *memreq(MEMPOOL *mem, size_t len)
+{
+ return memrequest(mem, memfirst(mem), len);
+}
+
+
diff --git a/sdk/other/picture.c b/sdk/other/picture.c
new file mode 100644
index 0000000..3ff2dba
--- /dev/null
+++ b/sdk/other/picture.c
@@ -0,0 +1,112 @@
+/*
+ * String formatting of numeric data.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <std/string.h>
+
+char *picture(char *buf, const char *pict, long value)
+{
+ char *bp = buf, *tp;
+ long shift = 0;
+ int sign = 0;
+ int zfill = 0;
+ int digit;
+ int currency = 0;
+ int digits = 0;
+
+ if(value < 0)
+ {
+ ++sign;
+ value = -value;
+ }
+
+ while(*pict)
+ {
+ switch(*pict)
+ {
+ case '$':
+ ++currency;
+ *(bp++) = ' ';
+ ++pict;
+ break;
+ case '+':
+ if(sign)
+ *(bp++) = ' ';
+ else
+ *(bp++) = '+';
+ ++pict;
+ break;
+ case '-':
+ if(sign)
+ *(bp++) = '-';
+ else
+ *(bp++) = ' ';
+ ++pict;
+ break;
+ case '9':
+ case '0':
+ shift *= 10;
+ if(!shift)
+ shift = 1;
+ default:
+ *(bp++) = *(pict++);
+ }
+ }
+ if(value >= shift * 10)
+ {
+ bp = buf;
+ while(*bp)
+ {
+ if(isdigit(*bp))
+ *bp = '#';
+ ++bp;
+ }
+ return buf;
+ }
+ bp = tp = buf;
+ while(*bp)
+ {
+ switch(*bp)
+ {
+ case ',':
+ if(*(bp - 1) == '#')
+ {
+ *bp = '#';
+ break;
+ }
+ if(!zfill)
+ *bp = ' ';
+ break;
+ case '#':
+ if(!digits)
+ if(shift > value)
+ break;
+ case '0':
+ ++zfill;
+ case '9':
+ ++digits;
+ digit = (int)(value / shift);
+ if((digit > 0) || (shift == 1))
+ ++zfill;
+ if(!zfill && !digit)
+ digit = (int)(' ' - '0');
+ *bp = (char)('0' + digit);
+ if(isdigit(*bp) && currency)
+ {
+ currency = 0;
+ *(tp - 1) = '$';
+ }
+ value %= shift;
+ shift /= 10;
+ }
+ if(*bp != '#')
+ *(tp++) = *bp;
+ ++bp;
+ }
+ *tp = 0;
+ return buf;
+}
+
diff --git a/sdk/other/search.c b/sdk/other/search.c
new file mode 100644
index 0000000..15963bf
--- /dev/null
+++ b/sdk/other/search.c
@@ -0,0 +1,46 @@
+/*
+ * File path search routines.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <other/files.h>
+#include <other/string.h>
+#include <std/process.h>
+
+#ifdef QNX
+#define PATHMARK "!"
+#endif
+
+#ifndef PATHMARK
+#define PATHMARK ":"
+#endif
+
+char *search(const char *path, const char *file)
+{
+ static char buf[PATH_MAX + 1];
+ char pbuf[PATH_MAX + 1];
+ char *p;
+
+ if(!path)
+ return NULL;
+
+ strcpy(pbuf, path);
+
+ p = strtok(pbuf, PATHMARK);
+
+ while(p)
+ {
+ if(*p)
+ fncat(strcpy(buf, p), file);
+ else
+ strcpy(buf, file);
+ if(isfile(buf))
+ return buf;
+ p = strtok(NULL, PATHMARK);
+ }
+ return NULL;
+}
+
+
diff --git a/sdk/other/strblank.c b/sdk/other/strblank.c
new file mode 100644
index 0000000..d3e8d18
--- /dev/null
+++ b/sdk/other/strblank.c
@@ -0,0 +1,24 @@
+/*
+ * Test for blank strings.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <other/string.h>
+
+char __SPACES[] = " \t\r\n";
+
+bool strblank(const char *str)
+{
+ if(!str)
+ return TRUE;
+
+ while(*str)
+ {
+ if(!strchr(__SPACES, *str))
+ return FALSE;
+ ++str;
+ }
+ return TRUE;
+}
diff --git a/sdk/other/strcopy.c b/sdk/other/strcopy.c
new file mode 100644
index 0000000..077f897
--- /dev/null
+++ b/sdk/other/strcopy.c
@@ -0,0 +1,61 @@
+/*
+ * String copying defined for supporting over-lapping strings 'insertion'.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <other/string.h>
+
+static char *revcopy(char *to, const char *from, size_t count)
+{
+ while(count--)
+ *(to--) = *(from--);
+
+ *to = *from;
+ return to;
+};
+
+char *strcopy(char *to, const char *from)
+{
+ char *s1 = to;
+ int l = from - to;
+ int l2 = len(from);
+
+ if(!to || !from)
+ return NULL;
+
+ if(l > 0 && l <= l2)
+ return revcopy(to + l2, from + l2, l2);
+
+ ++l2;
+ while(l2--)
+ *(to++) = *(from++);
+
+ return s1;
+};
+
+char *strncopy(char *to, const char *from, int l2)
+{
+ char *s1 = to;
+ int l = from - to;
+ if(len(from) < l2)
+ return strcopy(to, from);
+
+ if(!to || !from)
+ return NULL;
+
+ if(l > 0 && l <= l2)
+ {
+ to[l2] = 0;
+ --l2;
+ return revcopy(to + l2, from + l2, l2);
+ }
+
+ while(l2--)
+ *(to++) = *(from++);
+
+ *to = 0;
+ return s1;
+};
+
diff --git a/sdk/other/strcvt.h b/sdk/other/strcvt.h
new file mode 100644
index 0000000..443c820
--- /dev/null
+++ b/sdk/other/strcvt.h
@@ -0,0 +1,56 @@
+/*
+ * Portable string handling routines.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#ifndef __OTHER_STRCVT_H__
+#define __OTHER_STRCVT_H__
+
+#ifndef __STD_STRING_H__
+#include <std/string.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __NAMESPACE
+#define __SPACES __NAMESPACE(__SPACES)
+#endif
+
+extern char __SPACES[];
+
+#ifdef __NAMESPACE
+#define atob __NAMESPACE(atob)
+#define strint __NAMESPACE(strint)
+#define picture __NAMESPACE(picture)
+#define expand __NAMESPACE(expand)
+#define xdigit __NAMESPACE(xdigit)
+#define xtol __NAMESPACE(xtol)
+#define hex __NAMESPACE(hex)
+#define hexbyte __NAMESPACE(hexbyte)
+#define hexshort __NAMESPACE(hexshort)
+#define hexlong __NAMESPACE(hexlong)
+#define str2bcd __NAMESPACE(str2bcd)
+#define bcd2str __NAMESPACE(bcd2str)
+#endif
+
+bool atob(const char *str);
+char *strint(long i, int z);
+char *picture(char *buf, const char *pict, long value);
+char *expand(const char *str);
+int xdigit(char digit);
+ulong xtol(const char *digit);
+char hex(int value);
+char *hexbyte(uchar);
+char *hexshort(ushort);
+char *hexlong(ulong);
+char *str2bcd(uchar *bcd, char *str, int max);
+uchar *bcd2str(char *str, uchar *bcd, int len);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/sdk/other/strdiff.c b/sdk/other/strdiff.c
new file mode 100644
index 0000000..a0297f6
--- /dev/null
+++ b/sdk/other/strdiff.c
@@ -0,0 +1,24 @@
+/*
+ * Often used to evaluate similarity of soundex codes.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <other/string.h>
+#include <std/math.h>
+
+int strdiff(const char *s1, const char *s2)
+{
+ int l1 = len(s1);
+ int l2 = len(s2);
+ int l = min(l1, l2);
+ int dif = abs(l1 - l2);
+
+ while(l--)
+ {
+ if(*(s1++) != *(s2++))
+ ++dif;
+ }
+ return dif;
+}
diff --git a/sdk/other/string.h b/sdk/other/string.h
new file mode 100644
index 0000000..5db8cd4
--- /dev/null
+++ b/sdk/other/string.h
@@ -0,0 +1,65 @@
+/*
+ * Portable string handling routines.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#ifndef __OTHER_STRINGS_H__
+#define __OTHER_STRINGS_H__
+
+#ifndef __STD_STRING_H__
+#include <std/string.h>
+#endif
+
+#ifndef __STD_TYPES_H__
+#include <std/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __NAMESPACE
+#define __SPACES __NAMESPACE(__SPACES)
+#endif
+
+extern char __SPACES[];
+
+#ifdef __NAMESPACE
+#define strblank __NAMESPACE(strblank)
+#define strtrim __NAMESPACE(strtrim)
+#define strrtrim __NAMESPACE(strrtrim)
+#define strltrim __NAMESPACE(strltrim)
+#define right __NAMESPACE(right)
+#define left __NAMESPACE(left)
+#define ccount __NAMESPACE(ccount)
+#define tail __NAMESPACE(tail)
+#define field __NAMESPACE(field)
+#define token __NAMESPACE(token)
+#define strcopy __NAMESPACE(strcopy)
+#define strncopy __NAMESPACE(strncopy)
+#define strdiff __NAMESPACE(strdiff)
+#define getargv __NAMESPACE(getargv)
+#endif
+
+bool strblank(const char *str);
+char *strtrim(char *s, const char *trim);
+char *strrtrim(char *s, const char *trim);
+char *strltrim(char *s, const char *trim);
+char *right(char *str, size_t len);
+char *left(char *str, size_t len);
+int ccount(const char *str, const char *list);
+char *tail(const char *str);
+char *field(char **ptr, const char *tok);
+char *token(char **ptr, const char *tok);
+char *strcopy(char *to, const char *from);
+char *strncopy(char *to, const char *from, int len);
+int strdiff(const char *s1, const char *s2);
+int getargv(char *base[], char *str);
+void fatal(int exitcode, const char *format, ...);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/sdk/other/strint.c b/sdk/other/strint.c
new file mode 100644
index 0000000..f4291a1
--- /dev/null
+++ b/sdk/other/strint.c
@@ -0,0 +1,51 @@
+/*
+ * Convert integer to string, with optional leading zeros.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <other/strcvt.h>
+
+char *strint(long i, int z)
+{
+ static char buf[30];
+ char b1[30];
+ char *p = buf, *q = b1;
+ unsigned u;
+
+ if(!i)
+ {
+ if(z < 1)
+ z = 1;
+ while(z--)
+ *(p++) = '0';
+ *p = 0;
+ return buf;
+ }
+ if((i < 0) && !z)
+ {
+ i = -i;
+ buf[0] = '-';
+ ++p;
+ }
+ u = (unsigned)i;
+
+ while(u > 0)
+ {
+ *(q++) = (char)(u % 10) + '0';
+ u /= 10;
+ }
+ *q = 0;
+ z -= strlen(b1);
+ while(z-- > 0)
+ *(p++) = '0';
+
+ while(q > b1)
+ *(p++) = *(--q);
+ *p = 0;
+ return buf;
+}
+
+
+
diff --git a/sdk/other/strpos.c b/sdk/other/strpos.c
new file mode 100644
index 0000000..79afbf5
--- /dev/null
+++ b/sdk/other/strpos.c
@@ -0,0 +1,46 @@
+/*
+ * String pointer manipulation routines.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <other/string.h>
+
+char *tail(const char *tail)
+{
+ if(!tail)
+ return NULL;
+
+ while(*tail)
+ ++tail;
+
+ return (char *)tail;
+}
+
+char *left(char *str, size_t pos)
+{
+ if(!str)
+ return NULL;
+
+ if(pos < strlen(str))
+ str[pos] = 0;
+
+ return str;
+};
+
+char *right(char *s, size_t l)
+{
+ size_t len;
+
+ if(!s)
+ return NULL;
+
+ len = strlen(s);
+ if(len <= l)
+ return s;
+
+ return s + len - l;
+}
+
+
diff --git a/sdk/other/strreq.c b/sdk/other/strreq.c
new file mode 100644
index 0000000..fb69b95
--- /dev/null
+++ b/sdk/other/strreq.c
@@ -0,0 +1,39 @@
+/*
+ * Memory pool string copy.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <other/memory.h>
+
+char *strreq(MEMPOOL *mem, const char *str)
+{
+ char *newstr;
+
+ if(!str)
+ return NULL;
+
+ newstr = memreq(mem, strlen(str) + 1);
+ if(!newstr)
+ return NULL;
+
+ strcpy(newstr, str);
+ return newstr;
+}
+
+char *strlreq(MEMPOOL *mem, const char *str)
+{
+ char *newstr;
+
+ if(!str)
+ return NULL;
+
+ newstr = memlreq(mem, strlen(str) + 1);
+ if(!newstr)
+ return NULL;
+
+ strcpy(newstr, str);
+ return newstr;
+}
+
diff --git a/sdk/other/strtrim.c b/sdk/other/strtrim.c
new file mode 100644
index 0000000..9afcfd5
--- /dev/null
+++ b/sdk/other/strtrim.c
@@ -0,0 +1,45 @@
+/*
+ * Portable string trimming routines.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <other/string.h>
+
+char *strtrim(char *str, const char *trim)
+{
+ return strltrim(strrtrim(str, trim), trim);
+}
+
+char *strrtrim(char *str, const char *trim)
+{
+ char *end;
+
+ if(!str)
+ return NULL;
+
+ end = str + strlen(str);
+
+ while(end-- > str)
+ {
+ if(!strchr(trim, *end))
+ return str;
+ *end = 0;
+ }
+ return str;
+}
+
+char *strltrim(char *str, const char *trim)
+{
+ if(!str)
+ return NULL;
+
+ while(*str)
+ {
+ if(!strchr(trim, *str))
+ return str;
+ ++str;
+ }
+ return str;
+}
diff --git a/sdk/other/token.c b/sdk/other/token.c
new file mode 100644
index 0000000..c9846ed
--- /dev/null
+++ b/sdk/other/token.c
@@ -0,0 +1,50 @@
+/*
+ * Alternate thread-safe string token parsing.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <other/string.h>
+
+char *token(char **ptr, const char *tok)
+{
+ char *p;
+ char *brk;
+
+ if(strblank(*ptr))
+ return NULL;
+
+ p = strltrim(*ptr, tok);
+ brk = strpbrk(p, tok);
+ if(brk)
+ {
+ *brk = 0;
+ *ptr = strltrim(++brk, tok);
+ if(!(**ptr))
+ *ptr = NULL;
+ }
+ else
+ *ptr = NULL;
+ return p;
+}
+
+char *field(char **ptr, const char *tok)
+{
+ char *p = *ptr;
+ char *brk;
+
+ if(strblank(p))
+ return NULL;
+
+ brk = strpbrk(p, tok);
+ if(brk)
+ {
+ *brk = 0;
+ *ptr = ++brk;
+ }
+ else
+ *ptr = NULL;
+
+ return p;
+}
diff --git a/sdk/other/xval.c b/sdk/other/xval.c
new file mode 100644
index 0000000..c7d1276
--- /dev/null
+++ b/sdk/other/xval.c
@@ -0,0 +1,28 @@
+/*
+ * Hex digit conversions.
+ * $Id$
+ * Copyright (c) 1997 by Tycho Softworks.
+ * For conditions of distribution and reuse see product license.
+ */
+
+#include <other/strcvt.h>
+
+int xdigit(char c)
+{
+ if(c > '9')
+ return upper(c) - '7';
+
+ return digit(c);
+};
+
+ulong xtol(const char *s)
+{
+ ulong v = 0l;
+
+ while(isxdigit(*s))
+ {
+ v = v << 4 | xdigit(*s);
+ ++s;
+ }
+ return v;
+};