summaryrefslogtreecommitdiff
path: root/Source/DOH
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DOH')
-rw-r--r--Source/DOH/README118
-rw-r--r--Source/DOH/base.c943
-rw-r--r--Source/DOH/doh.h442
-rw-r--r--Source/DOH/dohint.h133
-rw-r--r--Source/DOH/file.c299
-rw-r--r--Source/DOH/fio.c589
-rw-r--r--Source/DOH/hash.c551
-rw-r--r--Source/DOH/list.c377
-rw-r--r--Source/DOH/memory.c220
-rw-r--r--Source/DOH/string.c1158
-rw-r--r--Source/DOH/void.c96
11 files changed, 4926 insertions, 0 deletions
diff --git a/Source/DOH/README b/Source/DOH/README
new file mode 100644
index 0000000..9a42e8b
--- /dev/null
+++ b/Source/DOH/README
@@ -0,0 +1,118 @@
+DOH (Dave's Object Hack)
+
+Overview:
+---------
+DOH is a small C library that provides a number of simple yet powerful
+data structures. The data structures are built around a dynamic typing
+model in which any given object is allowed to support one or more
+classes of operations. Furthermore, a simple garbage collection
+scheme and a variety of interesting library methods are available.
+All and all, the operation of DOH makes massive abuse of the C type
+system and would probably make the language purists scream and
+performance addicts run away in horror. However, I really don't
+care--so there! However, for the rest of us, DOH is actually kind of
+fun to use. This is only a short description of the methods and is no
+way meant to be exhaustive.
+
+Common Operations (for all types)
+---------------------------------
+Delete(obj) Decrease the reference count and destroy if zero
+Copy(obj) Make a copy of an object.
+Clear(obj) Clear an object.
+Setscope(obj) Set scope of an object (guru's only)
+Str(obj) Create a string representation of obj.
+Data(obj) Return pointer to raw data in an object
+Char(obj) Convert to a char *
+Len(obj) Length of an object
+Hash(obj) Hash value (used for mapping)
+Cmp(obj1,obj2) Compare two objects.
+Name(obj) Return the object name
+First(obj) Return first object (iterator)
+Next(obj) Return next object
+Dump(obj,out) Serialize on out
+Load(in) Unserialize from in
+First(obj) Iterator
+Next(iter) Next iterator
+
+Mapping Operations (for hash table behavior)
+--------------------------------------------
+Getattr(hash,key) Get an attribute
+Setattr(hash,key,value) Set an attribute
+Delattr(hash,key) Delete an attribute
+First(hash) Get first object (iterator)
+Next(hash) Get next object
+GetInt(hash,key) Get attribute as an 'int'
+SetInt(hash,key,ivalue) Set attribute as an 'int'
+GetDouble(hash,key) Get attribute as a 'double'
+SetDouble(hash,key,dvalue) Set Attribute as a 'double'
+GetChar(hash,key) Get attribute as a 'char *'
+
+Sequence Operations
+-------------------
+Getitem(list,index) Get an item
+Setitem(list,index,val) Set an item
+Delitem(list,index,val) Delete an item
+Insert(list,index,val) Insert an item
+Append(list,val) Append to end
+Push(list,val) Insert at beginning
+
+File Operations
+---------------
+Read(obj,buffer,len) Read data
+Write(obj,buffer,len) Write data
+Getc(obj) Get a character
+Putc(ch,obj) Put a character
+Ungetc(ch,obj) Put character back on input stream
+Seek(obj,offset,whence) Seek
+Tell(obj) Return file pointer
+Close(obj) Close
+
+String Operations
+-----------------
+Replace(obj, orig, rep, flags) Replace occurences of orig with rep.
+Chop(obj) Remove trailing whitespace
+
+flags is one of the following:
+ DOH_REPLACE_ANY
+ DOH_REPLACE_NOQUOTE
+ DOH_REPLACE_ID
+ DOH_REPLACE_FIRST
+
+Callable Operations
+-------------------
+Call(obj, args) Perform a function call with arguments args.
+
+Miscellaneous library functions
+-------------------------------
+NewScope() Create a new scope
+DelScope(s) Delete scope s
+Readline(in) Read a line of input from in
+Printf(out,fmt,...) Formatted output
+DohEncoding(name, fn) Register a format encoding for Printf
+
+Currently Available datatypes
+------------------------------
+NewString(char *initial) Strings
+NewHash() Hash
+NewList() List
+NewVoid(void *ptr, void (*del)(void *)) Void
+NewFile(char *filename, char *mode, List *newfiles) File
+NewCallable(DOH *(*func)(DOH *, DOH *)) Callable object
+
+
+Odds and ends:
+
+ 1. All objects are of type 'DOH *'
+ 2. When in doubt, see rule (1)
+ 3. In certain cases, DOH performs implicit conversions
+ of 'char *' to an appropriate DOH string representation.
+ For operations involving files, DOH works with many
+ kinds of objects including FILE *, DOH File objects,
+ and DOH strings. Don't even ask how this works.
+
+ 4. More complete documentation is forthcoming.
+
+
+
+
+
diff --git a/Source/DOH/base.c b/Source/DOH/base.c
new file mode 100644
index 0000000..4262e70
--- /dev/null
+++ b/Source/DOH/base.c
@@ -0,0 +1,943 @@
+/* -----------------------------------------------------------------------------
+ * base.c
+ *
+ * This file contains the function entry points for dispatching methods on
+ * DOH objects. A number of small utility functions are also included.
+ *
+ * Author(s) : David Beazley (beazley@cs.uchicago.edu)
+ *
+ * Copyright (C) 1999-2000. The University of Chicago
+ * See the file LICENSE for information on usage and redistribution.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_base_c[] = "$Id: base.c 11097 2009-01-30 10:27:37Z bhy $";
+
+#include "dohint.h"
+
+/* -----------------------------------------------------------------------------
+ * DohDelete()
+ * ----------------------------------------------------------------------------- */
+
+#ifndef SWIG_DEBUG_DELETE
+#define SWIG_DEBUG_DELETE 0
+#endif
+
+void DohDelete(DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+
+ if (!obj)
+ return;
+#if SWIG_DEBUG_DELETE
+ if (!DohCheck(b)) {
+ fputs("DOH: Fatal error. Attempt to delete a non-doh object.\n", stderr);
+ abort();
+ }
+#endif
+ if (b->flag_intern)
+ return;
+ assert(b->refcount > 0);
+ b->refcount--;
+ if (b->refcount <= 0) {
+ objinfo = b->type;
+ if (objinfo->doh_del) {
+ (objinfo->doh_del) (b);
+ } else {
+ if (b->data)
+ DohFree(b->data);
+ }
+ DohObjFree(b);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * DohCopy()
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohCopy(const DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+
+ if (!obj)
+ return 0;
+ objinfo = b->type;
+ if (objinfo->doh_copy) {
+ DohBase *bc = (DohBase *) (objinfo->doh_copy) (b);
+ if ((bc) && b->meta) {
+ bc->meta = Copy(b->meta);
+ }
+ return (DOH *) bc;
+ }
+ return 0;
+}
+
+void DohIncref(DOH *obj) {
+ Incref(obj);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohClear()
+ * ----------------------------------------------------------------------------- */
+
+void DohClear(DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo = b->type;
+ if (objinfo->doh_clear)
+ (objinfo->doh_clear) (b);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohStr()
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohStr(const DOH *obj) {
+ char buffer[512];
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (DohCheck(b)) {
+ objinfo = b->type;
+ if (objinfo->doh_str) {
+ return (objinfo->doh_str) (b);
+ }
+ sprintf(buffer, "<Object '%s' at %p>", objinfo->objname, (void *) b);
+ return NewString(buffer);
+ } else {
+ return NewString(obj);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * DohDump()
+ * ----------------------------------------------------------------------------- */
+
+int DohDump(const DOH *obj, DOH *out) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo = b->type;
+ if (objinfo->doh_dump) {
+ return (objinfo->doh_dump) (b, out);
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohLen() - Defaults to strlen() if not a DOH object
+ * ----------------------------------------------------------------------------- */
+int DohLen(const DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (!b)
+ return 0;
+ if (DohCheck(b)) {
+ objinfo = b->type;
+ if (objinfo->doh_len) {
+ return (objinfo->doh_len) (b);
+ }
+ return 0;
+ } else {
+ return strlen((char *) obj);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * DohHashVal()
+ * ----------------------------------------------------------------------------- */
+
+int DohHashval(const DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ /* obj is already checked and/or converted into DohBase* */
+ /* if (DohCheck(b)) */
+ {
+ objinfo = b->type;
+ if (objinfo->doh_hashval) {
+ return (objinfo->doh_hashval) (b);
+ }
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohData()
+ * ----------------------------------------------------------------------------- */
+
+void *DohData(const DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (DohCheck(obj)) {
+ objinfo = b->type;
+ if (objinfo->doh_data) {
+ return (objinfo->doh_data) (b);
+ }
+ return 0;
+ }
+ return (void *) obj;
+}
+
+/* -----------------------------------------------------------------------------
+ * RawData()
+ * ----------------------------------------------------------------------------- */
+
+static void *RawData(DohBase *b) {
+ DohObjInfo *objinfo = b->type;
+ return (objinfo->doh_data) ? (objinfo->doh_data) (b) : 0;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * DohCmp()
+ * ----------------------------------------------------------------------------- */
+
+int DohCmp(const DOH *obj1, const DOH *obj2) {
+ DohBase *b1, *b2;
+ DohObjInfo *b1info, *b2info;
+ int c1, c2;
+ b1 = (DohBase *) obj1;
+ b2 = (DohBase *) obj2;
+ c1 = DohCheck(b1);
+ c2 = DohCheck(b2);
+ /* most of the times, obj2 is a plain c string */
+ if (!c1 || !c2) {
+ if ((b1 == 0) && (b2 == 0))
+ return 0;
+ if (b1 && !b2)
+ return 1;
+ if (!b1 && b2)
+ return -1;
+ return strcmp((char *) (c1 ? RawData(b1) : (void *) obj1), (char *) (c2 ? RawData(b2) : (void *) obj2));
+ }
+ b1info = b1->type;
+ b2info = b2->type;
+ if ((b1info == b2info) && (b1info->doh_cmp))
+ return (b1info->doh_cmp) (b1, b2);
+ return 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohEqual()
+ * ----------------------------------------------------------------------------- */
+
+int DohEqual(const DOH *obj1, const DOH *obj2) {
+ DohBase *b1 = (DohBase *) obj1;
+ DohBase *b2 = (DohBase *) obj2;
+ if (!b1) {
+ return !b2;
+ } else if (!b2) {
+ return 0;
+ } else {
+ DohObjInfo *b1info = 0;
+ DohObjInfo *b2info = 0;
+ if (DohCheck(b1)) {
+ b1info = b1->type;
+ if (DohCheck(b2)) {
+ b2info = b2->type;
+ } else {
+ int len = (b1info->doh_len) (b1);
+ char *cobj = (char *) obj2;
+ return len == (int) strlen(cobj) ? (memcmp(RawData(b1), cobj, len) == 0) : 0;
+ }
+ } else if (DohCheck(b2)) {
+ int len = (b2->type->doh_len) (b2);
+ char *cobj = (char *) obj1;
+ return len == (int) strlen(cobj) ? (memcmp(RawData(b2), cobj, len) == 0) : 0;
+ } else {
+ return strcmp((char *) obj1, (char *) obj2) == 0;
+ }
+
+ if (!b1info) {
+ return obj1 == obj2;
+ } else if ((b1info == b2info)) {
+ return b1info->doh_equal ? (b1info->doh_equal) (b1, b2) : (b1info->doh_cmp ? (b1info->doh_cmp) (b1, b2) == 0 : (b1 == b2));
+ } else {
+ return 0;
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * DohFirst()
+ * ----------------------------------------------------------------------------- */
+
+DohIterator DohFirst(DOH *obj) {
+ DohIterator iter;
+ DohBase *b;
+ DohObjInfo *binfo;
+
+ b = (DohBase *) obj;
+ if (DohCheck(b)) {
+ binfo = b->type;
+ if (binfo->doh_first) {
+ return (binfo->doh_first) (b);
+ }
+ }
+ iter.object = 0;
+ iter.item = 0;
+ iter.key = 0;
+ iter._current = 0;
+ iter._index = 0;
+ return iter;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohNext()
+ * ----------------------------------------------------------------------------- */
+
+DohIterator DohNext(DohIterator iter) {
+ DohIterator niter;
+
+ if (iter.object) {
+ DohBase *b;
+ DohObjInfo *binfo;
+
+ b = (DohBase *) iter.object;
+ binfo = b->type;
+ if (binfo->doh_next) {
+ return (binfo->doh_next) (iter);
+ }
+ }
+ niter = iter;
+ return niter;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohIsMapping()
+ * ----------------------------------------------------------------------------- */
+int DohIsMapping(const DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (!DohCheck(b))
+ return 0;
+ objinfo = b->type;
+ if (objinfo->doh_hash)
+ return 1;
+ else
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetattr()
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohGetattr(DOH *obj, const DOH *name) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo = b->type;
+ if (objinfo->doh_hash && objinfo->doh_hash->doh_getattr) {
+ DOH *r = (objinfo->doh_hash->doh_getattr) (b, (DOH *) name);
+ return (r == DohNone) ? 0 : r;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSetattr()
+ * ----------------------------------------------------------------------------- */
+
+int DohSetattr(DOH *obj, const DOH *name, const DOH *value) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo = b->type;
+ if (objinfo->doh_hash && objinfo->doh_hash->doh_setattr) {
+ return (objinfo->doh_hash->doh_setattr) (b, (DOH *) name, (DOH *) value);
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohDelattr()
+ * ----------------------------------------------------------------------------- */
+
+int DohDelattr(DOH *obj, const DOH *name) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo = b->type;
+ if (objinfo->doh_hash && objinfo->doh_hash->doh_delattr) {
+ return (objinfo->doh_hash->doh_delattr) (b, (DOH *) name);
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohCheckattr()
+ * ----------------------------------------------------------------------------- */
+
+int DohCheckattr(DOH *obj, const DOH *name, const DOH *value) {
+ DOH *attr = Getattr(obj,name);
+ if (!attr) return 0;
+ return DohEqual(attr,value);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohKeys()
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohKeys(DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo = b->type;
+ if (objinfo && objinfo->doh_hash->doh_keys) {
+ return (objinfo->doh_hash->doh_keys) (b);
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetInt()
+ * ----------------------------------------------------------------------------- */
+
+int DohGetInt(DOH *obj, const DOH *name) {
+ DOH *val;
+ val = Getattr(obj, (DOH *) name);
+ if (!val)
+ return 0;
+ if (DohIsString(val)) {
+ return atoi((char *) Data(val));
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetDouble()
+ * ----------------------------------------------------------------------------- */
+
+double DohGetDouble(DOH *obj, const DOH *name) {
+ DOH *val;
+ val = Getattr(obj, (DOH *) name);
+ if (!val)
+ return 0;
+ if (DohIsString(val)) {
+ return atof((char *) Data(val));
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetChar()
+ * ----------------------------------------------------------------------------- */
+
+char *DohGetChar(DOH *obj, const DOH *name) {
+ DOH *val;
+ val = Getattr(obj, (DOH *) name);
+ if (!val)
+ return 0;
+ if (DohIsString(val)) {
+ return (char *) Data(val);
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetFlagAttr() / DohGetFlag()
+ * A flag is unset if the attribute (name) does not exist on the node (obj),
+ * or it is set to "0". If the attribute is set to any other value,
+ * the flag is set.
+ *
+ * DohGetFlag() returns if the flag is set or not
+ * DohGetFlagAttr() returns the flag value if is set, NULL otherwise
+ * ----------------------------------------------------------------------------- */
+
+
+DOH *DohGetFlagAttr(DOH *obj, const DOH *name) {
+ DOH *val = Getattr(obj, (DOH *) name);
+ if (!val) {
+ return NULL;
+ } else {
+ const char *cval = Char(val);
+ if (!cval)
+ return val;
+ return (strcmp(cval, "0") != 0) ? val : NULL;
+ }
+}
+
+int DohGetFlag(DOH *obj, const DOH *name) {
+ return DohGetFlagAttr(obj, name) ? 1 : 0;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * DohGetVoid()
+ * ----------------------------------------------------------------------------- */
+
+void *DohGetVoid(DOH *obj, const DOH *name) {
+ DOH *val;
+ val = Getattr(obj, (DOH *) name);
+ if (!val)
+ return 0;
+ return (void *) Data(val);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSetInt()
+ * ----------------------------------------------------------------------------- */
+
+void DohSetInt(DOH *obj, const DOH *name, int value) {
+ DOH *temp;
+ temp = NewStringEmpty();
+ Printf(temp, "%d", value);
+ Setattr(obj, (DOH *) name, temp);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSetDouble()
+ * ----------------------------------------------------------------------------- */
+
+void DohSetDouble(DOH *obj, const DOH *name, double value) {
+ DOH *temp;
+ temp = NewStringEmpty();
+ Printf(temp, "%0.17f", value);
+ Setattr(obj, (DOH *) name, temp);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSetChar()
+ * ----------------------------------------------------------------------------- */
+
+void DohSetChar(DOH *obj, const DOH *name, char *value) {
+ Setattr(obj, (DOH *) name, NewString(value));
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSetFlag()
+ * ----------------------------------------------------------------------------- */
+
+void DohSetFlagAttr(DOH *obj, const DOH *name, const DOH *attr) {
+ Setattr(obj, (DOH *) name, attr ? attr : NewString("0"));
+}
+
+void DohSetFlag(DOH *obj, const DOH *name) {
+ Setattr(obj, (DOH *) name, NewString("1"));
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSetVoid()
+ * ----------------------------------------------------------------------------- */
+
+void DohSetVoid(DOH *obj, const DOH *name, void *value) {
+ Setattr(obj, (DOH *) name, NewVoid(value, 0));
+}
+
+/* -----------------------------------------------------------------------------
+ * DohIsSequence()
+ * ----------------------------------------------------------------------------- */
+
+int DohIsSequence(const DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (!DohCheck(b))
+ return 0;
+ objinfo = b->type;
+ if (objinfo->doh_list)
+ return 1;
+ else
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetitem()
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohGetitem(DOH *obj, int index) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo = b->type;
+ if (objinfo->doh_list && objinfo->doh_list->doh_getitem) {
+ return (objinfo->doh_list->doh_getitem) (b, index);
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSetitem()
+ * ----------------------------------------------------------------------------- */
+
+int DohSetitem(DOH *obj, int index, const DOH *value) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo = b->type;
+ if (objinfo->doh_list && objinfo->doh_list->doh_setitem) {
+ return (objinfo->doh_list->doh_setitem) (b, index, (DOH *) value);
+ }
+ return -1;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohDelitem()
+ * ----------------------------------------------------------------------------- */
+
+int DohDelitem(DOH *obj, int index) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo = b->type;
+ if (objinfo->doh_list && objinfo->doh_list->doh_delitem) {
+ return (objinfo->doh_list->doh_delitem) (b, index);
+ }
+ return -1;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohInsertitem()
+ * ----------------------------------------------------------------------------- */
+
+int DohInsertitem(DOH *obj, int index, const DOH *value) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo = b->type;
+ if (objinfo->doh_list && objinfo->doh_list->doh_insitem) {
+ return (objinfo->doh_list->doh_insitem) (b, index, (DOH *) value);
+ }
+ return -1;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * DohDelslice()
+ * ----------------------------------------------------------------------------- */
+
+int DohDelslice(DOH *obj, int sindex, int eindex) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo = b->type;
+ if (objinfo->doh_list && objinfo->doh_list->doh_delslice) {
+ return (objinfo->doh_list->doh_delslice) (b, sindex, eindex);
+ }
+ return -1;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohIsFile()
+ * ----------------------------------------------------------------------------- */
+
+int DohIsFile(const DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (!DohCheck(b))
+ return 0;
+ objinfo = b->type;
+ if (objinfo->doh_file)
+ return 1;
+ else
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohRead()
+ * ----------------------------------------------------------------------------- */
+
+int DohRead(DOH *obj, void *buffer, int length) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (DohCheck(obj)) {
+ objinfo = b->type;
+ if ((objinfo->doh_file) && (objinfo->doh_file->doh_read)) {
+ return (objinfo->doh_file->doh_read) (b, buffer, length);
+ }
+ return -1;
+ }
+ /* Hmmm. Not a file. Maybe it's a real FILE */
+ return fread(buffer, 1, length, (FILE *) b);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohWrite()
+ * ----------------------------------------------------------------------------- */
+
+int DohWrite(DOH *obj, void *buffer, int length) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (DohCheck(obj)) {
+ objinfo = b->type;
+ if ((objinfo->doh_file) && (objinfo->doh_file->doh_write)) {
+ return (objinfo->doh_file->doh_write) (b, buffer, length);
+ }
+ return -1;
+ }
+ /* Hmmm. Not a file. Maybe it's a real FILE */
+ return fwrite(buffer, 1, length, (FILE *) b);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSeek()
+ * ----------------------------------------------------------------------------- */
+
+int DohSeek(DOH *obj, long offset, int whence) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (DohCheck(obj)) {
+ objinfo = b->type;
+ if ((objinfo->doh_file) && (objinfo->doh_file->doh_seek)) {
+ return (objinfo->doh_file->doh_seek) (b, offset, whence);
+ }
+ return -1;
+ }
+ return fseek((FILE *) b, offset, whence);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohTell()
+ * ----------------------------------------------------------------------------- */
+
+long DohTell(DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (DohCheck(obj)) {
+ objinfo = b->type;
+ if ((objinfo->doh_file) && (objinfo->doh_file->doh_tell)) {
+ return (objinfo->doh_file->doh_tell) (b);
+ }
+ return -1;
+ }
+ return ftell((FILE *) b);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetc()
+ * ----------------------------------------------------------------------------- */
+
+int DohGetc(DOH *obj) {
+ static DOH *lastdoh = 0;
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (obj == lastdoh) {
+ objinfo = b->type;
+ return (objinfo->doh_file->doh_getc) (b);
+ }
+ if (DohCheck(obj)) {
+ objinfo = b->type;
+ if (objinfo->doh_file->doh_getc) {
+ lastdoh = obj;
+ return (objinfo->doh_file->doh_getc) (b);
+ }
+ return EOF;
+ }
+ return fgetc((FILE *) b);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohPutc()
+ * ----------------------------------------------------------------------------- */
+
+int DohPutc(int ch, DOH *obj) {
+ static DOH *lastdoh = 0;
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+
+ if (obj == lastdoh) {
+ objinfo = b->type;
+ return (objinfo->doh_file->doh_putc) (b, ch);
+ }
+ if (DohCheck(obj)) {
+ objinfo = b->type;
+ if (objinfo->doh_file->doh_putc) {
+ lastdoh = obj;
+ return (objinfo->doh_file->doh_putc) (b, ch);
+ }
+ return EOF;
+ }
+ return fputc(ch, (FILE *) b);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohUngetc()
+ * ----------------------------------------------------------------------------- */
+
+int DohUngetc(int ch, DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (DohCheck(obj)) {
+ objinfo = b->type;
+ if (objinfo->doh_file->doh_ungetc) {
+ return (objinfo->doh_file->doh_ungetc) (b, ch);
+ }
+ return EOF;
+ }
+ return ungetc(ch, (FILE *) b);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohClose()
+ * ----------------------------------------------------------------------------- */
+
+int DohClose(DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (DohCheck(obj)) {
+ objinfo = b->type;
+ if (objinfo->doh_file->doh_close) {
+ return (objinfo->doh_file->doh_close) (b);
+ }
+ return 0;
+ }
+ return fclose((FILE *) obj);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohIsString()
+ * ----------------------------------------------------------------------------- */
+
+int DohIsString(const DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (!DohCheck(b))
+ return 0;
+ objinfo = b->type;
+ if (objinfo->doh_string)
+ return 1;
+ else
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohReplace()
+ * ----------------------------------------------------------------------------- */
+
+int DohReplace(DOH *src, const DOH *token, const DOH *rep, int flags) {
+ DohBase *b = (DohBase *) src;
+ DohObjInfo *objinfo;
+ if (!token)
+ return 0;
+ if (!rep)
+ rep = "";
+ if (DohIsString(src)) {
+ objinfo = b->type;
+ if (objinfo->doh_string->doh_replace) {
+ return (objinfo->doh_string->doh_replace) (b, (DOH *) token, (DOH *) rep, flags);
+ }
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohChop()
+ * ----------------------------------------------------------------------------- */
+
+void DohChop(DOH *src) {
+ DohBase *b = (DohBase *) src;
+ DohObjInfo *objinfo;
+ if (DohIsString(src)) {
+ objinfo = b->type;
+ if (objinfo->doh_string->doh_chop) {
+ (objinfo->doh_string->doh_chop) (b);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSetFile()
+ * ----------------------------------------------------------------------------- */
+void DohSetfile(DOH *ho, DOH *file) {
+ DohBase *h = (DohBase *) ho;
+ DohObjInfo *objinfo;
+ if (!h)
+ return;
+ objinfo = h->type;
+ if (objinfo->doh_setfile)
+ (objinfo->doh_setfile) (h, file);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetFile()
+ * ----------------------------------------------------------------------------- */
+DOH *DohGetfile(const DOH *ho) {
+ DohBase *h = (DohBase *) ho;
+ DohObjInfo *objinfo;
+ if (!h)
+ return 0;
+ objinfo = h->type;
+ if (objinfo->doh_getfile)
+ return (objinfo->doh_getfile) (h);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSetLine()
+ * ----------------------------------------------------------------------------- */
+void DohSetline(DOH *ho, int l) {
+ DohBase *h = (DohBase *) ho;
+ DohObjInfo *objinfo;
+ if (!h)
+ return;
+ objinfo = h->type;
+ if (objinfo->doh_setline)
+ (objinfo->doh_setline) (h, l);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetLine()
+ * ----------------------------------------------------------------------------- */
+int DohGetline(const DOH *ho) {
+ DohBase *h = (DohBase *) ho;
+ DohObjInfo *objinfo;
+ if (!h)
+ return 0;
+ objinfo = h->type;
+ if (objinfo->doh_getline)
+ return (objinfo->doh_getline) (h);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetmeta()
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohGetmeta(DOH *ho, const DOH *name) {
+ DohBase *h = (DohBase *) ho;
+ if (!DohCheck(ho))
+ return 0;
+ if (!h->meta)
+ return 0;
+ return DohGetattr(h->meta, name);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetmeta()
+ * ----------------------------------------------------------------------------- */
+
+int DohSetmeta(DOH *ho, const DOH *name, const DOH *value) {
+ DohBase *h = (DohBase *) ho;
+ if (!DohCheck(ho))
+ return 0;
+ if (!h->meta)
+ h->meta = NewHash();
+ return DohSetattr(h->meta, name, value);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohDelmeta()
+ * ----------------------------------------------------------------------------- */
+
+int DohDelmeta(DOH *ho, const DOH *name) {
+ DohBase *h = (DohBase *) ho;
+ if (!DohCheck(ho))
+ return 0;
+ if (!h->meta)
+ return 0;
+ return DohDelattr(h->meta, name);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSetmark()
+ * ----------------------------------------------------------------------------- */
+
+void DohSetmark(DOH *ho, int x) {
+ DohBase *h = (DohBase *) ho;
+ h->flag_usermark = x;
+}
+
+int DohGetmark(DOH *ho) {
+ DohBase *h = (DohBase *) ho;
+ return h->flag_usermark;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohCall()
+ *
+ * Invokes a function via DOH. A Function is represented by a hash table with
+ * the following attributes:
+ *
+ * "builtin" - Pointer to built-in function (if any)
+ *
+ * (Additional attributes may be added later)
+ *
+ * Returns a DOH object with result on success. Returns NULL on error
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohCall(DOH *func, DOH *args) {
+ DOH *result;
+ DOH *(*builtin) (DOH *);
+
+ builtin = (DOH *(*)(DOH *)) GetVoid(func, "builtin");
+ if (!builtin)
+ return 0;
+ result = (*builtin) (args);
+ return result;
+}
diff --git a/Source/DOH/doh.h b/Source/DOH/doh.h
new file mode 100644
index 0000000..b731e95
--- /dev/null
+++ b/Source/DOH/doh.h
@@ -0,0 +1,442 @@
+/* -----------------------------------------------------------------------------
+ * doh.h
+ *
+ * This file describes of the externally visible functions in DOH.
+ *
+ * Author(s) : David Beazley (beazley@cs.uchicago.edu)
+ *
+ * Copyright (C) 1999-2000. The University of Chicago
+ * See the file LICENSE for information on usage and redistribution.
+ *
+ * $Id: doh.h 11097 2009-01-30 10:27:37Z bhy $
+ * ----------------------------------------------------------------------------- */
+
+#ifndef _DOH_H
+#define _DOH_H
+
+#ifndef MACSWIG
+#include "swigconfig.h"
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+
+/* Set the namespace prefix for DOH API functions. This can be used to control
+ visibility of the functions in libraries */
+
+/* Set this macro if you want to change DOH linkage. You would do this if you
+ wanted to hide DOH in a library using a different set of names. Note: simply
+ change "Doh" to a new name. */
+
+/*
+#define DOH_NAMESPACE(x) Doh ## x
+*/
+
+#ifdef DOH_NAMESPACE
+
+/* Namespace control. These macros define all of the public API names in DOH */
+
+#define DohCheck DOH_NAMESPACE(Check)
+#define DohIntern DOH_NAMESPACE(Intern)
+#define DohDelete DOH_NAMESPACE(Delete)
+#define DohCopy DOH_NAMESPACE(Copy)
+#define DohClear DOH_NAMESPACE(Clear)
+#define DohStr DOH_NAMESPACE(Str)
+#define DohData DOH_NAMESPACE(Data)
+#define DohDump DOH_NAMESPACE(Dump)
+#define DohLen DOH_NAMESPACE(Len)
+#define DohHashval DOH_NAMESPACE(Hashval)
+#define DohCmp DOH_NAMESPACE(Cmp)
+#define DohEqual DOH_NAMESPACE(Equal)
+#define DohIncref DOH_NAMESPACE(Incref)
+#define DohCheckattr DOH_NAMESPACE(Checkattr)
+#define DohSetattr DOH_NAMESPACE(Setattr)
+#define DohDelattr DOH_NAMESPACE(Delattr)
+#define DohKeys DOH_NAMESPACE(Keys)
+#define DohGetInt DOH_NAMESPACE(GetInt)
+#define DohGetDouble DOH_NAMESPACE(GetDouble)
+#define DohGetChar DOH_NAMESPACE(GetChar)
+#define DohSetChar DOH_NAMESPACE(SetChar)
+#define DohSetInt DOH_NAMESPACE(SetInt)
+#define DohSetDouble DOH_NAMESPACE(SetDouble)
+#define DohSetVoid DOH_NAMESPACE(SetVoid)
+#define DohGetVoid DOH_NAMESPACE(GetVoid)
+#define DohGetitem DOH_NAMESPACE(Getitem)
+#define DohSetitem DOH_NAMESPACE(Setitem)
+#define DohDelitem DOH_NAMESPACE(Delitem)
+#define DohInsertitem DOH_NAMESPACE(Insertitem)
+#define DohDelslice DOH_NAMESPACE(Delslice)
+#define DohWrite DOH_NAMESPACE(Write)
+#define DohRead DOH_NAMESPACE(Read)
+#define DohSeek DOH_NAMESPACE(Seek)
+#define DohTell DOH_NAMESPACE(Tell)
+#define DohGetc DOH_NAMESPACE(Getc)
+#define DohPutc DOH_NAMESPACE(Putc)
+#define DohUngetc DOH_NAMESPACE(Ungetc)
+#define DohGetline DOH_NAMESPACE(Getline)
+#define DohSetline DOH_NAMESPACE(Setline)
+#define DohGetfile DOH_NAMESPACE(Getfile)
+#define DohSetfile DOH_NAMESPACE(Setfile)
+#define DohReplace DOH_NAMESPACE(Replace)
+#define DohChop DOH_NAMESPACE(Chop)
+#define DohGetmeta DOH_NAMESPACE(Getmeta)
+#define DohSetmeta DOH_NAMESPACE(Setmeta)
+#define DohDelmeta DOH_NAMESPACE(Delmeta)
+#define DohEncoding DOH_NAMESPACE(Encoding)
+#define DohPrintf DOH_NAMESPACE(Printf)
+#define DohvPrintf DOH_NAMESPACE(vPrintf)
+#define DohPrintv DOH_NAMESPACE(Printv)
+#define DohReadline DOH_NAMESPACE(Readline)
+#define DohIsMapping DOH_NAMESPACE(IsMapping)
+#define DohIsSequence DOH_NAMESPACE(IsSequence)
+#define DohIsString DOH_NAMESPACE(IsString)
+#define DohIsFile DOH_NAMESPACE(IsFile)
+#define DohNewString DOH_NAMESPACE(NewString)
+#define DohNewStringEmpty DOH_NAMESPACE(NewStringEmpty)
+#define DohNewStringWithSize DOH_NAMESPACE(NewStringWithSize)
+#define DohNewStringf DOH_NAMESPACE(NewStringf)
+#define DohStrcmp DOH_NAMESPACE(Strcmp)
+#define DohStrncmp DOH_NAMESPACE(Strncmp)
+#define DohStrstr DOH_NAMESPACE(Strstr)
+#define DohStrchr DOH_NAMESPACE(Strchr)
+#define DohNewFile DOH_NAMESPACE(NewFile)
+#define DohNewFileFromFile DOH_NAMESPACE(NewFileFromFile)
+#define DohNewFileFromFd DOH_NAMESPACE(NewFileFromFd)
+#define DohFileErrorDisplay DOH_NAMESPACE(FileErrorDisplay)
+#define DohClose DOH_NAMESPACE(Close)
+#define DohCopyto DOH_NAMESPACE(Copyto)
+#define DohNewList DOH_NAMESPACE(NewList)
+#define DohNewHash DOH_NAMESPACE(NewHash)
+#define DohNewVoid DOH_NAMESPACE(NewVoid)
+#define DohSplit DOH_NAMESPACE(Split)
+#define DohSplitLines DOH_NAMESPACE(SplitLines)
+#define DohNone DOH_NAMESPACE(None)
+#define DohCall DOH_NAMESPACE(Call)
+#define DohObjMalloc DOH_NAMESPACE(ObjMalloc)
+#define DohObjFree DOH_NAMESPACE(ObjFree)
+#define DohMemoryDebug DOH_NAMESPACE(MemoryDebug)
+#define DohStringType DOH_NAMESPACE(StringType)
+#define DohListType DOH_NAMESPACE(ListType)
+#define DohHashType DOH_NAMESPACE(HashType)
+#define DohFileType DOH_NAMESPACE(FileType)
+#define DohVoidType DOH_NAMESPACE(VoidType)
+#define DohIterator DOH_NAMESPACE(Iterator)
+#define DohFirst DOH_NAMESPACE(First)
+#define DohNext DOH_NAMESPACE(Next)
+#endif
+
+#define DOH_MAJOR_VERSION 0
+#define DOH_MINOR_VERSION 1
+
+typedef void DOH;
+
+/*
+ * With dynamic typing, all DOH objects are technically of type 'void *'.
+ * However, to clarify the reading of source code, the following symbolic
+ * names are used.
+ */
+
+#define DOHString DOH
+#define DOHList DOH
+#define DOHHash DOH
+#define DOHFile DOH
+#define DOHVoid DOH
+#define DOHString_or_char DOH
+#define DOHObj_or_char DOH
+
+typedef const DOHString_or_char * const_String_or_char_ptr;
+typedef const DOHString_or_char * DOHconst_String_or_char_ptr;
+
+#define DOH_BEGIN -1
+#define DOH_END -2
+#define DOH_CUR -3
+#define DOH_CURRENT -3
+
+/* Iterator objects */
+
+typedef struct {
+ void *key; /* Current key (if any) */
+ void *item; /* Current item */
+ void *object; /* Object being iterated over */
+ void *_current; /* Internal use */
+ int _index; /* Internal use */
+} DohIterator;
+
+/* Memory management */
+
+#ifndef DohMalloc
+#define DohMalloc malloc
+#endif
+#ifndef DohRealloc
+#define DohRealloc realloc
+#endif
+#ifndef DohFree
+#define DohFree free
+#endif
+
+extern int DohCheck(const DOH *ptr); /* Check if a DOH object */
+extern void DohIntern(DOH *); /* Intern an object */
+
+/* Basic object methods. Common to most objects */
+
+extern void DohDelete(DOH *obj); /* Delete an object */
+extern DOH *DohCopy(const DOH *obj);
+extern void DohClear(DOH *obj);
+extern DOHString *DohStr(const DOH *obj);
+extern void *DohData(const DOH *obj);
+extern int DohDump(const DOH *obj, DOHFile * out);
+extern int DohLen(const DOH *obj);
+extern int DohHashval(const DOH *obj);
+extern int DohCmp(const DOH *obj1, const DOH *obj2);
+extern int DohEqual(const DOH *obj1, const DOH *obj2);
+extern void DohIncref(DOH *obj);
+
+/* Mapping methods */
+
+extern DOH *DohGetattr(DOH *obj, const DOHString_or_char *name);
+extern int DohSetattr(DOH *obj, const DOHString_or_char *name, const DOHObj_or_char * value);
+extern int DohDelattr(DOH *obj, const DOHString_or_char *name);
+extern int DohCheckattr(DOH *obj, const DOHString_or_char *name, const DOHString_or_char *value);
+extern DOH *DohKeys(DOH *obj);
+extern int DohGetInt(DOH *obj, const DOHString_or_char *name);
+extern void DohSetInt(DOH *obj, const DOHString_or_char *name, int);
+extern double DohGetDouble(DOH *obj, const DOHString_or_char *name);
+extern void DohSetDouble(DOH *obj, const DOHString_or_char *name, double);
+extern char *DohGetChar(DOH *obj, const DOHString_or_char *name);
+extern void DohSetChar(DOH *obj, const DOH *name, char *value);
+extern void *DohGetFlagAttr(DOH *obj, const DOHString_or_char *name);
+extern int DohGetFlag(DOH *obj, const DOHString_or_char *name);
+extern void DohSetFlagAttr(DOH *obj, const DOHString_or_char *name, const DOHString_or_char *attr);
+extern void DohSetFlag(DOH *obj, const DOHString_or_char *name);
+extern void *DohGetVoid(DOH *obj, const DOHString_or_char *name);
+extern void DohSetVoid(DOH *obj, const DOHString_or_char *name, void *value);
+
+/* Sequence methods */
+
+extern DOH *DohGetitem(DOH *obj, int index);
+extern int DohSetitem(DOH *obj, int index, const DOHObj_or_char * value);
+extern int DohDelitem(DOH *obj, int index);
+extern int DohInsertitem(DOH *obj, int index, const DOHObj_or_char * value);
+extern int DohDelslice(DOH *obj, int sindex, int eindex);
+
+/* File methods */
+
+extern int DohWrite(DOHFile * obj, void *buffer, int length);
+extern int DohRead(DOHFile * obj, void *buffer, int length);
+extern int DohSeek(DOHFile * obj, long offset, int whence);
+extern long DohTell(DOHFile * obj);
+extern int DohGetc(DOHFile * obj);
+extern int DohPutc(int ch, DOHFile * obj);
+extern int DohUngetc(int ch, DOHFile * obj);
+
+
+
+/* Iterators */
+extern DohIterator DohFirst(DOH *obj);
+extern DohIterator DohNext(DohIterator x);
+
+/* Positional */
+
+extern int DohGetline(const DOH *obj);
+extern void DohSetline(DOH *obj, int line);
+extern DOH *DohGetfile(const DOH *obj);
+extern void DohSetfile(DOH *obj, DOH *file);
+
+ /* String Methods */
+
+extern int DohReplace(DOHString * src, const DOHString_or_char *token, const DOHString_or_char *rep, int flags);
+extern void DohChop(DOHString * src);
+
+/* Meta-variables */
+extern DOH *DohGetmeta(DOH *, const DOH *);
+extern int DohSetmeta(DOH *, const DOH *, const DOH *value);
+extern int DohDelmeta(DOH *, const DOH *);
+
+ /* Utility functions */
+
+extern void DohEncoding(char *name, DOH *(*fn) (DOH *s));
+extern int DohPrintf(DOHFile * obj, const char *format, ...);
+extern int DohvPrintf(DOHFile * obj, const char *format, va_list ap);
+extern int DohPrintv(DOHFile * obj, ...);
+extern DOH *DohReadline(DOHFile * in);
+
+ /* Miscellaneous */
+
+extern int DohIsMapping(const DOH *obj);
+extern int DohIsSequence(const DOH *obj);
+extern int DohIsString(const DOH *obj);
+extern int DohIsFile(const DOH *obj);
+
+extern void DohSetmark(DOH *obj, int x);
+extern int DohGetmark(DOH *obj);
+
+/* -----------------------------------------------------------------------------
+ * Strings.
+ * ----------------------------------------------------------------------------- */
+
+extern DOHString *DohNewStringEmpty(void);
+extern DOHString *DohNewString(const DOH *c);
+extern DOHString *DohNewStringWithSize(const DOH *c, int len);
+extern DOHString *DohNewStringf(const DOH *fmt, ...);
+
+extern int DohStrcmp(const DOHString_or_char *s1, const DOHString_or_char *s2);
+extern int DohStrncmp(const DOHString_or_char *s1, const DOHString_or_char *s2, int n);
+extern char *DohStrstr(const DOHString_or_char *s1, const DOHString_or_char *s2);
+extern char *DohStrchr(const DOHString_or_char *s1, int ch);
+
+/* String replacement flags */
+
+#define DOH_REPLACE_ANY 0x01
+#define DOH_REPLACE_NOQUOTE 0x02
+#define DOH_REPLACE_ID 0x04
+#define DOH_REPLACE_FIRST 0x08
+#define DOH_REPLACE_ID_BEGIN 0x10
+#define DOH_REPLACE_ID_END 0x20
+
+#define Replaceall(s,t,r) DohReplace(s,t,r,DOH_REPLACE_ANY)
+#define Replaceid(s,t,r) DohReplace(s,t,r,DOH_REPLACE_ID)
+
+/* -----------------------------------------------------------------------------
+ * Files
+ * ----------------------------------------------------------------------------- */
+
+extern DOHFile *DohNewFile(DOH *filename, const char *mode, DOHList *outfiles);
+extern DOHFile *DohNewFileFromFile(FILE *f);
+extern DOHFile *DohNewFileFromFd(int fd);
+extern void DohFileErrorDisplay(DOHString * filename);
+extern int DohClose(DOH *file);
+extern int DohCopyto(DOHFile * input, DOHFile * output);
+
+
+/* -----------------------------------------------------------------------------
+ * List
+ * ----------------------------------------------------------------------------- */
+
+extern DOHList *DohNewList(void);
+extern void DohSortList(DOH *lo, int (*cmp) (const DOH *, const DOH *));
+
+/* -----------------------------------------------------------------------------
+ * Hash
+ * ----------------------------------------------------------------------------- */
+
+extern DOHHash *DohNewHash(void);
+
+/* -----------------------------------------------------------------------------
+ * Void
+ * ----------------------------------------------------------------------------- */
+
+extern DOHVoid *DohNewVoid(void *ptr, void (*del) (void *));
+extern DOHList *DohSplit(DOHFile * input, char ch, int nsplits);
+extern DOHList *DohSplitLines(DOHFile * input);
+extern DOH *DohNone;
+
+extern void DohMemoryDebug(void);
+
+#ifndef DOH_LONG_NAMES
+/* Macros to invoke the above functions. Includes the location of
+ the caller to simplify debugging if something goes wrong */
+
+#define Delete DohDelete
+#define Copy DohCopy
+#define Clear DohClear
+#define Str DohStr
+#define Dump DohDump
+#define Getattr DohGetattr
+#define Setattr DohSetattr
+#define Delattr DohDelattr
+#define Checkattr DohCheckattr
+#define Hashval DohHashval
+#define Getitem DohGetitem
+#define Setitem DohSetitem
+#define Delitem DohDelitem
+#define Insert DohInsertitem
+#define Delslice DohDelslice
+#define Append(s,x) DohInsertitem(s,DOH_END,x)
+#define Push(s,x) DohInsertitem(s,DOH_BEGIN,x)
+#define Len DohLen
+#define Data DohData
+#define Char (char *) Data
+#define Cmp DohCmp
+#define Equal DohEqual
+#define Setline DohSetline
+#define Getline DohGetline
+#define Setfile DohSetfile
+#define Getfile DohGetfile
+#define Write DohWrite
+#define Read DohRead
+#define Seek DohSeek
+#define Tell DohTell
+#define Printf DohPrintf
+#define Printv DohPrintv
+#define Getc DohGetc
+#define Putc DohPutc
+#define Ungetc DohUngetc
+
+/* #define StringPutc DohStringPutc */
+/* #define StringGetc DohStringGetc */
+/* #define StringUngetc DohStringUngetc */
+/* #define StringAppend Append */
+/* #define StringLen DohStringLen */
+/* #define StringChar DohStringChar */
+/* #define StringEqual DohStringEqual */
+
+#define Close DohClose
+#define vPrintf DohvPrintf
+#define GetInt DohGetInt
+#define GetDouble DohGetDouble
+#define GetChar DohGetChar
+#define GetVoid DohGetVoid
+#define GetFlagAttr DohGetFlagAttr
+#define GetFlag DohGetFlag
+#define SetInt DohSetInt
+#define SetDouble DohSetDouble
+#define SetChar DohSetattr
+#define SetVoid DohSetVoid
+#define SetFlagAttr DohSetFlagAttr
+#define SetFlag DohSetFlag
+#define UnsetFlag(o,n) DohSetFlagAttr(o,n,NULL)
+#define ClearFlag(o,n) DohSetFlagAttr(o,n,"")
+#define Readline DohReadline
+#define Replace DohReplace
+#define Chop DohChop
+#define Getmeta DohGetmeta
+#define Setmeta DohSetmeta
+#define Delmeta DohDelmeta
+#define NewString DohNewString
+#define NewStringEmpty DohNewStringEmpty
+#define NewStringWithSize DohNewStringWithSize
+#define NewStringf DohNewStringf
+#define NewHash DohNewHash
+#define NewList DohNewList
+#define NewFile DohNewFile
+#define NewFileFromFile DohNewFileFromFile
+#define NewFileFromFd DohNewFileFromFd
+#define FileErrorDisplay DohFileErrorDisplay
+#define Close DohClose
+#define NewVoid DohNewVoid
+#define Keys DohKeys
+#define Strcmp DohStrcmp
+#define Strncmp DohStrncmp
+#define Strstr DohStrstr
+#define Strchr DohStrchr
+#define Copyto DohCopyto
+#define Split DohSplit
+#define SplitLines DohSplitLines
+#define Setmark DohSetmark
+#define Getmark DohGetmark
+#define None DohNone
+#define Call DohCall
+#define First DohFirst
+#define Next DohNext
+#define Iterator DohIterator
+#define SortList DohSortList
+#endif
+
+#ifdef NIL
+#undef NIL
+#endif
+
+#define NIL (char *) NULL
+
+
+#endif /* DOH_H */
diff --git a/Source/DOH/dohint.h b/Source/DOH/dohint.h
new file mode 100644
index 0000000..8f52d28
--- /dev/null
+++ b/Source/DOH/dohint.h
@@ -0,0 +1,133 @@
+
+/* -----------------------------------------------------------------------------
+ * dohint.h
+ *
+ * This file describes internally managed objects.
+ *
+ * Author(s) : David Beazley (beazley@cs.uchicago.edu)
+ *
+ * Copyright (C) 1999-2000. The University of Chicago
+ * See the file LICENSE for information on usage and redistribution.
+ *
+ * $Id: dohint.h 9607 2006-12-05 22:11:40Z beazley $
+ * ----------------------------------------------------------------------------- */
+
+#ifndef _DOHINT_H
+#define _DOHINT_H
+
+#include "doh.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+/* Hash objects */
+typedef struct {
+ DOH *(*doh_getattr) (DOH *obj, DOH *name); /* Get attribute */
+ int (*doh_setattr) (DOH *obj, DOH *name, DOH *value); /* Set attribute */
+ int (*doh_delattr) (DOH *obj, DOH *name); /* Del attribute */
+ DOH *(*doh_keys) (DOH *obj); /* All keys as a list */
+} DohHashMethods;
+
+/* List objects */
+typedef struct {
+ DOH *(*doh_getitem) (DOH *obj, int index); /* Get item */
+ int (*doh_setitem) (DOH *obj, int index, DOH *value); /* Set item */
+ int (*doh_delitem) (DOH *obj, int index); /* Delete item */
+ int (*doh_insitem) (DOH *obj, int index, DOH *value); /* Insert item */
+ int (*doh_delslice) (DOH *obj, int sindex, int eindex); /* Delete slice */
+} DohListMethods;
+
+/* File methods */
+typedef struct {
+ int (*doh_read) (DOH *obj, void *buffer, int nbytes); /* Read bytes */
+ int (*doh_write) (DOH *obj, void *buffer, int nbytes); /* Write bytes */
+ int (*doh_putc) (DOH *obj, int ch); /* Put character */
+ int (*doh_getc) (DOH *obj); /* Get character */
+ int (*doh_ungetc) (DOH *obj, int ch); /* Unget character */
+ int (*doh_seek) (DOH *obj, long offset, int whence); /* Seek */
+ long (*doh_tell) (DOH *obj); /* Tell */
+ int (*doh_close) (DOH *obj); /* Close */
+} DohFileMethods;
+
+/* String methods */
+typedef struct {
+ int (*doh_replace) (DOH *obj, DOH *old, DOH *rep, int flags);
+ void (*doh_chop) (DOH *obj);
+} DohStringMethods;
+
+/* -----------------------------------------------------------------------------
+ * DohObjInfo
+ * ----------------------------------------------------------------------------- */
+
+typedef struct DohObjInfo {
+ char *objname; /* Object name */
+
+ /* Basic object methods */
+ void (*doh_del) (DOH *obj); /* Delete object */
+ DOH *(*doh_copy) (DOH *obj); /* Copy and object */
+ void (*doh_clear) (DOH *obj); /* Clear an object */
+
+ /* I/O methods */
+ DOH *(*doh_str) (DOH *obj); /* Make a full string */
+ void *(*doh_data) (DOH *obj); /* Return raw data */
+ int (*doh_dump) (DOH *obj, DOH *out); /* Serialize on out */
+
+ /* Length and hash values */
+ int (*doh_len) (DOH *obj);
+ int (*doh_hashval) (DOH *obj);
+
+ /* Compare */
+ int (*doh_cmp) (DOH *obj1, DOH *obj2);
+
+ /* Equal */
+ int (*doh_equal) (DOH *obj1, DOH *obj2);
+
+ /* Iterators */
+ DohIterator (*doh_first) (DOH *obj);
+ DohIterator (*doh_next) (DohIterator);
+
+ /* Positional */
+ void (*doh_setfile) (DOH *obj, DOHString_or_char *file);
+ DOH *(*doh_getfile) (DOH *obj);
+ void (*doh_setline) (DOH *obj, int line);
+ int (*doh_getline) (DOH *obj);
+
+ DohHashMethods *doh_hash; /* Hash methods */
+ DohListMethods *doh_list; /* List methods */
+ DohFileMethods *doh_file; /* File methods */
+ DohStringMethods *doh_string; /* String methods */
+ void *doh_reserved; /* Reserved */
+ void *clientdata; /* User data */
+} DohObjInfo;
+
+typedef struct {
+ void *data; /* Data pointer */
+ DohObjInfo *type;
+ void *meta; /* Meta data */
+ unsigned int flag_intern:1; /* Interned object */
+ unsigned int flag_marked:1; /* Mark flag. Used to avoid recursive loops in places */
+ unsigned int flag_user:1; /* User flag */
+ unsigned int flag_usermark:1; /* User marked */
+ unsigned int refcount:28; /* Reference count (max 16 million) */
+} DohBase;
+
+/* Macros for decrefing and increfing (safe for null objects). */
+
+#define Decref(a) if (a) ((DohBase *) a)->refcount--
+#define Incref(a) if (a) ((DohBase *) a)->refcount++
+#define Refcount(a) ((DohBase *) a)->refcount
+
+/* Macros for manipulating objects in a safe manner */
+#define ObjData(a) ((DohBase *)a)->data
+#define ObjSetMark(a,x) ((DohBase *)a)->flag_marked = x
+#define ObjGetMark(a) ((DohBase *)a)->flag_marked
+#define ObjType(a) ((DohBase *)a)->type
+
+extern DOH *DohObjMalloc(DohObjInfo *type, void *data); /* Allocate a DOH object */
+extern void DohObjFree(DOH *ptr); /* Free a DOH object */
+
+#endif /* DOHINT_H */
diff --git a/Source/DOH/file.c b/Source/DOH/file.c
new file mode 100644
index 0000000..2384850
--- /dev/null
+++ b/Source/DOH/file.c
@@ -0,0 +1,299 @@
+/* -----------------------------------------------------------------------------
+ * file.c
+ *
+ * This file implements a file-like object that can be built around an
+ * ordinary FILE * or integer file descriptor.
+ *
+ * Author(s) : David Beazley (beazley@cs.uchicago.edu)
+ *
+ * Copyright (C) 1999-2000. The University of Chicago
+ * See the file LICENSE for information on usage and redistribution.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_file_c[] = "$Id: file.c 10898 2008-11-03 12:51:45Z wsfulton $";
+
+#include "dohint.h"
+
+#ifdef DOH_INTFILE
+#include <unistd.h>
+#endif
+#include <errno.h>
+
+typedef struct {
+ FILE *filep;
+ int fd;
+ int closeondel;
+} DohFile;
+
+/* -----------------------------------------------------------------------------
+ * DelFile()
+ * ----------------------------------------------------------------------------- */
+
+static void DelFile(DOH *fo) {
+ DohFile *f = (DohFile *) ObjData(fo);
+ if (f->closeondel) {
+ if (f->filep) {
+ fclose(f->filep);
+ }
+#ifdef DOH_INTFILE
+ if (f->fd) {
+ close(f->fd);
+ }
+#endif
+ }
+ DohFree(f);
+}
+
+/* -----------------------------------------------------------------------------
+ * File_read()
+ * ----------------------------------------------------------------------------- */
+
+static int File_read(DOH *fo, void *buffer, int len) {
+ DohFile *f = (DohFile *) ObjData(fo);
+
+ if (f->filep) {
+ return fread(buffer, 1, len, f->filep);
+ } else if (f->fd) {
+#ifdef DOH_INTFILE
+ return read(f->fd, buffer, len);
+#endif
+ }
+ return -1;
+}
+
+/* -----------------------------------------------------------------------------
+ * File_write()
+ * ----------------------------------------------------------------------------- */
+
+static int File_write(DOH *fo, void *buffer, int len) {
+ DohFile *f = (DohFile *) ObjData(fo);
+ if (f->filep) {
+ int ret = (int) fwrite(buffer, 1, len, f->filep);
+ int err = (ret != len) ? ferror(f->filep) : 0;
+ return err ? -1 : ret;
+ } else if (f->fd) {
+#ifdef DOH_INTFILE
+ return write(f->fd, buffer, len);
+#endif
+ }
+ return -1;
+}
+
+/* -----------------------------------------------------------------------------
+ * File_seek()
+ * ----------------------------------------------------------------------------- */
+
+static int File_seek(DOH *fo, long offset, int whence) {
+ DohFile *f = (DohFile *) ObjData(fo);
+ if (f->filep) {
+ return fseek(f->filep, offset, whence);
+ } else if (f->fd) {
+#ifdef DOH_INTFILE
+ return lseek(f->fd, offset, whence);
+#endif
+ }
+ return -1;
+}
+
+/* -----------------------------------------------------------------------------
+ * File_tell()
+ * ----------------------------------------------------------------------------- */
+
+static long File_tell(DOH *fo) {
+ DohFile *f = (DohFile *) ObjData(fo);
+ if (f->filep) {
+ return ftell(f->filep);
+ } else if (f->fd) {
+#ifdef DOH_INTFILE
+ return lseek(f->fd, 0, SEEK_CUR);
+#endif
+ }
+ return -1;
+}
+
+/* -----------------------------------------------------------------------------
+ * File_putc()
+ * ----------------------------------------------------------------------------- */
+
+static int File_putc(DOH *fo, int ch) {
+ DohFile *f = (DohFile *) ObjData(fo);
+ if (f->filep) {
+ return fputc(ch, f->filep);
+ } else if (f->fd) {
+#ifdef DOH_INTFILE
+ char c;
+ c = (char) ch;
+ return write(f->fd, &c, 1);
+#endif
+ }
+ return -1;
+}
+
+/* -----------------------------------------------------------------------------
+ * File_getc()
+ * ----------------------------------------------------------------------------- */
+
+static int File_getc(DOH *fo) {
+ DohFile *f = (DohFile *) ObjData(fo);
+ if (f->filep) {
+ return fgetc(f->filep);
+ } else if (f->fd) {
+#ifdef DOH_INTFILE
+ unsigned char c;
+ if (read(f->fd, &c, 1) < 0)
+ return EOF;
+ return c;
+#endif
+ }
+ return EOF;
+}
+
+/* -----------------------------------------------------------------------------
+ * File_ungetc()
+ *
+ * Put a character back onto the input
+ * ----------------------------------------------------------------------------- */
+
+static int File_ungetc(DOH *fo, int ch) {
+ DohFile *f = (DohFile *) ObjData(fo);
+ if (f->filep) {
+ return ungetc(ch, f->filep);
+ } else if (f->fd) {
+#ifdef DOH_INTFILE
+ /* Not implemented yet */
+#endif
+ }
+ return -1;
+}
+
+/* -----------------------------------------------------------------------------
+ * File_close()
+ *
+ * Close the file
+ * ----------------------------------------------------------------------------- */
+
+static int File_close(DOH *fo) {
+ int ret = 0;
+ DohFile *f = (DohFile *) ObjData(fo);
+ if (f->filep) {
+ ret = fclose(f->filep);
+ f->filep = 0;
+ } else if (f->fd) {
+#ifdef DOH_INTFILE
+ ret = close(f->fd);
+ f->fd = 0;
+#endif
+ }
+ return ret;
+}
+
+static DohFileMethods FileFileMethods = {
+ File_read,
+ File_write,
+ File_putc,
+ File_getc,
+ File_ungetc,
+ File_seek,
+ File_tell,
+ File_close, /* close */
+};
+
+static DohObjInfo DohFileType = {
+ "DohFile", /* objname */
+ DelFile, /* doh_del */
+ 0, /* doh_copy */
+ 0, /* doh_clear */
+ 0, /* doh_str */
+ 0, /* doh_data */
+ 0, /* doh_dump */
+ 0, /* doh_len */
+ 0, /* doh_hash */
+ 0, /* doh_cmp */
+ 0, /* doh_equal */
+ 0, /* doh_first */
+ 0, /* doh_next */
+ 0, /* doh_setfile */
+ 0, /* doh_getfile */
+ 0, /* doh_setline */
+ 0, /* doh_getline */
+ 0, /* doh_mapping */
+ 0, /* doh_sequence */
+ &FileFileMethods, /* doh_file */
+ 0, /* doh_string */
+ 0, /* doh_callable */
+ 0, /* doh_position */
+};
+
+/* -----------------------------------------------------------------------------
+ * NewFile()
+ *
+ * Create a new file from a given filename and mode.
+ * If newfiles is non-zero, the filename is added to the list of new files.
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohNewFile(DOH *filename, const char *mode, DOHList *newfiles) {
+ DohFile *f;
+ FILE *file;
+ char *filen;
+
+ filen = Char(filename);
+ file = fopen(filen, mode);
+ if (!file)
+ return 0;
+
+ f = (DohFile *) DohMalloc(sizeof(DohFile));
+ if (!f) {
+ fclose(file);
+ return 0;
+ }
+ if (newfiles)
+ Append(newfiles, filename);
+ f->filep = file;
+ f->fd = 0;
+ f->closeondel = 1;
+ return DohObjMalloc(&DohFileType, f);
+}
+
+/* -----------------------------------------------------------------------------
+ * NewFileFromFile()
+ *
+ * Create a file object from an already open FILE *.
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohNewFileFromFile(FILE *file) {
+ DohFile *f;
+ f = (DohFile *) DohMalloc(sizeof(DohFile));
+ if (!f)
+ return 0;
+ f->filep = file;
+ f->fd = 0;
+ f->closeondel = 0;
+ return DohObjMalloc(&DohFileType, f);
+}
+
+/* -----------------------------------------------------------------------------
+ * NewFileFromFd()
+ *
+ * Create a file object from an already open FILE *.
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohNewFileFromFd(int fd) {
+ DohFile *f;
+ f = (DohFile *) DohMalloc(sizeof(DohFile));
+ if (!f)
+ return 0;
+ f->filep = 0;
+ f->fd = fd;
+ f->closeondel = 0;
+ return DohObjMalloc(&DohFileType, f);
+}
+
+/* -----------------------------------------------------------------------------
+ * FileErrorDisplay()
+ *
+ * Display cause of one of the NewFile functions failing.
+ * ----------------------------------------------------------------------------- */
+
+void DohFileErrorDisplay(DOHString * filename) {
+ Printf(stderr, "Unable to open file %s: %s\n", filename, strerror(errno));
+}
diff --git a/Source/DOH/fio.c b/Source/DOH/fio.c
new file mode 100644
index 0000000..7f3eb8b
--- /dev/null
+++ b/Source/DOH/fio.c
@@ -0,0 +1,589 @@
+/* -----------------------------------------------------------------------------
+ * fio.c
+ *
+ * This file implements a number of standard I/O operations included
+ * formatted output, readline, and splitting.
+ *
+ * Author(s) : David Beazley (beazley@cs.uchicago.edu)
+ *
+ * Copyright (C) 1999-2000. The University of Chicago
+ * See the file LICENSE for information on usage and redistribution.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_fio_c[] = "$Id: fio.c 9607 2006-12-05 22:11:40Z beazley $";
+
+#include "dohint.h"
+
+#define OBUFLEN 512
+
+static DOH *encodings = 0; /* Encoding hash */
+
+/* -----------------------------------------------------------------------------
+ * Writen()
+ *
+ * Write's N characters of output and retries until all characters are
+ * written. This is useful should a write operation encounter a spurious signal.
+ * ----------------------------------------------------------------------------- */
+
+static int Writen(DOH *out, void *buffer, int len) {
+ int nw = len, ret;
+ char *cb = (char *) buffer;
+ while (nw) {
+ ret = Write(out, cb, nw);
+ if (ret < 0)
+ return -1;
+ nw = nw - ret;
+ cb += ret;
+ }
+ return len;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohEncoding()
+ *
+ * Registers a new printf encoding method. An encoder function should accept
+ * two file-like objects and operate as a filter.
+ * ----------------------------------------------------------------------------- */
+
+void DohEncoding(char *name, DOH *(*fn) (DOH *s)) {
+ if (!encodings)
+ encodings = NewHash();
+ Setattr(encodings, (void *) name, NewVoid((void *) fn, 0));
+}
+
+/* internal function for processing an encoding */
+static DOH *encode(char *name, DOH *s) {
+ DOH *handle, *ns;
+ DOH *(*fn) (DOH *);
+ long pos;
+ char *cfmt = strchr(name, ':');
+ DOH *tmp = 0;
+ if (cfmt) {
+ tmp = NewString(cfmt + 1);
+ Append(tmp, s);
+ Setfile(tmp, Getfile((DOH *) s));
+ Setline(tmp, Getline((DOH *) s));
+ *cfmt = '\0';
+ }
+ if (!encodings || !(handle = Getattr(encodings, name))) {
+ return Copy(s);
+ }
+ if (tmp)
+ s = tmp;
+ pos = Tell(s);
+ Seek(s, 0, SEEK_SET);
+ fn = (DOH *(*)(DOH *)) Data(handle);
+ ns = (*fn) (s);
+ Seek(s, pos, SEEK_SET);
+ if (tmp)
+ Delete(tmp);
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohvPrintf()
+ *
+ * DOH implementation of printf. Output can be directed to any file-like object
+ * including bare FILE * objects. The same formatting codes as printf are
+ * recognized with two extensions:
+ *
+ * %s - Prints a "char *" or the string representation of any
+ * DOH object. This will implicitly result in a call to
+ * Str(obj).
+ *
+ * %(encoder)* - Filters the output through an encoding function registered
+ * with DohEncoder().
+ *
+ * Note: This function is not particularly memory efficient with large strings.
+ * It's better to use Dump() or some other method instead.
+ * ----------------------------------------------------------------------------- */
+
+int DohvPrintf(DOH *so, const char *format, va_list ap) {
+ static char *fmt_codes = "dioxXucsSfeEgGpn";
+ int state = 0;
+ const char *p = format;
+ char newformat[256];
+ char obuffer[OBUFLEN];
+ char *fmt = 0;
+ char temp[64];
+ int widthval = 0;
+ int precval = 0;
+ int maxwidth;
+ char *w = 0;
+ int ivalue;
+ double dvalue;
+ void *pvalue;
+ char *stemp;
+ int nbytes = 0;
+ char encoder[128], *ec = 0;
+ int plevel = 0;
+
+ memset(newformat, 0, sizeof(newformat));
+
+ while (*p) {
+ switch (state) {
+ case 0: /* Ordinary text */
+ if (*p != '%') {
+ Putc(*p, so);
+ nbytes++;
+ } else {
+ fmt = newformat;
+ widthval = 0;
+ precval = 0;
+ *(fmt++) = *p;
+ encoder[0] = 0;
+ state = 10;
+ }
+ break;
+ case 10: /* Look for a width and precision */
+ if (isdigit((int) *p) && (*p != '0')) {
+ w = temp;
+ *(w++) = *p;
+ *(fmt++) = *p;
+ state = 20;
+ } else if (strchr(fmt_codes, *p)) {
+ /* Got one of the formatting codes */
+ p--;
+ state = 100;
+ } else if (*p == '*') {
+ /* Width field is specified in the format list */
+ widthval = va_arg(ap, int);
+ sprintf(temp, "%d", widthval);
+ for (w = temp; *w; w++) {
+ *(fmt++) = *w;
+ }
+ state = 30;
+ } else if (*p == '%') {
+ Putc(*p, so);
+ fmt = newformat;
+ nbytes++;
+ state = 0;
+ } else if (*p == '(') {
+ ++plevel;
+ ec = encoder;
+ state = 60;
+ } else {
+ *(fmt++) = *p;
+ }
+ break;
+
+ case 20: /* Hmmm. At the start of a width field */
+ if (isdigit((int) *p)) {
+ *(w++) = *p;
+ *(fmt++) = *p;
+ } else if (strchr(fmt_codes, *p)) {
+ /* Got one of the formatting codes */
+ /* Figure out width */
+ *w = 0;
+ widthval = atoi(temp);
+ p--;
+ state = 100;
+ } else if (*p == '.') {
+ *w = 0;
+ widthval = atoi(temp);
+ w = temp;
+ *(fmt++) = *p;
+ state = 40;
+ } else {
+ /* ??? */
+ *w = 0;
+ widthval = atoi(temp);
+ state = 50;
+ }
+ break;
+
+ case 30: /* Parsed a width from an argument. Look for a . */
+ if (*p == '.') {
+ w = temp;
+ *(fmt++) = *p;
+ state = 40;
+ } else if (strchr(fmt_codes, *p)) {
+ /* Got one of the formatting codes */
+ /* Figure out width */
+ p--;
+ state = 100;
+ } else {
+ /* hmmm. Something else. */
+ state = 50;
+ }
+ break;
+
+ case 40:
+ /* Start of precision expected */
+ if (isdigit((int) *p) && (*p != '0')) {
+ *(fmt++) = *p;
+ *(w++) = *p;
+ state = 41;
+ } else if (*p == '*') {
+ /* Precision field is specified in the format list */
+ precval = va_arg(ap, int);
+ sprintf(temp, "%d", precval);
+ for (w = temp; *w; w++) {
+ *(fmt++) = *w;
+ }
+ state = 50;
+ } else if (strchr(fmt_codes, *p)) {
+ p--;
+ state = 100;
+ } else {
+ *(fmt++) = *p;
+ state = 50;
+ }
+ break;
+ case 41:
+ if (isdigit((int) *p)) {
+ *(fmt++) = *p;
+ *(w++) = *p;
+ } else if (strchr(fmt_codes, *p)) {
+ /* Got one of the formatting codes */
+ /* Figure out width */
+ *w = 0;
+ precval = atoi(temp);
+ p--;
+ state = 100;
+ } else {
+ *w = 0;
+ precval = atoi(temp);
+ *(fmt++) = *p;
+ state = 50;
+ }
+ break;
+ /* Hang out, wait for format specifier */
+ case 50:
+ if (strchr(fmt_codes, *p)) {
+ p--;
+ state = 100;
+ } else {
+ *(fmt++) = *p;
+ }
+ break;
+
+ /* Got an encoding header */
+ case 60:
+ if (*p == '(') {
+ ++plevel;
+ *ec = *p;
+ ec++;
+ } else if (*p == ')') {
+ --plevel;
+ if (plevel <= 0) {
+ *ec = 0;
+ state = 10;
+ } else {
+ *ec = *p;
+ ec++;
+ }
+ } else {
+ *ec = *p;
+ ec++;
+ }
+ break;
+ case 100:
+ /* Got a formatting code */
+ if (widthval < precval)
+ maxwidth = precval;
+ else
+ maxwidth = widthval;
+ if ((*p == 's') || (*p == 'S')) { /* Null-Terminated string */
+ DOH *doh;
+ DOH *Sval;
+ DOH *enc = 0;
+ doh = va_arg(ap, DOH *);
+ if (DohCheck(doh)) {
+ /* Is a DOH object. */
+ if (DohIsString(doh)) {
+ Sval = doh;
+ } else {
+ Sval = Str(doh);
+ }
+ if (strlen(encoder)) {
+ enc = encode(encoder, Sval);
+ maxwidth = maxwidth + strlen(newformat) + Len(enc);
+ } else {
+ maxwidth = maxwidth + strlen(newformat) + Len(Sval);
+ }
+ *(fmt++) = 's';
+ *fmt = 0;
+ if ((maxwidth + 1) < OBUFLEN) {
+ stemp = obuffer;
+ } else {
+ stemp = (char *) DohMalloc(maxwidth + 1);
+ }
+ if (enc) {
+ nbytes += sprintf(stemp, newformat, Data(enc));
+ } else {
+ nbytes += sprintf(stemp, newformat, Data(Sval));
+ }
+ if (Writen(so, stemp, strlen(stemp)) < 0)
+ return -1;
+ if ((DOH *) Sval != doh) {
+ Delete(Sval);
+ }
+ if (enc)
+ Delete(enc);
+ if (*p == 'S') {
+ Delete(doh);
+ }
+ if (stemp != obuffer) {
+ DohFree(stemp);
+ }
+ } else {
+ if (!doh)
+ doh = (char *) "";
+
+ if (strlen(encoder)) {
+ DOH *s = NewString(doh);
+ Seek(s, 0, SEEK_SET);
+ enc = encode(encoder, s);
+ Delete(s);
+ doh = Char(enc);
+ } else {
+ enc = 0;
+ }
+ maxwidth = maxwidth + strlen(newformat) + strlen((char *) doh);
+ *(fmt++) = 's';
+ *fmt = 0;
+ if ((maxwidth + 1) < OBUFLEN) {
+ stemp = obuffer;
+ } else {
+ stemp = (char *) DohMalloc(maxwidth + 1);
+ }
+ nbytes += sprintf(stemp, newformat, doh);
+ if (Writen(so, stemp, strlen(stemp)) < 0)
+ return -1;
+ if (stemp != obuffer) {
+ DohFree(stemp);
+ }
+ if (enc)
+ Delete(enc);
+ }
+ } else {
+ *(fmt++) = *p;
+ *fmt = 0;
+ maxwidth = maxwidth + strlen(newformat) + 64;
+
+ /* Only allocate a buffer if it is too big to fit. Shouldn't have to do
+ this very often */
+
+ if (maxwidth < OBUFLEN)
+ stemp = obuffer;
+ else
+ stemp = (char *) DohMalloc(maxwidth + 1);
+ switch (*p) {
+ case 'd':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ case 'c':
+ ivalue = va_arg(ap, int);
+ nbytes += sprintf(stemp, newformat, ivalue);
+ break;
+ case 'f':
+ case 'g':
+ case 'e':
+ case 'E':
+ case 'G':
+ dvalue = va_arg(ap, double);
+ nbytes += sprintf(stemp, newformat, dvalue);
+ break;
+ case 'p':
+ pvalue = va_arg(ap, void *);
+ nbytes += sprintf(stemp, newformat, pvalue);
+ break;
+ default:
+ break;
+ }
+ if (Writen(so, stemp, strlen(stemp)) < 0)
+ return -1;
+ if (stemp != obuffer)
+ DohFree(stemp);
+ }
+ state = 0;
+ break;
+ }
+ p++;
+ }
+ if (state) {
+ int r;
+ *fmt = 0;
+ r = Writen(so, fmt, strlen(fmt));
+ if (r < 0)
+ return -1;
+ nbytes += r;
+ }
+ return nbytes;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohPrintf()
+ *
+ * Variable length argument entry point to Printf
+ * ----------------------------------------------------------------------------- */
+
+int DohPrintf(DOH *obj, const char *format, ...) {
+ va_list ap;
+ int ret;
+ va_start(ap, format);
+ ret = DohvPrintf(obj, format, ap);
+ va_end(ap);
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohPrintv()
+ *
+ * Print a null-terminated variable length list of DOH objects
+ * ----------------------------------------------------------------------------- */
+
+int DohPrintv(DOHFile * f, ...) {
+ va_list ap;
+ int ret = 0;
+ DOH *obj;
+ va_start(ap, f);
+ while (1) {
+ obj = va_arg(ap, void *);
+ if ((!obj) || (obj == DohNone))
+ break;
+ if (DohCheck(obj)) {
+ ret += DohDump(obj, f);
+ } else {
+ ret += DohWrite(f, obj, strlen((char *) obj));
+ }
+ }
+ va_end(ap);
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohCopyto()
+ *
+ * Copies all of the input from an input stream to an output stream. Returns the
+ * number of bytes copied.
+ * ----------------------------------------------------------------------------- */
+
+int DohCopyto(DOH *in, DOH *out) {
+ int nbytes = 0, ret;
+ int nwrite = 0, wret;
+ char *cw;
+ char buffer[16384];
+
+ if ((!in) || (!out))
+ return 0;
+ while (1) {
+ ret = Read(in, buffer, 16384);
+ if (ret > 0) {
+ nwrite = ret;
+ cw = buffer;
+ while (nwrite) {
+ wret = Write(out, cw, nwrite);
+ if (wret < 0)
+ return -1;
+ nwrite = nwrite - wret;
+ cw += wret;
+ }
+ nbytes += ret;
+ } else {
+ return nbytes;
+ }
+ }
+}
+
+
+/* -----------------------------------------------------------------------------
+ * DohSplit()
+ *
+ * Split an input stream into a list of strings delimited by the specified
+ * character. Optionally accepts a maximum number of splits to perform.
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohSplit(DOH *in, char ch, int nsplits) {
+ DOH *list;
+ DOH *str;
+ int c;
+
+ list = NewList();
+
+ if (DohIsString(in)) {
+ Seek(in, 0, SEEK_SET);
+ }
+
+ while (1) {
+ str = NewStringEmpty();
+ do {
+ c = Getc(in);
+ } while ((c != EOF) && (c == ch));
+ if (c != EOF) {
+ Putc(c, str);
+ while (1) {
+ c = Getc(in);
+ if ((c == EOF) || ((c == ch) && (nsplits != 0)))
+ break;
+ Putc(c, str);
+ }
+ nsplits--;
+ }
+ Append(list, str);
+ Delete(str);
+ if (c == EOF)
+ break;
+ }
+ return list;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSplitLines()
+ *
+ * Split an input stream into a list of strings delimited by newline characters.
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohSplitLines(DOH *in) {
+ DOH *list;
+ DOH *str;
+ int c = 0;
+
+ list = NewList();
+
+ if (DohIsString(in)) {
+ Seek(in, 0, SEEK_SET);
+ }
+
+ while (c != EOF) {
+ str = NewStringEmpty();
+ while ((c = Getc(in)) != '\n' && c != EOF) {
+ Putc(c, str);
+ }
+ Append(list, str);
+ Delete(str);
+ }
+ return list;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * DohReadline()
+ *
+ * Read a single input line and return it as a string.
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohReadline(DOH *in) {
+ char c;
+ int n = 0;
+ DOH *s = NewStringEmpty();
+ while (1) {
+ if (Read(in, &c, 1) < 0) {
+ if (n == 0) {
+ Delete(s);
+ return 0;
+ }
+ return s;
+ }
+ if (c == '\n')
+ return s;
+ if (c == '\r')
+ continue;
+ Putc(c, s);
+ n++;
+ }
+}
diff --git a/Source/DOH/hash.c b/Source/DOH/hash.c
new file mode 100644
index 0000000..071a6a6
--- /dev/null
+++ b/Source/DOH/hash.c
@@ -0,0 +1,551 @@
+/* -----------------------------------------------------------------------------
+ * hash.c
+ *
+ * Implements a simple hash table object.
+ *
+ * Author(s) : David Beazley (beazley@cs.uchicago.edu)
+ *
+ * Copyright (C) 1999-2000. The University of Chicago
+ * See the file LICENSE for information on usage and redistribution.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_hash_c[] = "$Id: hash.c 10926 2008-11-11 22:17:40Z wsfulton $";
+
+#include "dohint.h"
+
+extern DohObjInfo DohHashType;
+
+/* Hash node */
+typedef struct HashNode {
+ DOH *key;
+ DOH *object;
+ struct HashNode *next;
+} HashNode;
+
+/* Hash object */
+typedef struct Hash {
+ DOH *file;
+ int line;
+ HashNode **hashtable;
+ int hashsize;
+ int nitems;
+} Hash;
+
+/* Key interning structure */
+typedef struct KeyValue {
+ char *cstr;
+ DOH *sstr;
+ struct KeyValue *left;
+ struct KeyValue *right;
+} KeyValue;
+
+static KeyValue *root = 0;
+
+/* Find or create a key in the interned key table */
+static DOH *find_key(DOH *doh_c) {
+ char *c = (char *) doh_c;
+ KeyValue *r, *s;
+ int d = 0;
+ /* OK, sure, we use a binary tree for maintaining interned
+ symbols. Then we use their hash values for accessing secondary
+ hash tables. */
+ r = root;
+ s = 0;
+ while (r) {
+ s = r;
+ d = strcmp(r->cstr, c);
+ if (d == 0)
+ return r->sstr;
+ if (d < 0)
+ r = r->left;
+ else
+ r = r->right;
+ }
+ /* fprintf(stderr,"Interning '%s'\n", c); */
+ r = (KeyValue *) DohMalloc(sizeof(KeyValue));
+ r->cstr = (char *) DohMalloc(strlen(c) + 1);
+ strcpy(r->cstr, c);
+ r->sstr = NewString(c);
+ DohIntern(r->sstr);
+ r->left = 0;
+ r->right = 0;
+ if (!s) {
+ root = r;
+ } else {
+ if (d < 0)
+ s->left = r;
+ else
+ s->right = r;
+ }
+ return r->sstr;
+}
+
+#define HASH_INIT_SIZE 7
+
+/* Create a new hash node */
+static HashNode *NewNode(DOH *k, void *obj) {
+ HashNode *hn = (HashNode *) DohMalloc(sizeof(HashNode));
+ hn->key = k;
+ Incref(hn->key);
+ hn->object = obj;
+ Incref(obj);
+ hn->next = 0;
+ return hn;
+}
+
+/* Delete a hash node */
+static void DelNode(HashNode *hn) {
+ Delete(hn->key);
+ Delete(hn->object);
+ DohFree(hn);
+}
+
+/* -----------------------------------------------------------------------------
+ * DelHash()
+ *
+ * Delete a hash table.
+ * ----------------------------------------------------------------------------- */
+
+static void DelHash(DOH *ho) {
+ Hash *h = (Hash *) ObjData(ho);
+ HashNode *n, *next;
+ int i;
+
+ for (i = 0; i < h->hashsize; i++) {
+ n = h->hashtable[i];
+ while (n) {
+ next = n->next;
+ DelNode(n);
+ n = next;
+ }
+ }
+ DohFree(h->hashtable);
+ h->hashtable = 0;
+ h->hashsize = 0;
+ DohFree(h);
+}
+
+/* -----------------------------------------------------------------------------
+ * Hash_clear()
+ *
+ * Clear all of the entries in the hash table.
+ * ----------------------------------------------------------------------------- */
+
+static void Hash_clear(DOH *ho) {
+ Hash *h = (Hash *) ObjData(ho);
+ HashNode *n, *next;
+ int i;
+
+ for (i = 0; i < h->hashsize; i++) {
+ n = h->hashtable[i];
+ while (n) {
+ next = n->next;
+ DelNode(n);
+ n = next;
+ }
+ h->hashtable[i] = 0;
+ }
+ h->nitems = 0;
+}
+
+/* resize the hash table */
+static void resize(Hash *h) {
+ HashNode *n, *next, **table;
+ int oldsize, newsize;
+ int i, p, hv;
+
+ if (h->nitems < 2 * h->hashsize)
+ return;
+
+ /* Too big. We have to rescale everything now */
+ oldsize = h->hashsize;
+
+ /* Calculate a new size */
+ newsize = 2 * oldsize + 1;
+ p = 3;
+ while (p < (newsize >> 1)) {
+ if (((newsize / p) * p) == newsize) {
+ newsize += 2;
+ p = 3;
+ continue;
+ }
+ p = p + 2;
+ }
+
+ table = (HashNode **) DohMalloc(newsize * sizeof(HashNode *));
+ for (i = 0; i < newsize; i++) {
+ table[i] = 0;
+ }
+
+ /* Walk down the old set of nodes and re-place */
+ h->hashsize = newsize;
+ for (i = 0; i < oldsize; i++) {
+ n = h->hashtable[i];
+ while (n) {
+ hv = Hashval(n->key) % newsize;
+ next = n->next;
+ n->next = table[hv];
+ table[hv] = n;
+ n = next;
+ }
+ }
+ DohFree(h->hashtable);
+ h->hashtable = table;
+}
+
+/* -----------------------------------------------------------------------------
+ * Hash_setattr()
+ *
+ * Set an attribute in the hash table. Deletes the existing entry if it already
+ * exists.
+ * ----------------------------------------------------------------------------- */
+
+static int Hash_setattr(DOH *ho, DOH *k, DOH *obj) {
+ int hv;
+ HashNode *n, *prev;
+ Hash *h = (Hash *) ObjData(ho);
+
+ if (!obj) {
+ return DohDelattr(ho, k);
+ }
+ if (!DohCheck(k))
+ k = find_key(k);
+ if (!DohCheck(obj)) {
+ obj = NewString((char *) obj);
+ Decref(obj);
+ }
+ hv = (Hashval(k)) % h->hashsize;
+ n = h->hashtable[hv];
+ prev = 0;
+ while (n) {
+ if (Cmp(n->key, k) == 0) {
+ /* Node already exists. Just replace its contents */
+ if (n->object == obj) {
+ /* Whoa. Same object. Do nothing */
+ return 1;
+ }
+ Delete(n->object);
+ n->object = obj;
+ Incref(obj);
+ return 1; /* Return 1 to indicate a replacement */
+ } else {
+ prev = n;
+ n = n->next;
+ }
+ }
+ /* Add this to the table */
+ n = NewNode(k, obj);
+ if (prev)
+ prev->next = n;
+ else
+ h->hashtable[hv] = n;
+ h->nitems++;
+ resize(h);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Hash_getattr()
+ *
+ * Get an attribute from the hash table. Returns 0 if it doesn't exist.
+ * ----------------------------------------------------------------------------- */
+typedef int (*binop) (DOH *obj1, DOH *obj2);
+
+
+static DOH *Hash_getattr(DOH *h, DOH *k) {
+ DOH *obj = 0;
+ Hash *ho = (Hash *) ObjData(h);
+ DOH *ko = DohCheck(k) ? k : find_key(k);
+ int hv = Hashval(ko) % ho->hashsize;
+ DohObjInfo *k_type = ((DohBase*)ko)->type;
+ HashNode *n = ho->hashtable[hv];
+ if (k_type->doh_equal) {
+ binop equal = k_type->doh_equal;
+ while (n) {
+ DohBase *nk = (DohBase *)n->key;
+ if ((k_type == nk->type) && equal(ko, nk)) obj = n->object;
+ n = n->next;
+ }
+ } else {
+ binop cmp = k_type->doh_cmp;
+ while (n) {
+ DohBase *nk = (DohBase *)n->key;
+ if ((k_type == nk->type) && (cmp(ko, nk) == 0)) obj = n->object;
+ n = n->next;
+ }
+ }
+ return obj;
+}
+
+/* -----------------------------------------------------------------------------
+ * Hash_delattr()
+ *
+ * Delete an object from the hash table.
+ * ----------------------------------------------------------------------------- */
+
+static int Hash_delattr(DOH *ho, DOH *k) {
+ HashNode *n, *prev;
+ int hv;
+ Hash *h = (Hash *) ObjData(ho);
+
+ if (!DohCheck(k))
+ k = find_key(k);
+ hv = Hashval(k) % h->hashsize;
+ n = h->hashtable[hv];
+ prev = 0;
+ while (n) {
+ if (Cmp(n->key, k) == 0) {
+ /* Found it, kill it */
+
+ if (prev) {
+ prev->next = n->next;
+ } else {
+ h->hashtable[hv] = n->next;
+ }
+ DelNode(n);
+ h->nitems--;
+ return 1;
+ }
+ prev = n;
+ n = n->next;
+ }
+ return 0;
+}
+
+static DohIterator Hash_firstiter(DOH *ho) {
+ DohIterator iter;
+ Hash *h = (Hash *) ObjData(ho);
+ iter.object = ho;
+ iter._current = 0;
+ iter.item = 0;
+ iter.key = 0;
+ iter._index = 0; /* Index in hash table */
+ while ((iter._index < h->hashsize) && !h->hashtable[iter._index])
+ iter._index++;
+
+ if (iter._index >= h->hashsize) {
+ return iter;
+ }
+ iter._current = h->hashtable[iter._index];
+ iter.item = ((HashNode *) iter._current)->object;
+ iter.key = ((HashNode *) iter._current)->key;
+
+ /* Actually save the next slot in the hash. This makes it possible to
+ delete the item being iterated over without trashing the universe */
+ iter._current = ((HashNode *) iter._current)->next;
+ return iter;
+}
+
+static DohIterator Hash_nextiter(DohIterator iter) {
+ Hash *h = (Hash *) ObjData(iter.object);
+ if (!iter._current) {
+ iter._index++;
+ while ((iter._index < h->hashsize) && !h->hashtable[iter._index]) {
+ iter._index++;
+ }
+ if (iter._index >= h->hashsize) {
+ iter.item = 0;
+ iter.key = 0;
+ iter._current = 0;
+ return iter;
+ }
+ iter._current = h->hashtable[iter._index];
+ }
+ iter.key = ((HashNode *) iter._current)->key;
+ iter.item = ((HashNode *) iter._current)->object;
+
+ /* Store the next node to iterator on */
+ iter._current = ((HashNode *) iter._current)->next;
+ return iter;
+}
+
+/* -----------------------------------------------------------------------------
+ * Hash_keys(DOH *)
+ *
+ * Return a list of keys
+ * ----------------------------------------------------------------------------- */
+
+static DOH *Hash_keys(DOH *so) {
+ DOH *keys;
+ Iterator i;
+
+ keys = NewList();
+ for (i = First(so); i.key; i = Next(i)) {
+ Append(keys, i.key);
+ }
+ return keys;
+}
+
+/* -----------------------------------------------------------------------------
+ * Hash_str()
+ *
+ * Create a string representation of a hash table (mainly for debugging).
+ * ----------------------------------------------------------------------------- */
+
+static DOH *Hash_str(DOH *ho) {
+ int i, j;
+ HashNode *n;
+ DOH *s;
+ static int indent = 4;
+ Hash *h = (Hash *) ObjData(ho);
+
+ s = NewStringEmpty();
+ if (ObjGetMark(ho)) {
+ Printf(s, "Hash(0x%x)", ho);
+ return s;
+ }
+ ObjSetMark(ho, 1);
+ Printf(s, "Hash {\n");
+ for (i = 0; i < h->hashsize; i++) {
+ n = h->hashtable[i];
+ while (n) {
+ for (j = 0; j < indent; j++)
+ Putc(' ', s);
+ indent += 4;
+ Printf(s, "'%s' : %s, \n", n->key, n->object);
+ indent -= 4;
+ n = n->next;
+ }
+ }
+ for (j = 0; j < (indent - 4); j++)
+ Putc(' ', s);
+ Printf(s, "}\n");
+ ObjSetMark(ho, 0);
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * Hash_len()
+ *
+ * Return number of entries in the hash table.
+ * ----------------------------------------------------------------------------- */
+
+static int Hash_len(DOH *ho) {
+ Hash *h = (Hash *) ObjData(ho);
+ return h->nitems;
+}
+
+/* -----------------------------------------------------------------------------
+ * CopyHash()
+ *
+ * Make a copy of a hash table. Note: this is a shallow copy.
+ * ----------------------------------------------------------------------------- */
+
+static DOH *CopyHash(DOH *ho) {
+ Hash *h, *nh;
+ HashNode *n;
+ DOH *nho;
+
+ int i;
+ h = (Hash *) ObjData(ho);
+ nh = (Hash *) DohMalloc(sizeof(Hash));
+ nh->hashsize = h->hashsize;
+ nh->hashtable = (HashNode **) DohMalloc(nh->hashsize * sizeof(HashNode *));
+ for (i = 0; i < nh->hashsize; i++) {
+ nh->hashtable[i] = 0;
+ }
+ nh->nitems = 0;
+ nh->line = h->line;
+ nh->file = h->file;
+ if (nh->file)
+ Incref(nh->file);
+
+ nho = DohObjMalloc(&DohHashType, nh);
+ for (i = 0; i < h->hashsize; i++) {
+ n = h->hashtable[i];
+ while (n) {
+ Hash_setattr(nho, n->key, n->object);
+ n = n->next;
+ }
+ }
+ return nho;
+}
+
+
+
+static void Hash_setfile(DOH *ho, DOH *file) {
+ DOH *fo;
+ Hash *h = (Hash *) ObjData(ho);
+
+ if (!DohCheck(file)) {
+ fo = NewString(file);
+ Decref(fo);
+ } else
+ fo = file;
+ Incref(fo);
+ Delete(h->file);
+ h->file = fo;
+}
+
+static DOH *Hash_getfile(DOH *ho) {
+ Hash *h = (Hash *) ObjData(ho);
+ return h->file;
+}
+
+static void Hash_setline(DOH *ho, int line) {
+ Hash *h = (Hash *) ObjData(ho);
+ h->line = line;
+}
+
+static int Hash_getline(DOH *ho) {
+ Hash *h = (Hash *) ObjData(ho);
+ return h->line;
+}
+
+/* -----------------------------------------------------------------------------
+ * type information
+ * ----------------------------------------------------------------------------- */
+
+static DohHashMethods HashHashMethods = {
+ Hash_getattr,
+ Hash_setattr,
+ Hash_delattr,
+ Hash_keys,
+};
+
+DohObjInfo DohHashType = {
+ "Hash", /* objname */
+ DelHash, /* doh_del */
+ CopyHash, /* doh_copy */
+ Hash_clear, /* doh_clear */
+ Hash_str, /* doh_str */
+ 0, /* doh_data */
+ 0, /* doh_dump */
+ Hash_len, /* doh_len */
+ 0, /* doh_hash */
+ 0, /* doh_cmp */
+ 0, /* doh_equal */
+ Hash_firstiter, /* doh_first */
+ Hash_nextiter, /* doh_next */
+ Hash_setfile, /* doh_setfile */
+ Hash_getfile, /* doh_getfile */
+ Hash_setline, /* doh_setline */
+ Hash_getline, /* doh_getline */
+ &HashHashMethods, /* doh_mapping */
+ 0, /* doh_sequence */
+ 0, /* doh_file */
+ 0, /* doh_string */
+ 0, /* doh_positional */
+ 0,
+};
+
+/* -----------------------------------------------------------------------------
+ * NewHash()
+ *
+ * Create a new hash table.
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohNewHash(void) {
+ Hash *h;
+ int i;
+ h = (Hash *) DohMalloc(sizeof(Hash));
+ h->hashsize = HASH_INIT_SIZE;
+ h->hashtable = (HashNode **) DohMalloc(h->hashsize * sizeof(HashNode *));
+ for (i = 0; i < h->hashsize; i++) {
+ h->hashtable[i] = 0;
+ }
+ h->nitems = 0;
+ h->file = 0;
+ h->line = 0;
+ return DohObjMalloc(&DohHashType, h);
+}
diff --git a/Source/DOH/list.c b/Source/DOH/list.c
new file mode 100644
index 0000000..b7e23ad
--- /dev/null
+++ b/Source/DOH/list.c
@@ -0,0 +1,377 @@
+/* -----------------------------------------------------------------------------
+ * list.c
+ *
+ * Implements a simple list object.
+ *
+ * Author(s) : David Beazley (beazley@cs.uchicago.edu)
+ *
+ * Copyright (C) 1999-2000. The University of Chicago
+ * See the file LICENSE for information on usage and redistribution.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_list_c[] = "$Id: list.c 10926 2008-11-11 22:17:40Z wsfulton $";
+
+#include "dohint.h"
+
+typedef struct List {
+ int maxitems; /* Max size */
+ int nitems; /* Num items */
+ DOH *file;
+ int line;
+ DOH **items;
+} List;
+
+extern DohObjInfo DohListType;
+
+/* Doubles amount of memory in a list */
+static
+void more(List *l) {
+ l->items = (void **) DohRealloc(l->items, l->maxitems * 2 * sizeof(void *));
+ assert(l->items);
+ l->maxitems *= 2;
+}
+
+/* -----------------------------------------------------------------------------
+ * CopyList()
+ *
+ * Make a shallow copy of a list.
+ * ----------------------------------------------------------------------------- */
+static DOH *CopyList(DOH *lo) {
+ List *l, *nl;
+ int i;
+ l = (List *) ObjData(lo);
+ nl = (List *) DohMalloc(sizeof(List));
+ nl->nitems = l->nitems;
+ nl->maxitems = l->maxitems;
+ nl->items = (void **) DohMalloc(l->maxitems * sizeof(void *));
+ for (i = 0; i < l->nitems; i++) {
+ nl->items[i] = l->items[i];
+ Incref(nl->items[i]);
+ }
+ nl->file = l->file;
+ if (nl->file)
+ Incref(nl->file);
+ nl->line = l->line;
+ return DohObjMalloc(&DohListType, nl);
+}
+
+/* -----------------------------------------------------------------------------
+ * DelList()
+ *
+ * Delete a list.
+ * ----------------------------------------------------------------------------- */
+
+static void DelList(DOH *lo) {
+ List *l = (List *) ObjData(lo);
+ int i;
+ for (i = 0; i < l->nitems; i++)
+ Delete(l->items[i]);
+ DohFree(l->items);
+ DohFree(l);
+}
+
+/* -----------------------------------------------------------------------------
+ * List_clear()
+ *
+ * Remove all of the list entries, but keep the list object intact.
+ * ----------------------------------------------------------------------------- */
+
+static void List_clear(DOH *lo) {
+ List *l = (List *) ObjData(lo);
+ int i;
+ for (i = 0; i < l->nitems; i++) {
+ Delete(l->items[i]);
+ }
+ l->nitems = 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * List_insert()
+ *
+ * Insert an item into the list. If the item is not a DOH object, it is assumed
+ * to be a 'char *' and is used to construct an equivalent string object.
+ * ----------------------------------------------------------------------------- */
+
+static int List_insert(DOH *lo, int pos, DOH *item) {
+ List *l = (List *) ObjData(lo);
+ int i;
+
+ if (!item)
+ return -1;
+ if (!DohCheck(item)) {
+ item = NewString(item);
+ Decref(item);
+ }
+ if (pos == DOH_END)
+ pos = l->nitems;
+ if (pos < 0)
+ pos = 0;
+ if (pos > l->nitems)
+ pos = l->nitems;
+ if (l->nitems == l->maxitems)
+ more(l);
+ for (i = l->nitems; i > pos; i--) {
+ l->items[i] = l->items[i - 1];
+ }
+ l->items[pos] = item;
+ Incref(item);
+ l->nitems++;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * List_remove()
+ *
+ * Remove an item from a list.
+ * ----------------------------------------------------------------------------- */
+
+static int List_remove(DOH *lo, int pos) {
+ List *l = (List *) ObjData(lo);
+ int i;
+ if (pos == DOH_END)
+ pos = l->nitems - 1;
+ if (pos == DOH_BEGIN)
+ pos = 0;
+ assert(!((pos < 0) || (pos >= l->nitems)));
+ Delete(l->items[pos]);
+ for (i = pos; i < l->nitems - 1; i++) {
+ l->items[i] = l->items[i + 1];
+ }
+ l->nitems--;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * List_len()
+ *
+ * Return the number of elements in the list
+ * ----------------------------------------------------------------------------- */
+
+static int List_len(DOH *lo) {
+ List *l = (List *) ObjData(lo);
+ return l->nitems;
+}
+
+/* -----------------------------------------------------------------------------
+ * List_get()
+ *
+ * Get the nth item from the list.
+ * ----------------------------------------------------------------------------- */
+
+static DOH *List_get(DOH *lo, int n) {
+ List *l = (List *) ObjData(lo);
+ if (n == DOH_END)
+ n = l->nitems - 1;
+ if (n == DOH_BEGIN)
+ n = 0;
+ assert(!((n < 0) || (n >= l->nitems)));
+ return l->items[n];
+}
+
+/* -----------------------------------------------------------------------------
+ * List_set()
+ *
+ * Set the nth item in the list replacing any previous item.
+ * ----------------------------------------------------------------------------- */
+
+static int List_set(DOH *lo, int n, DOH *val) {
+ List *l = (List *) ObjData(lo);
+ if (!val)
+ return -1;
+ assert(!((n < 0) || (n >= l->nitems)));
+ if (!DohCheck(val)) {
+ val = NewString(val);
+ Decref(val);
+ }
+ Delete(l->items[n]);
+ l->items[n] = val;
+ Incref(val);
+ Delete(val);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * List_first()
+ *
+ * Return the first item in the list.
+ * ----------------------------------------------------------------------------- */
+
+static DohIterator List_first(DOH *lo) {
+ DohIterator iter;
+ List *l = (List *) ObjData(lo);
+ iter.object = lo;
+ iter._index = 0;
+ iter._current = 0;
+ iter.key = 0;
+ if (l->nitems > 0) {
+ iter.item = l->items[0];
+ } else {
+ iter.item = 0;
+ }
+ return iter;
+}
+
+/* -----------------------------------------------------------------------------
+ * List_next()
+ *
+ * Return the next item in the list.
+ * ----------------------------------------------------------------------------- */
+
+static DohIterator List_next(DohIterator iter) {
+ List *l = (List *) ObjData(iter.object);
+ iter._index = iter._index + 1;
+ if (iter._index >= l->nitems) {
+ iter.item = 0;
+ iter.key = 0;
+ } else {
+ iter.item = l->items[iter._index];
+ }
+ return iter;
+}
+
+/* -----------------------------------------------------------------------------
+ * List_str()
+ *
+ * Create a string representation of the list.
+ * ----------------------------------------------------------------------------- */
+static DOH *List_str(DOH *lo) {
+ DOH *s;
+ int i;
+ List *l = (List *) ObjData(lo);
+ s = NewStringEmpty();
+ if (ObjGetMark(lo)) {
+ Printf(s, "List(%x)", lo);
+ return s;
+ }
+ ObjSetMark(lo, 1);
+ Printf(s, "List[ ");
+ for (i = 0; i < l->nitems; i++) {
+ Printf(s, "%s", l->items[i]);
+ if ((i + 1) < l->nitems)
+ Printf(s, ", ");
+ }
+ Printf(s, " ]\n");
+ ObjSetMark(lo, 0);
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * List_dump()
+ *
+ * Dump the items to an output stream.
+ * ----------------------------------------------------------------------------- */
+
+static int List_dump(DOH *lo, DOH *out) {
+ int nsent = 0;
+ int i, ret;
+ List *l = (List *) ObjData(lo);
+ for (i = 0; i < l->nitems; i++) {
+ ret = Dump(l->items[i], out);
+ if (ret < 0)
+ return -1;
+ nsent += ret;
+ }
+ return nsent;
+}
+
+static void List_setfile(DOH *lo, DOH *file) {
+ DOH *fo;
+ List *l = (List *) ObjData(lo);
+
+ if (!DohCheck(file)) {
+ fo = NewString(file);
+ Decref(fo);
+ } else
+ fo = file;
+ Incref(fo);
+ Delete(l->file);
+ l->file = fo;
+}
+
+static DOH *List_getfile(DOH *lo) {
+ List *l = (List *) ObjData(lo);
+ return l->file;
+}
+
+static void List_setline(DOH *lo, int line) {
+ List *l = (List *) ObjData(lo);
+ l->line = line;
+}
+
+static int List_getline(DOH *lo) {
+ List *l = (List *) ObjData(lo);
+ return l->line;
+}
+
+static DohListMethods ListListMethods = {
+ List_get,
+ List_set,
+ List_remove,
+ List_insert,
+ 0, /* delslice */
+};
+
+DohObjInfo DohListType = {
+ "List", /* objname */
+ DelList, /* doh_del */
+ CopyList, /* doh_copy */
+ List_clear, /* doh_clear */
+ List_str, /* doh_str */
+ 0, /* doh_data */
+ List_dump, /* doh_dump */
+ List_len, /* doh_len */
+ 0, /* doh_hash */
+ 0, /* doh_cmp */
+ 0, /* doh_equal */
+ List_first, /* doh_first */
+ List_next, /* doh_next */
+ List_setfile, /* doh_setfile */
+ List_getfile, /* doh_getfile */
+ List_setline, /* doh_setline */
+ List_getline, /* doh_getline */
+ 0, /* doh_mapping */
+ &ListListMethods, /* doh_sequence */
+ 0, /* doh_file */
+ 0, /* doh_string */
+ 0, /* doh_callable */
+ 0, /* doh_position */
+};
+
+/* -----------------------------------------------------------------------------
+ * NewList()
+ *
+ * Create a new list.
+ * ----------------------------------------------------------------------------- */
+
+#define MAXLISTITEMS 8
+
+DOH *DohNewList(void) {
+ List *l;
+ int i;
+ l = (List *) DohMalloc(sizeof(List));
+ l->nitems = 0;
+ l->maxitems = MAXLISTITEMS;
+ l->items = (void **) DohMalloc(l->maxitems * sizeof(void *));
+ for (i = 0; i < MAXLISTITEMS; i++) {
+ l->items[i] = 0;
+ }
+ l->file = 0;
+ l->line = 0;
+ return DohObjMalloc(&DohListType, l);
+}
+
+static int (*List_sort_compare_func) (const DOH *, const DOH *);
+static int List_qsort_compare(const void *a, const void *b) {
+ return List_sort_compare_func(*((DOH **) a), *((DOH **) b));
+}
+
+/* Sort a list */
+void DohSortList(DOH *lo, int (*cmp) (const DOH *, const DOH *)) {
+ List *l = (List *) ObjData(lo);
+ if (cmp) {
+ List_sort_compare_func = cmp;
+ } else {
+ List_sort_compare_func = DohCmp;
+ }
+ qsort(l->items, l->nitems, sizeof(DOH *), List_qsort_compare);
+}
diff --git a/Source/DOH/memory.c b/Source/DOH/memory.c
new file mode 100644
index 0000000..79ff21c
--- /dev/null
+++ b/Source/DOH/memory.c
@@ -0,0 +1,220 @@
+/* -----------------------------------------------------------------------------
+ * memory.c
+ *
+ * This file implements all of DOH's memory management including allocation
+ * of objects and checking of objects.
+ *
+ * Author(s) : David Beazley (beazley@cs.uchicago.edu)
+ *
+ * Copyright (C) 1999-2000. The University of Chicago
+ * See the file LICENSE for information on usage and redistribution.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_memory_c[] = "$Id: memory.c 9607 2006-12-05 22:11:40Z beazley $";
+
+#include "dohint.h"
+
+#ifndef DOH_POOL_SIZE
+#define DOH_POOL_SIZE 16384
+#endif
+
+static int PoolSize = DOH_POOL_SIZE;
+
+DOH *DohNone = 0; /* The DOH None object */
+
+typedef struct pool {
+ DohBase *ptr; /* Start of pool */
+ int len; /* Length of pool */
+ int blen; /* Byte length of pool */
+ int current; /* Current position for next allocation */
+ char *pbeg; /* Beg of pool */
+ char *pend; /* End of pool */
+ struct pool *next; /* Next pool */
+} Pool;
+
+static DohBase *FreeList = 0; /* List of free objects */
+static Pool *Pools = 0;
+static int pools_initialized = 0;
+
+/* ----------------------------------------------------------------------
+ * CreatePool() - Create a new memory pool
+ * ---------------------------------------------------------------------- */
+
+static void CreatePool() {
+ Pool *p = 0;
+ p = (Pool *) DohMalloc(sizeof(Pool));
+ assert(p);
+ p->ptr = (DohBase *) DohMalloc(sizeof(DohBase) * PoolSize);
+ assert(p->ptr);
+ memset(p->ptr, 0, sizeof(DohBase) * PoolSize);
+ p->len = PoolSize;
+ p->blen = PoolSize * sizeof(DohBase);
+ p->current = 0;
+ p->pbeg = ((char *) p->ptr);
+ p->pend = p->pbeg + p->blen;
+ p->next = Pools;
+ Pools = p;
+}
+
+/* ----------------------------------------------------------------------
+ * InitPools() - Initialize the memory allocator
+ * ---------------------------------------------------------------------- */
+
+static void InitPools() {
+ if (pools_initialized)
+ return;
+ CreatePool(); /* Create initial pool */
+ pools_initialized = 1;
+ DohNone = NewVoid(0, 0); /* Create the None object */
+ DohIntern(DohNone);
+}
+
+/* ----------------------------------------------------------------------
+ * DohCheck()
+ *
+ * Returns 1 if an arbitrary pointer is a DOH object.
+ * ---------------------------------------------------------------------- */
+
+int DohCheck(const DOH *ptr) {
+ register Pool *p = Pools;
+ register char *cptr = (char *) ptr;
+ while (p) {
+ if ((cptr >= p->pbeg) && (cptr < p->pend))
+ return 1;
+ /*
+ pptr = (char *) p->ptr;
+ if ((cptr >= pptr) && (cptr < (pptr+(p->current*sizeof(DohBase))))) return 1; */
+ p = p->next;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohIntern()
+ * ----------------------------------------------------------------------------- */
+
+void DohIntern(DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ b->flag_intern = 1;
+}
+
+/* ----------------------------------------------------------------------
+ * DohObjMalloc()
+ *
+ * Allocate memory for a new object.
+ * ---------------------------------------------------------------------- */
+
+DOH *DohObjMalloc(DohObjInfo *type, void *data) {
+ DohBase *obj;
+ if (!pools_initialized)
+ InitPools();
+ if (FreeList) {
+ obj = FreeList;
+ FreeList = (DohBase *) obj->data;
+ } else {
+ while (Pools->current == Pools->len) {
+ CreatePool();
+ }
+ obj = Pools->ptr + Pools->current;
+ ++Pools->current;
+ }
+ obj->type = type;
+ obj->data = data;
+ obj->meta = 0;
+ obj->refcount = 1;
+ obj->flag_intern = 0;
+ obj->flag_marked = 0;
+ obj->flag_user = 0;
+ obj->flag_usermark = 0;
+ return (DOH *) obj;
+}
+
+/* ----------------------------------------------------------------------
+ * DohObjFree() - Free a DOH object
+ * ---------------------------------------------------------------------- */
+
+void DohObjFree(DOH *ptr) {
+ DohBase *b, *meta;
+ b = (DohBase *) ptr;
+ if (b->flag_intern)
+ return;
+ meta = (DohBase *) b->meta;
+ b->data = (void *) FreeList;
+ b->meta = 0;
+ b->type = 0;
+ FreeList = b;
+ if (meta) {
+ Delete(meta);
+ }
+}
+
+/* ----------------------------------------------------------------------
+ * DohMemoryDebug()
+ *
+ * Display memory usage statistics
+ * ---------------------------------------------------------------------- */
+
+void DohMemoryDebug(void) {
+ extern DohObjInfo DohStringType;
+ extern DohObjInfo DohListType;
+ extern DohObjInfo DohHashType;
+
+ Pool *p;
+ int totsize = 0;
+ int totused = 0;
+ int totfree = 0;
+
+ int numstring = 0;
+ int numlist = 0;
+ int numhash = 0;
+
+ printf("Memory statistics:\n\n");
+ printf("Pools:\n");
+
+ p = Pools;
+ while (p) {
+ /* Calculate number of used, free items */
+ int i;
+ int nused = 0, nfree = 0;
+ for (i = 0; i < p->len; i++) {
+ if (p->ptr[i].refcount <= 0)
+ nfree++;
+ else {
+ nused++;
+ if (p->ptr[i].type == &DohStringType)
+ numstring++;
+ else if (p->ptr[i].type == &DohListType)
+ numlist++;
+ else if (p->ptr[i].type == &DohHashType)
+ numhash++;
+ }
+ }
+ printf(" Pool %8p: size = %10d. used = %10d. free = %10d\n", (void *) p, p->len, nused, nfree);
+ totsize += p->len;
+ totused += nused;
+ totfree += nfree;
+ p = p->next;
+ }
+ printf("\n Total: size = %10d, used = %10d, free = %10d\n", totsize, totused, totfree);
+
+ printf("\nObject types\n");
+ printf(" Strings : %d\n", numstring);
+ printf(" Lists : %d\n", numlist);
+ printf(" Hashes : %d\n", numhash);
+
+#if 0
+ p = Pools;
+ while (p) {
+ int i;
+ for (i = 0; i < p->len; i++) {
+ if (p->ptr[i].refcount > 0) {
+ if (p->ptr[i].type == &DohStringType) {
+ Printf(stdout, "%s\n", p->ptr + i);
+ }
+ }
+ }
+ p = p->next;
+ }
+#endif
+
+}
diff --git a/Source/DOH/string.c b/Source/DOH/string.c
new file mode 100644
index 0000000..425a39f
--- /dev/null
+++ b/Source/DOH/string.c
@@ -0,0 +1,1158 @@
+/* -----------------------------------------------------------------------------
+ * string.c
+ *
+ * Implements a string object that supports both sequence operations and
+ * file semantics.
+ *
+ * Author(s) : David Beazley (beazley@cs.uchicago.edu)
+ *
+ * Copyright (C) 1999-2000. The University of Chicago
+ * See the file LICENSE for information on usage and redistribution.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_string_c[] = "$Id: string.c 10926 2008-11-11 22:17:40Z wsfulton $";
+
+#include "dohint.h"
+
+extern DohObjInfo DohStringType;
+
+typedef struct String {
+ DOH *file;
+ int line;
+ int maxsize; /* Max size allocated */
+ int len; /* Current length */
+ int hashkey; /* Hash key value */
+ int sp; /* Current position */
+ char *str; /* String data */
+} String;
+
+/* -----------------------------------------------------------------------------
+ * void *String_data() - Return as a 'void *'
+ * ----------------------------------------------------------------------------- */
+
+static void *String_data(DOH *so) {
+ String *s = (String *) ObjData(so);
+ s->str[s->len] = 0;
+ return (void *) s->str;
+}
+
+/* static char *String_char(DOH *so) {
+ return (char *) String_data(so);
+}
+*/
+
+/* -----------------------------------------------------------------------------
+ * int String_dump() - Serialize a string onto out
+ * ----------------------------------------------------------------------------- */
+
+static int String_dump(DOH *so, DOH *out) {
+ int nsent;
+ int ret;
+ String *s = (String *) ObjData(so);
+ nsent = 0;
+ while (nsent < s->len) {
+ ret = Write(out, s->str + nsent, (s->len - nsent));
+ if (ret < 0)
+ return ret;
+ nsent += ret;
+ }
+ return nsent;
+}
+
+/* -----------------------------------------------------------------------------
+ * CopyString() - Copy a string
+ * ----------------------------------------------------------------------------- */
+
+static DOH *CopyString(DOH *so) {
+ String *str;
+ String *s = (String *) ObjData(so);
+ str = (String *) DohMalloc(sizeof(String));
+ str->hashkey = s->hashkey;
+ str->sp = s->sp;
+ str->line = s->line;
+ str->file = s->file;
+ if (str->file)
+ Incref(str->file);
+ str->str = (char *) DohMalloc(s->len + 1);
+ memcpy(str->str, s->str, s->len);
+ str->maxsize = s->len;
+ str->len = s->len;
+ str->str[str->len] = 0;
+
+ return DohObjMalloc(&DohStringType, str);
+}
+
+/* -----------------------------------------------------------------------------
+ * DelString() - Delete a string
+ * ----------------------------------------------------------------------------- */
+
+static void DelString(DOH *so) {
+ String *s = (String *) ObjData(so);
+ DohFree(s->str);
+ DohFree(s);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohString_len() - Length of a string
+ * ----------------------------------------------------------------------------- */
+
+static int String_len(DOH *so) {
+ String *s = (String *) ObjData(so);
+ return s->len;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * int String_cmp() - Compare two strings
+ * ----------------------------------------------------------------------------- */
+
+static int String_cmp(DOH *so1, DOH *so2) {
+ String *s1, *s2;
+ char *c1, *c2;
+ int maxlen, i;
+ s1 = (String *) ObjData(so1);
+ s2 = (String *) ObjData(so2);
+ maxlen = s1->len;
+ if (s2->len < maxlen)
+ maxlen = s2->len;
+ c1 = s1->str;
+ c2 = s2->str;
+ for (i = maxlen; i; --i, c1++, c2++) {
+ if (*c1 != *c2)
+ break;
+ }
+ if (i != 0) {
+ if (*c1 < *c2)
+ return -1;
+ else
+ return 1;
+ }
+ if (s1->len == s2->len)
+ return 0;
+ if (s1->len > s2->len)
+ return 1;
+ return -1;
+}
+
+/* -----------------------------------------------------------------------------
+ * int String_equal() - Say if two string are equal
+ * ----------------------------------------------------------------------------- */
+
+static int String_equal(DOH *so1, DOH *so2) {
+ String *s1 = (String *) ObjData(so1);
+ String *s2 = (String *) ObjData(so2);
+ register int len = s1->len;
+ if (len != s2->len) {
+ return 0;
+ } else {
+ register char *c1 = s1->str;
+ register char *c2 = s2->str;
+#if 0
+ register int mlen = len >> 2;
+ register int i = mlen;
+ for (; i; --i) {
+ if (*(c1++) != *(c2++))
+ return 0;
+ if (*(c1++) != *(c2++))
+ return 0;
+ if (*(c1++) != *(c2++))
+ return 0;
+ if (*(c1++) != *(c2++))
+ return 0;
+ }
+ for (i = len - (mlen << 2); i; --i) {
+ if (*(c1++) != *(c2++))
+ return 0;
+ }
+ return 1;
+#else
+ return memcmp(c1, c2, len) == 0;
+#endif
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * int String_hash() - Compute string hash value
+ * ----------------------------------------------------------------------------- */
+
+static int String_hash(DOH *so) {
+ String *s = (String *) ObjData(so);
+ if (s->hashkey >= 0) {
+ return s->hashkey;
+ } else {
+ register char *c = s->str;
+ register int len = s->len > 50 ? 50 : s->len;
+ register int h = 0;
+ register int mlen = len >> 2;
+ register int i = mlen;
+ for (; i; --i) {
+ h = (h << 5) + *(c++);
+ h = (h << 5) + *(c++);
+ h = (h << 5) + *(c++);
+ h = (h << 5) + *(c++);
+ }
+ for (i = len - (mlen << 2); i; --i) {
+ h = (h << 5) + *(c++);
+ }
+ h &= 0x7fffffff;
+ s->hashkey = h;
+ return h;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * DohString_append(String *s, const char *newstr) - Append to s
+ * ----------------------------------------------------------------------------- */
+
+void DohString_append(DOH *so, DOH *str) {
+ int oldlen, newlen, newmaxsize, l, sp;
+ char *tc;
+ String *s = (String *) ObjData(so);
+ char *newstr = 0;
+
+ if (DohCheck(str)) {
+ String *ss = (String *) ObjData(str);
+ newstr = (char *) String_data((DOH *) str);
+ l = ss->len;
+ } else {
+ newstr = (char *) (str);
+ l = (int) strlen(newstr);
+ }
+ if (!newstr)
+ return;
+ s->hashkey = -1;
+
+ oldlen = s->len;
+ newlen = oldlen + l + 1;
+ if (newlen >= s->maxsize - 1) {
+ newmaxsize = 2 * s->maxsize;
+ if (newlen >= newmaxsize - 1)
+ newmaxsize = newlen + 1;
+ s->str = (char *) DohRealloc(s->str, newmaxsize);
+ assert(s->str);
+ s->maxsize = newmaxsize;
+ }
+ tc = s->str;
+ memcpy(tc + oldlen, newstr, l + 1);
+ sp = s->sp;
+ if (sp >= oldlen) {
+ int i = oldlen + l - sp;
+ tc += sp;
+ for (; i; --i) {
+ if (*(tc++) == '\n')
+ s->line++;
+ }
+ s->sp = oldlen + l;
+ }
+ s->len += l;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * void String_clear() - Clear a string
+ * ----------------------------------------------------------------------------- */
+
+static void String_clear(DOH *so) {
+ String *s = (String *) ObjData(so);
+ s->hashkey = -1;
+ s->len = 0;
+ *(s->str) = 0;
+ s->sp = 0;
+ s->line = 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * void String_insert() - Insert a string
+ * ----------------------------------------------------------------------------- */
+
+static int String_insert(DOH *so, int pos, DOH *str) {
+ String *s;
+ char *nstr;
+ int len;
+ char *data;
+
+ if (pos == DOH_END) {
+ DohString_append(so, str);
+ return 0;
+ }
+
+
+ s = (String *) ObjData(so);
+ s->hashkey = -1;
+ if (DohCheck(str)) {
+ String *ss = (String *) ObjData(str);
+ data = (char *) String_data(str);
+ len = ss->len;
+ } else {
+ data = (char *) (str);
+ len = (int) strlen(data);
+ }
+ nstr = s->str;
+
+ if (pos < 0)
+ pos = 0;
+ else if (pos > s->len)
+ pos = s->len;
+
+ /* See if there is room to insert the new data */
+ while (s->maxsize <= s->len + len) {
+ int newsize = 2 * s->maxsize;
+ s->str = (char *) DohRealloc(s->str, newsize);
+ assert(s->str);
+ s->maxsize = newsize;
+ }
+ memmove(s->str + pos + len, s->str + pos, (s->len - pos));
+ memcpy(s->str + pos, data, len);
+ if (s->sp >= pos) {
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (data[i] == '\n')
+ s->line++;
+ }
+ s->sp += len;
+ }
+ s->len += len;
+ s->str[s->len] = 0;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * int String_delitem() - Delete a character
+ * ----------------------------------------------------------------------------- */
+
+static int String_delitem(DOH *so, int pos) {
+ String *s = (String *) ObjData(so);
+ s->hashkey = -1;
+ if (pos == DOH_END)
+ pos = s->len - 1;
+ if (pos == DOH_BEGIN)
+ pos = 0;
+ if (s->len == 0)
+ return 0;
+
+ if (s->sp > pos) {
+ s->sp--;
+ assert(s->sp >= 0);
+ if (s->str[pos] == '\n')
+ s->line--;
+ }
+ memmove(s->str + pos, s->str + pos + 1, ((s->len - 1) - pos));
+ s->len--;
+ s->str[s->len] = 0;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * int String_delslice() - Delete a range
+ * ----------------------------------------------------------------------------- */
+
+static int String_delslice(DOH *so, int sindex, int eindex) {
+ String *s = (String *) ObjData(so);
+ int size;
+ if (s->len == 0)
+ return 0;
+ s->hashkey = -1;
+ if (eindex == DOH_END)
+ eindex = s->len;
+ if (sindex == DOH_BEGIN)
+ sindex = 0;
+
+ size = eindex - sindex;
+ if (s->sp > sindex) {
+ /* Adjust the file pointer and line count */
+ int i, end;
+ if (s->sp > eindex) {
+ end = eindex;
+ s->sp -= size;
+ } else {
+ end = s->sp;
+ s->sp = sindex;
+ }
+ for (i = sindex; i < end; i++) {
+ if (s->str[i] == '\n')
+ s->line--;
+ }
+ assert(s->sp >= 0);
+ }
+ memmove(s->str + sindex, s->str + eindex, s->len - eindex);
+ s->len -= size;
+ s->str[s->len] = 0;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DOH *String_str() - Returns a string (used by printing commands)
+ * ----------------------------------------------------------------------------- */
+
+static DOH *String_str(DOH *so) {
+ String *s = (String *) ObjData(so);
+ s->str[s->len] = 0;
+ return NewString(s->str);
+}
+
+/* -----------------------------------------------------------------------------
+ * int String_read() - Read data from a string
+ * ----------------------------------------------------------------------------- */
+
+static int String_read(DOH *so, void *buffer, int len) {
+ int reallen, retlen;
+ char *cb;
+ String *s = (String *) ObjData(so);
+ if ((s->sp + len) > s->len)
+ reallen = (s->len - s->sp);
+ else
+ reallen = len;
+
+ cb = (char *) buffer;
+ retlen = reallen;
+
+ if (reallen > 0) {
+ memmove(cb, s->str + s->sp, reallen);
+ s->sp += reallen;
+ }
+ return retlen;
+}
+
+/* -----------------------------------------------------------------------------
+ * int String_write() - Write data to a string
+ * ----------------------------------------------------------------------------- */
+static int String_write(DOH *so, void *buffer, int len) {
+ int newlen;
+ String *s = (String *) ObjData(so);
+ s->hashkey = -1;
+ if (s->sp > s->len)
+ s->sp = s->len;
+ newlen = s->sp + len + 1;
+ if (newlen > s->maxsize) {
+ s->str = (char *) DohRealloc(s->str, newlen);
+ assert(s->str);
+ s->maxsize = newlen;
+ s->len = s->sp + len;
+ }
+ if ((s->sp + len) > s->len)
+ s->len = s->sp + len;
+ memmove(s->str + s->sp, buffer, len);
+ s->sp += len;
+ s->str[s->len] = 0;
+ return len;
+}
+
+/* -----------------------------------------------------------------------------
+ * int String_seek() - Seek to a new position
+ * ----------------------------------------------------------------------------- */
+
+static int String_seek(DOH *so, long offset, int whence) {
+ int pos, nsp, inc;
+ String *s = (String *) ObjData(so);
+ if (whence == SEEK_SET)
+ pos = 0;
+ else if (whence == SEEK_CUR)
+ pos = s->sp;
+ else if (whence == SEEK_END) {
+ pos = s->len;
+ offset = -offset;
+ } else
+ pos = s->sp;
+
+ nsp = pos + offset;
+ if (nsp < 0)
+ nsp = 0;
+ if (s->len > 0 && nsp > s->len)
+ nsp = s->len;
+
+ inc = (nsp > s->sp) ? 1 : -1;
+
+ {
+#if 0
+ register int sp = s->sp;
+ register char *tc = s->str;
+ register int len = s->len;
+ while (sp != nsp) {
+ int prev = sp + inc;
+ if (prev >= 0 && prev <= len && tc[prev] == '\n')
+ s->line += inc;
+ sp += inc;
+ }
+#else
+ register int sp = s->sp;
+ register char *tc = s->str;
+ if (inc > 0) {
+ while (sp != nsp) {
+ if (tc[++sp] == '\n')
+ ++s->line;
+ }
+ } else {
+ while (sp != nsp) {
+ if (tc[--sp] == '\n')
+ --s->line;
+ }
+ }
+#endif
+ s->sp = sp;
+ }
+ assert(s->sp >= 0);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * long String_tell() - Return current position
+ * ----------------------------------------------------------------------------- */
+
+static long String_tell(DOH *so) {
+ String *s = (String *) ObjData(so);
+ return (long) (s->sp);
+}
+
+/* -----------------------------------------------------------------------------
+ * int String_putc()
+ * ----------------------------------------------------------------------------- */
+
+static int String_putc(DOH *so, int ch) {
+ String *s = (String *) ObjData(so);
+ register int len = s->len;
+ register int sp = s->sp;
+ s->hashkey = -1;
+ if (sp >= len) {
+ register int maxsize = s->maxsize;
+ register char *tc = s->str;
+ if (len > (maxsize - 2)) {
+ maxsize *= 2;
+ tc = (char *) DohRealloc(tc, maxsize);
+ assert(tc);
+ s->maxsize = (int) maxsize;
+ s->str = tc;
+ }
+ tc += sp;
+ *tc = (char) ch;
+ *(++tc) = 0;
+ s->len = s->sp = sp + 1;
+ } else {
+ s->str[s->sp++] = (char) ch;
+ }
+ if (ch == '\n')
+ s->line++;
+ return ch;
+}
+
+/* -----------------------------------------------------------------------------
+ * int String_getc()
+ * ----------------------------------------------------------------------------- */
+
+static int String_getc(DOH *so) {
+ int c;
+ String *s = (String *) ObjData(so);
+ if (s->sp >= s->len)
+ c = EOF;
+ else
+ c = (int)(unsigned char) s->str[s->sp++];
+ if (c == '\n')
+ s->line++;
+ return c;
+}
+
+/* -----------------------------------------------------------------------------
+ * int String_ungetc()
+ * ----------------------------------------------------------------------------- */
+
+static int String_ungetc(DOH *so, int ch) {
+ String *s = (String *) ObjData(so);
+ if (ch == EOF)
+ return ch;
+ if (s->sp <= 0)
+ return EOF;
+ s->sp--;
+ if (ch == '\n')
+ s->line--;
+ return ch;
+}
+
+/* -----------------------------------------------------------------------------
+ * replace_simple(String *str, char *token, char *rep, int flags, int count)
+ *
+ * Replaces count non-overlapping occurrences of token with rep in a string.
+ * ----------------------------------------------------------------------------- */
+
+static char *end_quote(char *s) {
+ char *qs;
+ char qc;
+ char *q;
+ char *nl;
+ qc = *s;
+ qs = s;
+ while (1) {
+ q = strpbrk(s + 1, "\"\'");
+ nl = strchr(s + 1, '\n');
+ if (nl && (nl < q)) {
+ /* A new line appears before the end of the string */
+ if (*(nl - 1) == '\\') {
+ s = nl + 1;
+ continue;
+ }
+ /* String was terminated by a newline. Wing it */
+ return qs;
+ }
+ if (!q && nl) {
+ return qs;
+ }
+ if (!q)
+ return 0;
+ if ((*q == qc) && (*(q - 1) != '\\'))
+ return q;
+ s = q;
+ }
+}
+
+static char *match_simple(char *base, char *s, char *token, int tokenlen) {
+ (void) base;
+ (void) tokenlen;
+ return strstr(s, token);
+}
+
+static char *match_identifier(char *base, char *s, char *token, int tokenlen) {
+ while (s) {
+ s = strstr(s, token);
+ if (!s)
+ return 0;
+ if ((s > base) && (isalnum((int) *(s - 1)) || (*(s - 1) == '_'))) {
+ s += tokenlen;
+ continue;
+ }
+ if (isalnum((int) *(s + tokenlen)) || (*(s + tokenlen) == '_')) {
+ s += tokenlen;
+ continue;
+ }
+ return s;
+ }
+ return 0;
+}
+
+
+static char *match_identifier_begin(char *base, char *s, char *token, int tokenlen) {
+ while (s) {
+ s = strstr(s, token);
+ if (!s)
+ return 0;
+ if ((s > base) && (isalnum((int) *(s - 1)) || (*(s - 1) == '_'))) {
+ s += tokenlen;
+ continue;
+ }
+ return s;
+ }
+ return 0;
+}
+
+static char *match_identifier_end(char *base, char *s, char *token, int tokenlen) {
+ (void) base;
+ while (s) {
+ s = strstr(s, token);
+ if (!s)
+ return 0;
+ if (isalnum((int) *(s + tokenlen)) || (*(s + tokenlen) == '_')) {
+ s += tokenlen;
+ continue;
+ }
+ return s;
+ }
+ return 0;
+}
+
+static int replace_simple(String *str, char *token, char *rep, int flags, int count, char *(*match) (char *, char *, char *, int)) {
+ int tokenlen; /* Length of the token */
+ int replen; /* Length of the replacement */
+ int delta, expand = 0;
+ int ic;
+ int rcount = 0;
+ int noquote = 0;
+ char *c, *s, *t, *first;
+ char *q, *q2;
+ register char *base;
+ int i;
+
+ /* Figure out if anything gets replaced */
+ if (!strlen(token))
+ return 0;
+
+ base = str->str;
+ tokenlen = strlen(token);
+ s = (*match) (base, base, token, tokenlen);
+
+ if (!s)
+ return 0; /* No matches. Who cares */
+
+ str->hashkey = -1;
+
+ if (flags & DOH_REPLACE_NOQUOTE)
+ noquote = 1;
+
+ /* If we are not replacing inside quotes, we need to do a little extra work */
+ if (noquote) {
+ q = strpbrk(base, "\"\'");
+ if (!q) {
+ noquote = 0; /* Well, no quotes to worry about. Oh well */
+ } else {
+ while (q && (q < s)) {
+ /* First match was found inside a quote. Try to find another match */
+ q2 = end_quote(q);
+ if (!q2) {
+ return 0;
+ }
+ if (q2 > s) {
+ /* Find next match */
+ s = (*match) (base, q2 + 1, token, tokenlen);
+ }
+ if (!s)
+ return 0; /* Oh well, no matches */
+ q = strpbrk(q2 + 1, "\"\'");
+ if (!q)
+ noquote = 0; /* No more quotes */
+ }
+ }
+ }
+
+ first = s;
+ replen = strlen(rep);
+
+ delta = (replen - tokenlen);
+
+ if (delta <= 0) {
+ /* String is either shrinking or staying the same size */
+ /* In this case, we do the replacement in place without memory reallocation */
+ ic = count;
+ t = s; /* Target of memory copies */
+ while (ic && s) {
+ if (replen) {
+ memcpy(t, rep, replen);
+ t += replen;
+ }
+ rcount++;
+ expand += delta;
+ /* Find the next location */
+ s += tokenlen;
+ if (ic == 1)
+ break;
+ c = (*match) (base, s, token, tokenlen);
+
+ if (noquote) {
+ q = strpbrk(s, "\"\'");
+ if (!q) {
+ noquote = 0;
+ } else {
+ while (q && (q < c)) {
+ /* First match was found inside a quote. Try to find another match */
+ q2 = end_quote(q);
+ if (!q2) {
+ c = 0;
+ break;
+ }
+ if (q2 > c)
+ c = (*match) (base, q2 + 1, token, tokenlen);
+ if (!c)
+ break;
+ q = strpbrk(q2 + 1, "\"\'");
+ if (!q)
+ noquote = 0; /* No more quotes */
+ }
+ }
+ }
+ if (delta) {
+ if (c) {
+ memmove(t, s, c - s);
+ t += (c - s);
+ } else {
+ memmove(t, s, (str->str + str->len) - s + 1);
+ }
+ } else {
+ t += (c - s);
+ }
+ s = c;
+ ic--;
+ }
+ if (s && delta) {
+ memmove(t, s, (str->str + str->len) - s + 1);
+ }
+ str->len += expand;
+ str->str[str->len] = 0;
+ if (str->sp >= str->len)
+ str->sp += expand; /* Fix the end of file pointer */
+ return rcount;
+ }
+ /* The string is expanding as a result of the replacement */
+ /* Figure out how much expansion is going to occur and allocate a new string */
+ {
+ char *ns;
+ int newsize;
+
+ rcount++;
+ ic = count - 1;
+ s += tokenlen;
+ while (ic && (c = (*match) (base, s, token, tokenlen))) {
+ if (noquote) {
+ q = strpbrk(s, "\"\'");
+ if (!q) {
+ break;
+ } else {
+ while (q && (q < c)) {
+ /* First match was found inside a quote. Try to find another match */
+ q2 = end_quote(q);
+ if (!q2) {
+ c = 0;
+ break;
+ }
+ if (q2 > c) {
+ c = (*match) (base, q2 + 1, token, tokenlen);
+ if (!c)
+ break;
+ }
+ q = strpbrk(q2 + 1, "\"\'");
+ if (!q)
+ noquote = 0;
+ }
+ }
+ }
+ if (c) {
+ rcount++;
+ ic--;
+ s = c + tokenlen;
+ } else {
+ break;
+ }
+ }
+
+ expand = delta * rcount; /* Total amount of expansion for the replacement */
+ newsize = str->maxsize;
+ while ((str->len + expand) >= newsize)
+ newsize *= 2;
+
+ ns = (char *) DohMalloc(newsize);
+ assert(ns);
+ t = ns;
+ s = first;
+
+ /* Copy the first part of the string */
+ if (first > str->str) {
+ memcpy(t, str->str, (first - str->str));
+ t += (first - str->str);
+ }
+ for (i = 0; i < rcount; i++) {
+ memcpy(t, rep, replen);
+ t += replen;
+ s += tokenlen;
+ c = (*match) (base, s, token, tokenlen);
+ if (noquote) {
+ q = strpbrk(s, "\"\'");
+ if (!q) {
+ noquote = 0;
+ } else {
+ while (q && (q < c)) {
+ /* First match was found inside a quote. Try to find another match */
+ q2 = end_quote(q);
+ if (!q2) {
+ c = 0;
+ break;
+ }
+ if (q2 > c) {
+ c = (*match) (base, q2 + 1, token, tokenlen);
+ if (!c)
+ break;
+ }
+ q = strpbrk(q2 + 1, "\"\'");
+ if (!q)
+ noquote = 0; /* No more quotes */
+ }
+ }
+ }
+ if (i < (rcount - 1)) {
+ memcpy(t, s, c - s);
+ t += (c - s);
+ } else {
+ memcpy(t, s, (str->str + str->len) - s + 1);
+ }
+ s = c;
+ }
+ c = str->str;
+ str->str = ns;
+ if (str->sp >= str->len)
+ str->sp += expand;
+ str->len += expand;
+ str->str[str->len] = 0;
+ str->maxsize = newsize;
+ DohFree(c);
+ return rcount;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * int String_replace()
+ * ----------------------------------------------------------------------------- */
+
+static int String_replace(DOH *stro, DOH *token, DOH *rep, int flags) {
+ int count = -1;
+ String *str = (String *) ObjData(stro);
+
+ if (flags & DOH_REPLACE_FIRST)
+ count = 1;
+
+ if (flags & DOH_REPLACE_ID_END) {
+ return replace_simple(str, Char(token), Char(rep), flags, count, match_identifier_end);
+ } else if (flags & DOH_REPLACE_ID_BEGIN) {
+ return replace_simple(str, Char(token), Char(rep), flags, count, match_identifier_begin);
+ } else if (flags & DOH_REPLACE_ID) {
+ return replace_simple(str, Char(token), Char(rep), flags, count, match_identifier);
+ } else {
+ return replace_simple(str, Char(token), Char(rep), flags, count, match_simple);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * void String_chop(DOH *str)
+ * ----------------------------------------------------------------------------- */
+
+static void String_chop(DOH *so) {
+ char *c;
+ String *str = (String *) ObjData(so);
+ /* Replace trailing whitespace */
+ c = str->str + str->len - 1;
+ while ((str->len > 0) && (isspace((int) *c))) {
+ if (str->sp >= str->len) {
+ str->sp--;
+ if (*c == '\n')
+ str->line--;
+ }
+ str->len--;
+ c--;
+ }
+ str->str[str->len] = 0;
+ assert(str->sp >= 0);
+ str->hashkey = -1;
+}
+
+static void String_setfile(DOH *so, DOH *file) {
+ DOH *fo;
+ String *str = (String *) ObjData(so);
+
+ if (!DohCheck(file)) {
+ fo = NewString(file);
+ Decref(fo);
+ } else
+ fo = file;
+ Incref(fo);
+ Delete(str->file);
+ str->file = fo;
+}
+
+static DOH *String_getfile(DOH *so) {
+ String *str = (String *) ObjData(so);
+ return str->file;
+}
+
+static void String_setline(DOH *so, int line) {
+ String *str = (String *) ObjData(so);
+ str->line = line;
+}
+
+static int String_getline(DOH *so) {
+ String *str = (String *) ObjData(so);
+ return str->line;
+}
+
+static DohListMethods StringListMethods = {
+ 0, /* doh_getitem */
+ 0, /* doh_setitem */
+ String_delitem, /* doh_delitem */
+ String_insert, /* doh_insitem */
+ String_delslice, /* doh_delslice */
+};
+
+static DohFileMethods StringFileMethods = {
+ String_read,
+ String_write,
+ String_putc,
+ String_getc,
+ String_ungetc,
+ String_seek,
+ String_tell,
+ 0, /* close */
+};
+
+static DohStringMethods StringStringMethods = {
+ String_replace,
+ String_chop,
+};
+
+DohObjInfo DohStringType = {
+ "String", /* objname */
+ DelString, /* doh_del */
+ CopyString, /* doh_copy */
+ String_clear, /* doh_clear */
+ String_str, /* doh_str */
+ String_data, /* doh_data */
+ String_dump, /* doh_dump */
+ String_len, /* doh_len */
+ String_hash, /* doh_hash */
+ String_cmp, /* doh_cmp */
+ String_equal, /* doh_equal */
+ 0, /* doh_first */
+ 0, /* doh_next */
+ String_setfile, /* doh_setfile */
+ String_getfile, /* doh_getfile */
+ String_setline, /* doh_setline */
+ String_getline, /* doh_getline */
+ 0, /* doh_mapping */
+ &StringListMethods, /* doh_sequence */
+ &StringFileMethods, /* doh_file */
+ &StringStringMethods, /* doh_string */
+ 0, /* doh_position */
+ 0
+};
+
+
+#define INIT_MAXSIZE 16
+
+/* -----------------------------------------------------------------------------
+ * NewString(const char *c) - Create a new string
+ * ----------------------------------------------------------------------------- */
+
+DOHString *DohNewString(const DOH *so) {
+ int l = 0, max;
+ String *str;
+ char *s;
+ int hashkey = -1;
+ if (DohCheck(so)) {
+ str = (String *) ObjData(so);
+ s = (char *) String_data((String *) so);
+ l = s ? str->len : 0;
+ hashkey = str->hashkey;
+ } else {
+ s = (char *) so;
+ l = s ? (int) strlen(s) : 0;
+ }
+
+ str = (String *) DohMalloc(sizeof(String));
+ str->hashkey = hashkey;
+ str->sp = 0;
+ str->line = 1;
+ str->file = 0;
+ max = INIT_MAXSIZE;
+ if (s) {
+ if ((l + 1) > max)
+ max = l + 1;
+ }
+ str->str = (char *) DohMalloc(max);
+ str->maxsize = max;
+ if (s) {
+ strcpy(str->str, s);
+ str->len = l;
+ str->sp = l;
+ } else {
+ str->str[0] = 0;
+ str->len = 0;
+ }
+ return DohObjMalloc(&DohStringType, str);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * NewStringEmpty() - Create a new string
+ * ----------------------------------------------------------------------------- */
+
+DOHString *DohNewStringEmpty(void) {
+ int max = INIT_MAXSIZE;
+ String *str = (String *) DohMalloc(sizeof(String));
+ str->hashkey = 0;
+ str->sp = 0;
+ str->line = 1;
+ str->file = 0;
+ str->str = (char *) DohMalloc(max);
+ str->maxsize = max;
+ str->str[0] = 0;
+ str->len = 0;
+ return DohObjMalloc(&DohStringType, str);
+}
+
+/* -----------------------------------------------------------------------------
+ * NewStringWithSize(const char *c, int len) - Create a new string
+ * ----------------------------------------------------------------------------- */
+
+DOHString *DohNewStringWithSize(const DOH *so, int len) {
+ int l = 0, max;
+ String *str;
+ char *s;
+ if (DohCheck(so)) {
+ s = (char *) String_data((String *) so);
+ } else {
+ s = (char *) so;
+ }
+
+ str = (String *) DohMalloc(sizeof(String));
+ str->hashkey = -1;
+ str->sp = 0;
+ str->line = 1;
+ str->file = 0;
+ max = INIT_MAXSIZE;
+ if (s) {
+ l = (int) len;
+ if ((l + 1) > max)
+ max = l + 1;
+ }
+ str->str = (char *) DohMalloc(max);
+ str->maxsize = max;
+ if (s) {
+ strncpy(str->str, s, len);
+ str->len = l;
+ str->sp = l;
+ } else {
+ str->str[0] = 0;
+ str->len = 0;
+ }
+ return DohObjMalloc(&DohStringType, str);
+}
+
+/* -----------------------------------------------------------------------------
+ * NewStringf(DOH *fmt, ...)
+ *
+ * Create a new string from a list of objects.
+ * ----------------------------------------------------------------------------- */
+
+DOHString *DohNewStringf(const DOH *fmt, ...) {
+ va_list ap;
+ DOH *r;
+ va_start(ap, fmt);
+ r = NewStringEmpty();
+ DohvPrintf(r, Char(fmt), ap);
+ va_end(ap);
+ return (DOHString *) r;
+}
+
+/* -----------------------------------------------------------------------------
+ * Strcmp()
+ * Strncmp()
+ * Strstr()
+ * Strchr()
+ *
+ * Some utility functions.
+ * ----------------------------------------------------------------------------- */
+
+int DohStrcmp(const DOHString_or_char *s1, const DOHString_or_char *s2) {
+ const char *c1 = Char(s1);
+ const char *c2 = Char(s2);
+ if (c1 && c2) {
+ return strcmp(c1, c2);
+ } else {
+ return c1 < c2;
+ }
+}
+
+int DohStrncmp(const DOHString_or_char *s1, const DOHString_or_char *s2, int n) {
+ return strncmp(Char(s1), Char(s2), n);
+}
+
+char *DohStrstr(const DOHString_or_char *s1, const DOHString_or_char *s2) {
+ char *p1 = Char(s1);
+ char *p2 = Char(s2);
+ return p1 == 0 || p2 == 0 || *p2 == '\0' ? p1 : strstr(p1, p2);
+}
+
+char *DohStrchr(const DOHString_or_char *s1, int ch) {
+ return strchr(Char(s1), ch);
+}
diff --git a/Source/DOH/void.c b/Source/DOH/void.c
new file mode 100644
index 0000000..ed34da1
--- /dev/null
+++ b/Source/DOH/void.c
@@ -0,0 +1,96 @@
+/* -----------------------------------------------------------------------------
+ * void.c
+ *
+ * Implements a "void" object that is really just a DOH container around
+ * an arbitrary C object represented as a void *.
+ *
+ * Author(s) : David Beazley (beazley@cs.uchicago.edu)
+ *
+ * Copyright (C) 1999-2000. The University of Chicago
+ * See the file LICENSE for information on usage and redistribution.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_void_c[] = "$Id: void.c 9607 2006-12-05 22:11:40Z beazley $";
+
+#include "dohint.h"
+
+typedef struct {
+ void *ptr;
+ void (*del) (void *);
+} VoidObj;
+
+/* -----------------------------------------------------------------------------
+ * Void_delete()
+ *
+ * Delete a void object. Invokes the destructor supplied at the time of creation.
+ * ----------------------------------------------------------------------------- */
+
+static void Void_delete(DOH *vo) {
+ VoidObj *v = (VoidObj *) ObjData(vo);
+ if (v->del)
+ (*v->del) (v->ptr);
+ DohFree(v);
+}
+
+/* -----------------------------------------------------------------------------
+ * Void_copy()
+ *
+ * Copies a void object. This is only a shallow copy. The object destruction
+ * function is not copied in order to avoid potential double-free problems.
+ * ----------------------------------------------------------------------------- */
+
+static DOH *Void_copy(DOH *vo) {
+ VoidObj *v = (VoidObj *) ObjData(vo);
+ return NewVoid(v->ptr, 0);
+}
+
+/* -----------------------------------------------------------------------------
+ * Void_data()
+ *
+ * Returns the void * stored in the object.
+ * ----------------------------------------------------------------------------- */
+
+static void *Void_data(DOH *vo) {
+ VoidObj *v = (VoidObj *) ObjData(vo);
+ return v->ptr;
+}
+
+static DohObjInfo DohVoidType = {
+ "VoidObj", /* objname */
+ Void_delete, /* doh_del */
+ Void_copy, /* doh_copy */
+ 0, /* doh_clear */
+ 0, /* doh_str */
+ Void_data, /* doh_data */
+ 0, /* doh_dump */
+ 0, /* doh_len */
+ 0, /* doh_hash */
+ 0, /* doh_cmp */
+ 0, /* doh_equal */
+ 0, /* doh_first */
+ 0, /* doh_next */
+ 0, /* doh_setfile */
+ 0, /* doh_getfile */
+ 0, /* doh_setline */
+ 0, /* doh_getline */
+ 0, /* doh_mapping */
+ 0, /* doh_sequence */
+ 0, /* doh_file */
+ 0, /* doh_string */
+ 0, /* doh_reserved */
+ 0, /* clientdata */
+};
+
+/* -----------------------------------------------------------------------------
+ * NewVoid()
+ *
+ * Creates a new Void object given a void * and an optional destructor function.
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohNewVoid(void *obj, void (*del) (void *)) {
+ VoidObj *v;
+ v = (VoidObj *) DohMalloc(sizeof(VoidObj));
+ v->ptr = obj;
+ v->del = del;
+ return DohObjMalloc(&DohVoidType, v);
+}