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