base.c   [plain text]


/* -----------------------------------------------------------------------------
 * 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;
}