summaryrefslogtreecommitdiff
path: root/Source/DOH/base.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DOH/base.c')
-rw-r--r--Source/DOH/base.c943
1 files changed, 943 insertions, 0 deletions
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;
+}