PageRenderTime 96ms CodeModel.GetById 14ms app.highlight 75ms RepoModel.GetById 2ms app.codeStats 0ms

/trunk/Source/DOH/base.c

#
C | 957 lines | 631 code | 125 blank | 201 comment | 148 complexity | 9b47118af697d0167f3b276ce2ad8964 MD5 | raw file
  1/* -----------------------------------------------------------------------------
  2 * This file is part of SWIG, which is licensed as a whole under version 3 
  3 * (or any later version) of the GNU General Public License. Some additional
  4 * terms also apply to certain portions of SWIG. The full details of the SWIG
  5 * license and copyrights can be found in the LICENSE and COPYRIGHT files
  6 * included with the SWIG source code as distributed by the SWIG developers
  7 * and at http://www.swig.org/legal.html.
  8 *
  9 * base.c 
 10 *
 11 *     This file contains the function entry points for dispatching methods on
 12 *     DOH objects.  A number of small utility functions are also included.
 13 * ----------------------------------------------------------------------------- */
 14
 15char cvsroot_base_c[] = "$Id: base.c 12946 2012-03-23 15:23:47Z drjoe $";
 16
 17#include "dohint.h"
 18
 19/* -----------------------------------------------------------------------------
 20 * DohDelete()
 21 * ----------------------------------------------------------------------------- */
 22
 23#ifndef SWIG_DEBUG_DELETE
 24#define SWIG_DEBUG_DELETE 0
 25#endif
 26
 27void DohDelete(DOH *obj) {
 28  DohBase *b = (DohBase *) obj;
 29  DohObjInfo *objinfo;
 30
 31  if (!obj)
 32    return;
 33  if (!DohCheck(b)) {
 34#if SWIG_DEBUG_DELETE
 35    fputs("DOH: Fatal error. Attempt to delete a non-doh object.\n", stderr);
 36    abort();
 37#else
 38    assert(0);
 39#endif
 40    return;
 41  }
 42  if (b->flag_intern)
 43    return;
 44  assert(b->refcount > 0);
 45  b->refcount--;
 46  if (b->refcount <= 0) {
 47    objinfo = b->type;
 48    if (objinfo->doh_del) {
 49      (objinfo->doh_del) (b);
 50    } else {
 51      if (b->data)
 52	DohFree(b->data);
 53    }
 54    DohObjFree(b);
 55  }
 56}
 57
 58/* -----------------------------------------------------------------------------
 59 * DohCopy()
 60 * ----------------------------------------------------------------------------- */
 61
 62DOH *DohCopy(const DOH *obj) {
 63  DohBase *b = (DohBase *) obj;
 64  DohObjInfo *objinfo;
 65
 66  if (!obj)
 67    return 0;
 68  if (!DohCheck(b)) {
 69#if SWIG_DEBUG_DELETE
 70    fputs("DOH: Fatal error. Attempt to copy a non-doh object.\n", stderr);
 71    abort();
 72#else
 73    assert(0);
 74#endif
 75    return 0;
 76  }
 77  objinfo = b->type;
 78  if (objinfo->doh_copy) {
 79    DohBase *bc = (DohBase *) (objinfo->doh_copy) (b);
 80    if ((bc) && b->meta) {
 81      bc->meta = Copy(b->meta);
 82    }
 83    return (DOH *) bc;
 84  }
 85  return 0;
 86}
 87
 88void DohIncref(DOH *obj) {
 89  Incref(obj);
 90}
 91
 92/* -----------------------------------------------------------------------------
 93 * DohClear()
 94 * ----------------------------------------------------------------------------- */
 95
 96void DohClear(DOH *obj) {
 97  DohBase *b = (DohBase *) obj;
 98  DohObjInfo *objinfo = b->type;
 99  if (objinfo->doh_clear)
100    (objinfo->doh_clear) (b);
101}
102
103/* -----------------------------------------------------------------------------
104 * DohStr()
105 * ----------------------------------------------------------------------------- */
106
107DOH *DohStr(const DOH *obj) {
108  char buffer[512];
109  DohBase *b = (DohBase *) obj;
110  DohObjInfo *objinfo;
111  if (DohCheck(b)) {
112    objinfo = b->type;
113    if (objinfo->doh_str) {
114      return (objinfo->doh_str) (b);
115    }
116    sprintf(buffer, "<Object '%s' at %p>", objinfo->objname, (void *) b);
117    return NewString(buffer);
118  } else {
119    return NewString(obj);
120  }
121}
122
123/* -----------------------------------------------------------------------------
124 * DohDump()
125 * ----------------------------------------------------------------------------- */
126
127int DohDump(const DOH *obj, DOH *out) {
128  DohBase *b = (DohBase *) obj;
129  DohObjInfo *objinfo = b->type;
130  if (objinfo->doh_dump) {
131    return (objinfo->doh_dump) (b, out);
132  }
133  return 0;
134}
135
136/* -----------------------------------------------------------------------------
137 * DohLen() - Defaults to strlen() if not a DOH object
138 * ----------------------------------------------------------------------------- */
139int DohLen(const DOH *obj) {
140  DohBase *b = (DohBase *) obj;
141  DohObjInfo *objinfo;
142  if (!b)
143    return 0;
144  if (DohCheck(b)) {
145    objinfo = b->type;
146    if (objinfo->doh_len) {
147      return (objinfo->doh_len) (b);
148    }
149    return 0;
150  } else {
151    return strlen((char *) obj);
152  }
153}
154
155/* -----------------------------------------------------------------------------
156 * DohHashVal()
157 * ----------------------------------------------------------------------------- */
158
159int DohHashval(const DOH *obj) {
160  DohBase *b = (DohBase *) obj;
161  DohObjInfo *objinfo;
162  /* obj is already checked and/or converted into DohBase* */
163  /*  if (DohCheck(b)) */
164  {
165    objinfo = b->type;
166    if (objinfo->doh_hashval) {
167      return (objinfo->doh_hashval) (b);
168    }
169  }
170  return 0;
171}
172
173/* -----------------------------------------------------------------------------
174 * DohData()
175 * ----------------------------------------------------------------------------- */
176
177void *DohData(const DOH *obj) {
178  DohBase *b = (DohBase *) obj;
179  DohObjInfo *objinfo;
180  if (DohCheck(obj)) {
181    objinfo = b->type;
182    if (objinfo->doh_data) {
183      return (objinfo->doh_data) (b);
184    }
185    return 0;
186  }
187  return (void *) obj;
188}
189
190/* -----------------------------------------------------------------------------
191 * RawData()
192 * ----------------------------------------------------------------------------- */
193
194static void *RawData(DohBase *b) {
195  DohObjInfo *objinfo = b->type;
196  return (objinfo->doh_data) ? (objinfo->doh_data) (b) : 0;
197}
198
199
200/* -----------------------------------------------------------------------------
201 * DohCmp()
202 * ----------------------------------------------------------------------------- */
203
204int DohCmp(const DOH *obj1, const DOH *obj2) {
205  DohBase *b1, *b2;
206  DohObjInfo *b1info, *b2info;
207  int c1, c2;
208  b1 = (DohBase *) obj1;
209  b2 = (DohBase *) obj2;
210  c1 = DohCheck(b1);
211  c2 = DohCheck(b2);
212  /* most of the times, obj2 is a plain c string */
213  if (!c1 || !c2) {
214    if ((b1 == 0) && (b2 == 0))
215      return 0;
216    if (b1 && !b2)
217      return 1;
218    if (!b1 && b2)
219      return -1;
220    return strcmp((char *) (c1 ? RawData(b1) : (void *) obj1), (char *) (c2 ? RawData(b2) : (void *) obj2));
221  }
222  b1info = b1->type;
223  b2info = b2->type;
224  if ((b1info == b2info) && (b1info->doh_cmp))
225    return (b1info->doh_cmp) (b1, b2);
226  return 1;
227}
228
229/* -----------------------------------------------------------------------------
230 * DohEqual()
231 * ----------------------------------------------------------------------------- */
232
233int DohEqual(const DOH *obj1, const DOH *obj2) {
234  DohBase *b1 = (DohBase *) obj1;
235  DohBase *b2 = (DohBase *) obj2;
236  if (!b1) {
237    return !b2;
238  } else if (!b2) {
239    return 0;
240  } else {
241    DohObjInfo *b1info = 0;
242    DohObjInfo *b2info = 0;
243    if (DohCheck(b1)) {
244      b1info = b1->type;
245      if (DohCheck(b2)) {
246	b2info = b2->type;
247      } else {
248	int len = (b1info->doh_len) (b1);
249	char *cobj = (char *) obj2;
250	return len == (int) strlen(cobj) ? (memcmp(RawData(b1), cobj, len) == 0) : 0;
251      }
252    } else if (DohCheck(b2)) {
253      int len = (b2->type->doh_len) (b2);
254      char *cobj = (char *) obj1;
255      return len == (int) strlen(cobj) ? (memcmp(RawData(b2), cobj, len) == 0) : 0;
256    } else {
257      return strcmp((char *) obj1, (char *) obj2) == 0;
258    }
259
260    if (!b1info) {
261      return obj1 == obj2;
262    } else if ((b1info == b2info)) {
263      return b1info->doh_equal ? (b1info->doh_equal) (b1, b2) : (b1info->doh_cmp ? (b1info->doh_cmp) (b1, b2) == 0 : (b1 == b2));
264    } else {
265      return 0;
266    }
267  }
268}
269
270/* -----------------------------------------------------------------------------
271 * DohFirst()
272 * ----------------------------------------------------------------------------- */
273
274DohIterator DohFirst(DOH *obj) {
275  DohIterator iter;
276  DohBase *b;
277  DohObjInfo *binfo;
278
279  b = (DohBase *) obj;
280  if (DohCheck(b)) {
281    binfo = b->type;
282    if (binfo->doh_first) {
283      return (binfo->doh_first) (b);
284    }
285  }
286  iter.object = 0;
287  iter.item = 0;
288  iter.key = 0;
289  iter._current = 0;
290  iter._index = 0;
291  return iter;
292}
293
294/* -----------------------------------------------------------------------------
295 * DohNext()
296 * ----------------------------------------------------------------------------- */
297
298DohIterator DohNext(DohIterator iter) {
299  DohIterator niter;
300
301  if (iter.object) {
302    DohBase *b;
303    DohObjInfo *binfo;
304
305    b = (DohBase *) iter.object;
306    binfo = b->type;
307    if (binfo->doh_next) {
308      return (binfo->doh_next) (iter);
309    }
310  }
311  niter = iter;
312  return niter;
313}
314
315/* -----------------------------------------------------------------------------
316 * DohIsMapping()
317 * ----------------------------------------------------------------------------- */
318int DohIsMapping(const DOH *obj) {
319  DohBase *b = (DohBase *) obj;
320  DohObjInfo *objinfo;
321  if (!DohCheck(b))
322    return 0;
323  objinfo = b->type;
324  if (objinfo->doh_hash)
325    return 1;
326  else
327    return 0;
328}
329
330/* -----------------------------------------------------------------------------
331 * DohGetattr()
332 * ----------------------------------------------------------------------------- */
333
334DOH *DohGetattr(DOH *obj, const DOH *name) {
335  DohBase *b = (DohBase *) obj;
336  DohObjInfo *objinfo = b->type;
337  if (objinfo->doh_hash && objinfo->doh_hash->doh_getattr) {
338    DOH *r = (objinfo->doh_hash->doh_getattr) (b, (DOH *) name);
339    return (r == DohNone) ? 0 : r;
340  }
341  return 0;
342}
343
344/* -----------------------------------------------------------------------------
345 * DohSetattr()
346 * ----------------------------------------------------------------------------- */
347
348int DohSetattr(DOH *obj, const DOH *name, const DOH *value) {
349  DohBase *b = (DohBase *) obj;
350  DohObjInfo *objinfo = b->type;
351  if (objinfo->doh_hash && objinfo->doh_hash->doh_setattr) {
352    return (objinfo->doh_hash->doh_setattr) (b, (DOH *) name, (DOH *) value);
353  }
354  return 0;
355}
356
357/* -----------------------------------------------------------------------------
358 * DohDelattr()
359 * ----------------------------------------------------------------------------- */
360
361int DohDelattr(DOH *obj, const DOH *name) {
362  DohBase *b = (DohBase *) obj;
363  DohObjInfo *objinfo = b->type;
364  if (objinfo->doh_hash && objinfo->doh_hash->doh_delattr) {
365    return (objinfo->doh_hash->doh_delattr) (b, (DOH *) name);
366  }
367  return 0;
368}
369
370/* -----------------------------------------------------------------------------
371 * DohCheckattr()
372 * ----------------------------------------------------------------------------- */
373
374int DohCheckattr(DOH *obj, const DOH *name, const DOH *value) {
375  DOH *attr = Getattr(obj,name);
376  if (!attr) return 0;
377  return DohEqual(attr,value);
378}
379
380/* -----------------------------------------------------------------------------
381 * DohKeys()
382 * ----------------------------------------------------------------------------- */
383
384DOH *DohKeys(DOH *obj) {
385  DohBase *b = (DohBase *) obj;
386  DohObjInfo *objinfo = b->type;
387  if (objinfo && objinfo->doh_hash->doh_keys) {
388    return (objinfo->doh_hash->doh_keys) (b);
389  }
390  return 0;
391}
392
393/* -----------------------------------------------------------------------------
394 * DohGetInt()
395 * ----------------------------------------------------------------------------- */
396
397int DohGetInt(DOH *obj, const DOH *name) {
398  DOH *val;
399  val = Getattr(obj, (DOH *) name);
400  if (!val)
401    return 0;
402  if (DohIsString(val)) {
403    return atoi((char *) Data(val));
404  }
405  return 0;
406}
407
408/* -----------------------------------------------------------------------------
409 * DohGetDouble()
410 * ----------------------------------------------------------------------------- */
411
412double DohGetDouble(DOH *obj, const DOH *name) {
413  DOH *val;
414  val = Getattr(obj, (DOH *) name);
415  if (!val)
416    return 0;
417  if (DohIsString(val)) {
418    return atof((char *) Data(val));
419  }
420  return 0;
421}
422
423/* -----------------------------------------------------------------------------
424 * DohGetChar()
425 * ----------------------------------------------------------------------------- */
426
427char *DohGetChar(DOH *obj, const DOH *name) {
428  DOH *val;
429  val = Getattr(obj, (DOH *) name);
430  if (!val)
431    return 0;
432  if (DohIsString(val)) {
433    return (char *) Data(val);
434  }
435  return 0;
436}
437
438/* -----------------------------------------------------------------------------
439 * DohGetFlagAttr() / DohGetFlag()
440 * A flag is unset if the attribute (name) does not exist on the node (obj),
441 * or it is set to "0". If the attribute is set to any other value,
442 * the flag is set.
443 * 
444 * DohGetFlag()     returns if the flag is set or not
445 * DohGetFlagAttr() returns the flag value if is set, NULL otherwise
446 * ----------------------------------------------------------------------------- */
447
448
449DOH *DohGetFlagAttr(DOH *obj, const DOH *name) {
450  DOH *val = Getattr(obj, (DOH *) name);
451  if (!val) {
452    return NULL;
453  } else {
454    const char *cval = Char(val);
455    if (!cval)
456      return val;
457    return (strcmp(cval, "0") != 0) ? val : NULL;
458  }
459}
460
461int DohGetFlag(DOH *obj, const DOH *name) {
462  return DohGetFlagAttr(obj, name) ? 1 : 0;
463}
464
465
466/* -----------------------------------------------------------------------------
467 * DohGetVoid()
468 * ----------------------------------------------------------------------------- */
469
470void *DohGetVoid(DOH *obj, const DOH *name) {
471  DOH *val;
472  val = Getattr(obj, (DOH *) name);
473  if (!val)
474    return 0;
475  return (void *) Data(val);
476}
477
478/* -----------------------------------------------------------------------------
479 * DohSetInt()
480 * ----------------------------------------------------------------------------- */
481
482void DohSetInt(DOH *obj, const DOH *name, int value) {
483  DOH *temp;
484  temp = NewStringEmpty();
485  Printf(temp, "%d", value);
486  Setattr(obj, (DOH *) name, temp);
487}
488
489/* -----------------------------------------------------------------------------
490 * DohSetDouble()
491 * ----------------------------------------------------------------------------- */
492
493void DohSetDouble(DOH *obj, const DOH *name, double value) {
494  DOH *temp;
495  temp = NewStringEmpty();
496  Printf(temp, "%0.17f", value);
497  Setattr(obj, (DOH *) name, temp);
498}
499
500/* -----------------------------------------------------------------------------
501 * DohSetChar()
502 * ----------------------------------------------------------------------------- */
503
504void DohSetChar(DOH *obj, const DOH *name, char *value) {
505  Setattr(obj, (DOH *) name, NewString(value));
506}
507
508/* -----------------------------------------------------------------------------
509 * DohSetFlag()
510 * ----------------------------------------------------------------------------- */
511
512void DohSetFlagAttr(DOH *obj, const DOH *name, const DOH *attr) {
513  Setattr(obj, (DOH *) name, attr ? attr : NewString("0"));
514}
515
516void DohSetFlag(DOH *obj, const DOH *name) {
517  Setattr(obj, (DOH *) name, NewString("1"));
518}
519
520/* -----------------------------------------------------------------------------
521 * DohSetVoid()
522 * ----------------------------------------------------------------------------- */
523
524void DohSetVoid(DOH *obj, const DOH *name, void *value) {
525  Setattr(obj, (DOH *) name, NewVoid(value, 0));
526}
527
528/* -----------------------------------------------------------------------------
529 * DohIsSequence()
530 * ----------------------------------------------------------------------------- */
531
532int DohIsSequence(const DOH *obj) {
533  DohBase *b = (DohBase *) obj;
534  DohObjInfo *objinfo;
535  if (!DohCheck(b))
536    return 0;
537  objinfo = b->type;
538  if (objinfo->doh_list)
539    return 1;
540  else
541    return 0;
542}
543
544/* -----------------------------------------------------------------------------
545 * DohGetitem()
546 * ----------------------------------------------------------------------------- */
547
548DOH *DohGetitem(DOH *obj, int index) {
549  DohBase *b = (DohBase *) obj;
550  DohObjInfo *objinfo = b->type;
551  if (objinfo->doh_list && objinfo->doh_list->doh_getitem) {
552    return (objinfo->doh_list->doh_getitem) (b, index);
553  }
554  return 0;
555}
556
557/* -----------------------------------------------------------------------------
558 * DohSetitem()
559 * ----------------------------------------------------------------------------- */
560
561int DohSetitem(DOH *obj, int index, const DOH *value) {
562  DohBase *b = (DohBase *) obj;
563  DohObjInfo *objinfo = b->type;
564  if (objinfo->doh_list && objinfo->doh_list->doh_setitem) {
565    return (objinfo->doh_list->doh_setitem) (b, index, (DOH *) value);
566  }
567  return -1;
568}
569
570/* -----------------------------------------------------------------------------
571 * DohDelitem()
572 * ----------------------------------------------------------------------------- */
573
574int DohDelitem(DOH *obj, int index) {
575  DohBase *b = (DohBase *) obj;
576  DohObjInfo *objinfo = b->type;
577  if (objinfo->doh_list && objinfo->doh_list->doh_delitem) {
578    return (objinfo->doh_list->doh_delitem) (b, index);
579  }
580  return -1;
581}
582
583/* -----------------------------------------------------------------------------
584 * DohInsertitem()
585 * ----------------------------------------------------------------------------- */
586
587int DohInsertitem(DOH *obj, int index, const DOH *value) {
588  DohBase *b = (DohBase *) obj;
589  DohObjInfo *objinfo = b->type;
590  if (objinfo->doh_list && objinfo->doh_list->doh_insitem) {
591    return (objinfo->doh_list->doh_insitem) (b, index, (DOH *) value);
592  }
593  return -1;
594}
595
596
597/* -----------------------------------------------------------------------------
598 * DohDelslice()
599 * ----------------------------------------------------------------------------- */
600
601int DohDelslice(DOH *obj, int sindex, int eindex) {
602  DohBase *b = (DohBase *) obj;
603  DohObjInfo *objinfo = b->type;
604  if (objinfo->doh_list && objinfo->doh_list->doh_delslice) {
605    return (objinfo->doh_list->doh_delslice) (b, sindex, eindex);
606  }
607  return -1;
608}
609
610/* -----------------------------------------------------------------------------
611 * DohIsFile()
612 * ----------------------------------------------------------------------------- */
613
614int DohIsFile(const DOH *obj) {
615  DohBase *b = (DohBase *) obj;
616  DohObjInfo *objinfo;
617  if (!DohCheck(b))
618    return 0;
619  objinfo = b->type;
620  if (objinfo->doh_file)
621    return 1;
622  else
623    return 0;
624}
625
626/* -----------------------------------------------------------------------------
627 * DohRead()
628 * ----------------------------------------------------------------------------- */
629
630int DohRead(DOH *obj, void *buffer, int length) {
631  DohBase *b = (DohBase *) obj;
632  DohObjInfo *objinfo;
633  if (DohCheck(obj)) {
634    objinfo = b->type;
635    if ((objinfo->doh_file) && (objinfo->doh_file->doh_read)) {
636      return (objinfo->doh_file->doh_read) (b, buffer, length);
637    }
638    return -1;
639  }
640  /* Hmmm.  Not a file.  Maybe it's a real FILE */
641  return fread(buffer, 1, length, (FILE *) b);
642}
643
644/* -----------------------------------------------------------------------------
645 * DohWrite()
646 * ----------------------------------------------------------------------------- */
647
648int DohWrite(DOH *obj, const void *buffer, int length) {
649  DohBase *b = (DohBase *) obj;
650  DohObjInfo *objinfo;
651  if (DohCheck(obj)) {
652    objinfo = b->type;
653    if ((objinfo->doh_file) && (objinfo->doh_file->doh_write)) {
654      return (objinfo->doh_file->doh_write) (b, buffer, length);
655    }
656    return -1;
657  }
658  /* Hmmm.  Not a file.  Maybe it's a real FILE */
659  return fwrite(buffer, 1, length, (FILE *) b);
660}
661
662/* -----------------------------------------------------------------------------
663 * DohSeek()
664 * ----------------------------------------------------------------------------- */
665
666int DohSeek(DOH *obj, long offset, int whence) {
667  DohBase *b = (DohBase *) obj;
668  DohObjInfo *objinfo;
669  if (DohCheck(obj)) {
670    objinfo = b->type;
671    if ((objinfo->doh_file) && (objinfo->doh_file->doh_seek)) {
672      return (objinfo->doh_file->doh_seek) (b, offset, whence);
673    }
674    return -1;
675  }
676  return fseek((FILE *) b, offset, whence);
677}
678
679/* -----------------------------------------------------------------------------
680 * DohTell()
681 * ----------------------------------------------------------------------------- */
682
683long DohTell(DOH *obj) {
684  DohBase *b = (DohBase *) obj;
685  DohObjInfo *objinfo;
686  if (DohCheck(obj)) {
687    objinfo = b->type;
688    if ((objinfo->doh_file) && (objinfo->doh_file->doh_tell)) {
689      return (objinfo->doh_file->doh_tell) (b);
690    }
691    return -1;
692  }
693  return ftell((FILE *) b);
694}
695
696/* -----------------------------------------------------------------------------
697 * DohGetc()
698 * ----------------------------------------------------------------------------- */
699
700int DohGetc(DOH *obj) {
701  static DOH *lastdoh = 0;
702  DohBase *b = (DohBase *) obj;
703  DohObjInfo *objinfo;
704  if (obj == lastdoh) {
705    objinfo = b->type;
706    return (objinfo->doh_file->doh_getc) (b);
707  }
708  if (DohCheck(obj)) {
709    objinfo = b->type;
710    if (objinfo->doh_file->doh_getc) {
711      lastdoh = obj;
712      return (objinfo->doh_file->doh_getc) (b);
713    }
714    return EOF;
715  }
716  return fgetc((FILE *) b);
717}
718
719/* -----------------------------------------------------------------------------
720 * DohPutc()
721 * ----------------------------------------------------------------------------- */
722
723int DohPutc(int ch, DOH *obj) {
724  static DOH *lastdoh = 0;
725  DohBase *b = (DohBase *) obj;
726  DohObjInfo *objinfo;
727
728  if (obj == lastdoh) {
729    objinfo = b->type;
730    return (objinfo->doh_file->doh_putc) (b, ch);
731  }
732  if (DohCheck(obj)) {
733    objinfo = b->type;
734    if (objinfo->doh_file->doh_putc) {
735      lastdoh = obj;
736      return (objinfo->doh_file->doh_putc) (b, ch);
737    }
738    return EOF;
739  }
740  return fputc(ch, (FILE *) b);
741}
742
743/* -----------------------------------------------------------------------------
744 * DohUngetc()
745 * ----------------------------------------------------------------------------- */
746
747int DohUngetc(int ch, DOH *obj) {
748  DohBase *b = (DohBase *) obj;
749  DohObjInfo *objinfo;
750  if (DohCheck(obj)) {
751    objinfo = b->type;
752    if (objinfo->doh_file->doh_ungetc) {
753      return (objinfo->doh_file->doh_ungetc) (b, ch);
754    }
755    return EOF;
756  }
757  return ungetc(ch, (FILE *) b);
758}
759
760/* -----------------------------------------------------------------------------
761 * DohClose()
762 * ----------------------------------------------------------------------------- */
763
764int DohClose(DOH *obj) {
765  DohBase *b = (DohBase *) obj;
766  DohObjInfo *objinfo;
767  if (DohCheck(obj)) {
768    objinfo = b->type;
769    if (objinfo->doh_file->doh_close) {
770      return (objinfo->doh_file->doh_close) (b);
771    }
772    return 0;
773  }
774  return fclose((FILE *) obj);
775}
776
777/* -----------------------------------------------------------------------------
778 * DohIsString()
779 * ----------------------------------------------------------------------------- */
780
781int DohIsString(const DOH *obj) {
782  DohBase *b = (DohBase *) obj;
783  DohObjInfo *objinfo;
784  if (!DohCheck(b))
785    return 0;
786  objinfo = b->type;
787  if (objinfo->doh_string)
788    return 1;
789  else
790    return 0;
791}
792
793/* -----------------------------------------------------------------------------
794 * DohReplace()
795 * ----------------------------------------------------------------------------- */
796
797int DohReplace(DOH *src, const DOH *token, const DOH *rep, int flags) {
798  DohBase *b = (DohBase *) src;
799  DohObjInfo *objinfo;
800  if (!token)
801    return 0;
802  if (!rep)
803    rep = "";
804  if (DohIsString(src)) {
805    objinfo = b->type;
806    if (objinfo->doh_string->doh_replace) {
807      return (objinfo->doh_string->doh_replace) (b, (DOH *) token, (DOH *) rep, flags);
808    }
809  }
810  return 0;
811}
812
813/* -----------------------------------------------------------------------------
814 * DohChop()
815 * ----------------------------------------------------------------------------- */
816
817void DohChop(DOH *src) {
818  DohBase *b = (DohBase *) src;
819  DohObjInfo *objinfo;
820  if (DohIsString(src)) {
821    objinfo = b->type;
822    if (objinfo->doh_string->doh_chop) {
823      (objinfo->doh_string->doh_chop) (b);
824    }
825  }
826}
827
828/* -----------------------------------------------------------------------------
829 * DohSetFile()
830 * ----------------------------------------------------------------------------- */
831void DohSetfile(DOH *ho, DOH *file) {
832  DohBase *h = (DohBase *) ho;
833  DohObjInfo *objinfo;
834  if (!h)
835    return;
836  objinfo = h->type;
837  if (objinfo->doh_setfile)
838    (objinfo->doh_setfile) (h, file);
839}
840
841/* -----------------------------------------------------------------------------
842 * DohGetFile()
843 * ----------------------------------------------------------------------------- */
844DOH *DohGetfile(const DOH *ho) {
845  DohBase *h = (DohBase *) ho;
846  DohObjInfo *objinfo;
847  if (!h)
848    return 0;
849  objinfo = h->type;
850  if (objinfo->doh_getfile)
851    return (objinfo->doh_getfile) (h);
852  return 0;
853}
854
855/* -----------------------------------------------------------------------------
856 * DohSetLine()
857 * ----------------------------------------------------------------------------- */
858void DohSetline(DOH *ho, int l) {
859  DohBase *h = (DohBase *) ho;
860  DohObjInfo *objinfo;
861  if (!h)
862    return;
863  objinfo = h->type;
864  if (objinfo->doh_setline)
865    (objinfo->doh_setline) (h, l);
866}
867
868/* -----------------------------------------------------------------------------
869 * DohGetLine()
870 * ----------------------------------------------------------------------------- */
871int DohGetline(const DOH *ho) {
872  DohBase *h = (DohBase *) ho;
873  DohObjInfo *objinfo;
874  if (!h)
875    return 0;
876  objinfo = h->type;
877  if (objinfo->doh_getline)
878    return (objinfo->doh_getline) (h);
879  return 0;
880}
881
882/* -----------------------------------------------------------------------------
883 * DohGetmeta()
884 * ----------------------------------------------------------------------------- */
885
886DOH *DohGetmeta(DOH *ho, const DOH *name) {
887  DohBase *h = (DohBase *) ho;
888  if (!DohCheck(ho))
889    return 0;
890  if (!h->meta)
891    return 0;
892  return DohGetattr(h->meta, name);
893}
894
895/* -----------------------------------------------------------------------------
896 * DohGetmeta()
897 * ----------------------------------------------------------------------------- */
898
899int DohSetmeta(DOH *ho, const DOH *name, const DOH *value) {
900  DohBase *h = (DohBase *) ho;
901  if (!DohCheck(ho))
902    return 0;
903  if (!h->meta)
904    h->meta = NewHash();
905  return DohSetattr(h->meta, name, value);
906}
907
908/* -----------------------------------------------------------------------------
909 * DohDelmeta()
910 * ----------------------------------------------------------------------------- */
911
912int DohDelmeta(DOH *ho, const DOH *name) {
913  DohBase *h = (DohBase *) ho;
914  if (!DohCheck(ho))
915    return 0;
916  if (!h->meta)
917    return 0;
918  return DohDelattr(h->meta, name);
919}
920
921/* -----------------------------------------------------------------------------
922 * DohSetmark()
923 * ----------------------------------------------------------------------------- */
924
925void DohSetmark(DOH *ho, int x) {
926  DohBase *h = (DohBase *) ho;
927  h->flag_usermark = x;
928}
929
930int DohGetmark(DOH *ho) {
931  DohBase *h = (DohBase *) ho;
932  return h->flag_usermark;
933}
934
935/* -----------------------------------------------------------------------------
936 * DohCall()
937 *
938 * Invokes a function via DOH.  A Function is represented by a hash table with
939 * the following attributes:
940 *
941 *       "builtin"    -  Pointer to built-in function (if any)
942 *
943 * (Additional attributes may be added later)
944 * 
945 * Returns a DOH object with result on success. Returns NULL on error
946 * ----------------------------------------------------------------------------- */
947
948DOH *DohCall(DOH *func, DOH *args) {
949  DOH *result;
950  DOH *(*builtin) (DOH *);
951
952  builtin = (DOH *(*)(DOH *)) GetVoid(func, "builtin");
953  if (!builtin)
954    return 0;
955  result = (*builtin) (args);
956  return result;
957}