Major changes

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@28 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Dave Beazley 2000-01-02 15:34:50 +00:00
commit 722d67666a
10 changed files with 532 additions and 160 deletions

View file

@ -9,7 +9,7 @@
# Set your C++ compiler here. g++ works on most machines,
# but you might have to change it depending on your installation.
#
CC = cc -g
CC = gcc -g -Wall -DDOH_STRING_UPDATE_LINES -O2
prefix = /usr/local
# Comment out the following line if you're on an SGI or don't have ranlib!

View file

@ -45,6 +45,7 @@ static DohObjInfo DohBaseType = {
0, /* doh_del */
0, /* doh_copy */
0, /* doh_clear */
0, /* doh_scope */
0, /* doh_str */
0, /* doh_data */
0, /* doh_dump */
@ -85,8 +86,12 @@ static DOH *find_internal(DOH *co) {
StringNode *r, *s;
int d;
char *c;
DOH *n;
if (DohCheck(co)) return co;
c = (char *) co;
n = NewString(c);
return n;
if (doh_debug_level) {
DohError(DOH_CONVERSION,"Unknown object '%s' being treated as 'char *'.\n", c);
}
@ -120,26 +125,24 @@ void DohDestroy(DOH *obj) {
DohBase *b = (DohBase *) obj;
DohError(DOH_CALLS,"DohDestroy %x\n",obj);
if (!DohCheck(b)) return;
if (b->flags & DOH_FLAG_INTERN) return;
b->refcount--;
if (b->refcount <= 0) {
if (doh_debug_level >= DOH_MEMORY) {
if (DohObjFreeCheck(obj)) {
DohError(DOH_MEMORY,"DohDestroy. %x was already released! (ignoring for now)\n", obj);
return;
}
}
if (b->refcount == 0) {
if (b->objinfo->doh_del) {
(b->objinfo->doh_del)(obj);
return;
} else {
/* free(b); */
(b->objinfo->doh_del)(obj);
}
return;
}
}
void DohIntern(DOH *obj) {
DohBase *b = (DohBase *) obj;
if (!DohCheck(b)) return;
b->flags = b->flags | DOH_FLAG_INTERN;
}
/* Copy an object */
DOH *DohCopy(DOH *obj) {
DOH *result;
DohBase *b = (DohBase *) obj;
DohError(DOH_CALLS,"DohCopy %x\n",obj);
if (!DohCheck(b)) {
@ -167,6 +170,20 @@ void DohClear(DOH *obj) {
DohError(DOH_UNSUPPORTED, "No clear method defined for type '%s'\n", b->objinfo->objname);
}
void DohSetScope(DOH *obj, int s) {
DohBase *b = (DohBase *) obj;
DohError(DOH_CALLS,"DohScope %x\n",obj);
if (!DohCheck(b)) {
DohError(DOH_UNKNOWN,"Unknown object %x passed to Scope.\n",obj);
return;
}
if (b->objinfo->doh_scope) {
(b->objinfo->doh_scope)(obj,s);
return;
}
if (s < b->scope) b->scope = s;
}
/* Turn an object into a string */
DOH *DohStr(DOH *obj) {
DOH *s;
@ -202,7 +219,6 @@ int DohDump(DOH *obj, DOH *out) {
/* Get the length */
int DohLen(DOH *obj) {
int s;
DohBase *b = (DohBase *) obj;
DohError(DOH_CALLS,"DohLen %x\n",obj);
if (!b) return 0;
@ -220,7 +236,6 @@ int DohLen(DOH *obj) {
/* Get the hash value */
int DohHashval(DOH *obj) {
int s;
DohBase *b = (DohBase *) obj;
DohError(DOH_CALLS,"DohHashval %x\n",obj);
if (DohCheck(b)) {
@ -237,7 +252,6 @@ int DohHashval(DOH *obj) {
/* Get raw data */
void *DohData(DOH *obj) {
char *c;
char *s;
DohBase *b = (DohBase *) obj;
DohError(DOH_CALLS,"DohData %x\n",obj);
c = (char *) obj;
@ -312,7 +326,6 @@ void DohSetfile(DOH *obj, DOH *file) {
/* Get an attribute from an object */
int DohCmp(DOH *obj1, DOH *obj2) {
int s;
DohBase *b1, *b2;
DohError(DOH_CALLS,"DohCmp %x, %x\n",obj1,obj2);
b1 = (DohBase *) obj1;
@ -347,15 +360,12 @@ int DohIsMapping(DOH *obj) {
/* Get an attribute from an object */
DOH *DohGetattr(DOH *obj, DOH *name) {
DOH *s;
DOH *name_obj;
DohBase *b = (DohBase *) obj;
DohError(DOH_CALLS,"DohGetattr %x, %x\n",obj,name);
if (!name) return 0;
if (DohIsMapping(b)) {
name_obj = find_internal(name);
if (b->objinfo->doh_mapping->doh_getattr) {
return (b->objinfo->doh_mapping->doh_getattr)(obj,name_obj);
return (b->objinfo->doh_mapping->doh_getattr)(obj,name);
}
}
if (DohCheck(b)) {
@ -368,21 +378,12 @@ DOH *DohGetattr(DOH *obj, DOH *name) {
/* Set an attribute in an object */
int DohSetattr(DOH *obj, DOH *name, DOH *value) {
int s;
DOH *name_obj, *value_obj;
DohBase *b = (DohBase *) obj;
DohError(DOH_CALLS,"DohSetattr %x, %x, %x\n",obj,name, value);
if ((!name) || (!value)) return 0;
if (DohIsMapping(b)) {
name_obj = find_internal(name);
if (!DohCheck(value)) {
DohError(DOH_CONVERSION,"Unknown object %x converted to a string in Setattr.\n",value);
value_obj = NewString(value);
} else {
value_obj = value;
}
if (b->objinfo->doh_mapping->doh_setattr) {
return (b->objinfo->doh_mapping->doh_setattr)(obj,name_obj,value_obj);
return (b->objinfo->doh_mapping->doh_setattr)(obj,name,value);
}
}
if (DohCheck(b)) {
@ -395,14 +396,12 @@ int DohSetattr(DOH *obj, DOH *name, DOH *value) {
/* Delete an attribute from an object */
void DohDelattr(DOH *obj, DOH *name) {
DOH *name_obj;
DohBase *b = (DohBase *) obj;
DohError(DOH_CALLS,"DohDelattr %x, %x\n",obj,name);
if (!name) return;
if (DohIsMapping(obj)) {
name_obj = find_internal(name);
if (b->objinfo->doh_mapping->doh_delattr) {
(b->objinfo->doh_mapping->doh_delattr)(obj,name_obj);
(b->objinfo->doh_mapping->doh_delattr)(obj,name);
return;
}
}
@ -416,7 +415,6 @@ void DohDelattr(DOH *obj, DOH *name) {
/* Get first item in an object */
DOH *DohFirst(DOH *obj) {
DOH *s;
DohBase *b = (DohBase *) obj;
DohError(DOH_CALLS,"DohFirst %x\n",obj);
if (DohIsMapping(obj)) {
@ -434,7 +432,6 @@ DOH *DohFirst(DOH *obj) {
/* Get next item in an object */
DOH *DohNext(DOH *obj) {
DOH *s;
DohBase *b = (DohBase *) obj;
DohError(DOH_CALLS,"DohNext %x\n",obj);
if (DohIsMapping(obj)) {
@ -453,7 +450,6 @@ DOH *DohNext(DOH *obj) {
/* Get first item in an object */
DOH *DohFirstkey(DOH *obj) {
DOH *s;
DohBase *b = (DohBase *) obj;
DohError(DOH_CALLS,"DohFirstkey %x\n",obj);
if (DohIsMapping(obj)) {
@ -471,7 +467,6 @@ DOH *DohFirstkey(DOH *obj) {
/* Get next item in an object */
DOH *DohNextkey(DOH *obj) {
DOH *s;
DohBase *b = (DohBase *) obj;
DohError(DOH_CALLS,"DohNextkey %x\n",obj);
if (DohIsMapping(obj)) {
@ -488,7 +483,6 @@ DOH *DohNextkey(DOH *obj) {
}
int DohGetInt(DOH *obj, DOH *name) {
int ival;
DOH *val;
DohError(DOH_CALLS,"DohGetInt %x, %x\n",obj,name);
val = Getattr(obj,name);
@ -500,7 +494,6 @@ int DohGetInt(DOH *obj, DOH *name) {
}
double DohGetDouble(DOH *obj, DOH *name) {
double dval;
DOH *val;
DohError(DOH_CALLS,"DohGetDouble %x, %x\n",obj,name);
val = Getattr(obj,name);
@ -512,7 +505,6 @@ double DohGetDouble(DOH *obj, DOH *name) {
}
char *DohGetChar(DOH *obj, DOH *name) {
double dval;
DOH *val;
DohError(DOH_CALLS,"DohGetChar %x, %x\n",obj,name);
val = Getattr(obj,name);
@ -553,7 +545,6 @@ int DohIsSequence(DOH *obj) {
/* Get an item from an object */
DOH *DohGetitem(DOH *obj, int index) {
DOH *s;
DohBase *b = (DohBase *) obj;
DohError(DOH_CALLS,"DohGetitem %x, %d\n",obj,index);
if (DohIsSequence(obj)) {
@ -621,7 +612,6 @@ void DohInsertitem(DOH *obj, int index, DOH *value) {
DohError(DOH_CONVERSION,"Unknown object %x being converted to a string in Insertitem.\n", value);
value_obj = NewString(value);
no = 1;
Incref(value_obj);
} else {
value_obj = value;
}
@ -827,10 +817,38 @@ int DohClose(DOH *obj) {
return 0;
}
/* -----------------------------------------------------------------------------
* String methods
* ----------------------------------------------------------------------------- */
int DohIsString(DOH *obj) {
DohBase *b = (DohBase *) obj;
if (!DohCheck(b)) return 0;
if (b->objinfo->doh_string) return 1;
else return 0;
}
int DohReplace(DOH *src, DOH *token, DOH *rep, int flags) {
DohBase *b = (DohBase *) src;
DohError(DOH_CALLS, "DohReplace %x\n", src);
if (DohIsString(src)) {
if (b->objinfo->doh_string->doh_replace) {
return (b->objinfo->doh_string->doh_replace)(src,token,rep,flags);
}
}
if (DohCheck(b)) {
DohError(DOH_UNSUPPORTED, "No replace method defined for type '%s'\n", b->objinfo->objname);
} else {
DohError(DOH_UNKNOWN,"Unknown object %x passed to Replace\n", b);
}
return 0;
}
void DohInit(DOH *b) {
DohBase *bs = (DohBase *) b;
bs->refcount =0;
bs->refcount = 1;
bs->objinfo = &DohBaseType;
bs->line = 0;
bs->file = 0;
bs->flags = 0;
}

View file

@ -14,6 +14,7 @@
****************************************************************************/
#include "dohint.h"
#include <unistd.h>
/* ---------------------------------------------------------------------------
* $Header$
@ -58,6 +59,7 @@ static DohObjInfo FileType = {
DelFile, /* doh_del */
0, /* doh_copy */
0, /* doh_clear */
0, /* doh_scope */
0, /* doh_str */
0, /* doh_data */
0, /* doh_dump */
@ -95,7 +97,6 @@ NewFile(DOH *fn, char *mode)
fclose(file);
return 0;
}
DohInit(f);
f->objinfo = &FileType;
f->filep = file;
f->fd = fileno(file);
@ -113,7 +114,6 @@ NewFileFromFile(FILE *file)
File *f;
f = (File *) DohObjMalloc(sizeof(File));
if (!f) return 0;
DohInit(f);
f->objinfo = &FileType;
f->filep = file;
f->fd = fileno(file);
@ -131,7 +131,6 @@ NewFileFromFd(int fd)
File *f;
f = (File *) DohObjMalloc(sizeof(File));
if (!f) return 0;
DohInit(f);
f->objinfo = &FileType;
f->filep = 0;
f->fd = fd;

View file

@ -77,18 +77,18 @@ DohvPrintf(DOH *so, char *format, va_list ap)
char *p = format;
char newformat[256];
char obuffer[OBUFLEN];
char *fmt;
char *fmt = 0;
char temp[64];
int widthval = 0;
int precval = 0;
int maxwidth;
char *w, *prec;
char *w = 0;
int ivalue;
double dvalue;
void *pvalue;
char *stemp;
int nbytes = 0;
char encoder[128], *ec;
char encoder[128], *ec = 0;
while (*p) {
switch(state) {

View file

@ -40,17 +40,62 @@ typedef struct Hash {
HashNode *current;
} Hash;
/* -----------------------------------------------------------------------------
Key interning. This is used for getattr,setattr functions.
The following structure maps raw char * entries to string objects.
----------------------------------------------------------------------------- */
typedef struct KeyValue {
char *cstr;
DOH *sstr;
struct KeyValue *left;
struct KeyValue *right;
} KeyValue;
static KeyValue *root = 0;
static DOH *find_key(char *c) {
KeyValue *r, *s;
int d = 0;
r = root;
s = 0;
while (r) {
s = r;
d = strcmp(r->cstr,c);
if (d == 0) return r->sstr;
if (d < 0) r = r->left;
else r = r->right;
}
/* fprintf(stderr,"Interning '%s'\n", c); */
r = (KeyValue *) DohMalloc(sizeof(KeyValue));
r->cstr = (char *) DohMalloc(strlen(c)+1);
strcpy(r->cstr,c);
r->sstr = NewString(c);
DohIntern(r->sstr);
r->left = 0;
r->right = 0;
if (!s) { root = r; }
else {
if (d < 0) s->left = r;
else s->right = r;
}
return r->sstr;
}
/* Forward references */
DOH *CopyHash(DOH *h);
void DelHash(DOH *h);
void Hash_clear(DOH *);
int Hash_setattr(DOH *, DOH *k, DOH *obj);
void DelHash(DOH *h);
void Hash_clear(DOH *);
void Hash_scope(DOH *, int);
int Hash_setattr(DOH *, DOH *k, DOH *obj);
DOH *Hash_getattr(DOH *h, DOH *k);
int Hash_delattr(DOH *h, DOH *k);
DOH *Hash_firstkey(DOH *h);
DOH *Hash_nextkey(DOH *h);
DOH *Hash_str(DOH *h);
int Hash_len(DOH *h);
int Hash_len(DOH *h);
#define HASH_INIT_SIZE 7
@ -87,6 +132,7 @@ static DohObjInfo HashType = {
DelHash, /* doh_del */
CopyHash, /* doh_copy */
Hash_clear, /* doh_clear */
Hash_scope, /* doh_scope */
Hash_str, /* doh_str */
0, /* doh_data */
0, /* doh_dump */
@ -121,7 +167,6 @@ DOH *NewHash() {
Hash *h;
int i;
h = (Hash *) DohObjMalloc(sizeof(Hash));
DohInit(h);
h->hashsize = HASH_INIT_SIZE;
h->hashtable = (HashNode **) DohMalloc(h->hashsize*sizeof(HashNode *));
for (i = 0; i < h->hashsize; i++) {
@ -142,11 +187,9 @@ DOH *CopyHash(DOH *ho) {
Hash *h, *nh;
HashNode *n;
int i;
DOH *key;
h = (Hash *) ho;
nh = (Hash *) DohObjMalloc(sizeof(Hash));
DohInit(nh);
nh->hashsize = h->hashsize;
nh->hashtable = (HashNode **) DohMalloc(nh->hashsize*sizeof(HashNode *));
@ -159,7 +202,7 @@ DOH *CopyHash(DOH *ho) {
nh->objinfo = h->objinfo;
for (i = 0; i < h->hashsize; i++) {
if (n = h->hashtable[i]) {
if ((n = h->hashtable[i])) {
while (n) {
Hash_setattr(nh, n->key, n->object);
n = n->next;
@ -181,7 +224,7 @@ void DelHash(DOH *ho)
h = (Hash *) ho;
for (i = 0; i < h->hashsize; i++) {
if (n = h->hashtable[i]) {
if ((n = h->hashtable[i])) {
while (n) {
next = n->next;
DelNode(n);
@ -190,6 +233,8 @@ void DelHash(DOH *ho)
}
}
DohFree(h->hashtable);
h->hashtable = 0;
h->hashsize = 0;
DohObjFree(h);
}
@ -205,7 +250,7 @@ void Hash_clear(DOH *ho)
h = (Hash *) ho;
for (i = 0; i < h->hashsize; i++) {
if (n = h->hashtable[i]) {
if ((n = h->hashtable[i])) {
while (n) {
next = n->next;
DelNode(n);
@ -217,6 +262,31 @@ void Hash_clear(DOH *ho)
h->nitems = 0;
}
/* -----------------------------------------------------------------------------
* Hash_scope(DOH *ho, int s) - Clear all entries in a hash table
* ----------------------------------------------------------------------------- */
void Hash_scope(DOH *ho, int s)
{
Hash *h;
HashNode *n;
int i;
h = (Hash *) ho;
if (h->flags & DOH_FLAG_SETSCOPE) return;
if (s < h->scope) h->scope = s;
h->flags = h->flags | DOH_FLAG_SETSCOPE;
for (i = 0; i < h->hashsize; i++) {
if ((n = h->hashtable[i])) {
while (n) {
Setscope(n->object,s);
Setscope(n->key,s);
n = n->next;
}
}
}
h->flags = h->flags & ~DOH_FLAG_SETSCOPE;
}
/* -----------------------------------------------------------------------------
* static resize(Hash *h) - Resizes the hash table
* ----------------------------------------------------------------------------- */
@ -275,6 +345,10 @@ Hash_setattr(DOH *ho, DOH *k, DOH *obj) {
HashNode *n, *prev;
Hash *h;
if (!DohCheck(k)) k = find_key(k);
if (!DohCheck(obj)) {
obj = NewString((char *) obj);
}
h = (Hash *) ho;
hv = (Hashval(k)) % h->hashsize;
n = h->hashtable[hv];
@ -299,6 +373,8 @@ Hash_setattr(DOH *ho, DOH *k, DOH *obj) {
}
/* Add this to the table */
n = NewNode(k,obj);
Setscope(n->key,h->scope);
Setscope(n->object,h->scope);
if (prev) prev->next = n;
else h->hashtable[hv] = n;
h->nitems++;
@ -316,6 +392,7 @@ Hash_getattr(DOH *ho, DOH *k) {
HashNode *n;
Hash *h;
if (!DohCheck(k)) k = find_key(k);
h = (Hash *) ho;
hv = Hashval(k) % h->hashsize;
n = h->hashtable[hv];
@ -337,6 +414,7 @@ Hash_delattr(DOH *ho, DOH *k)
int hv;
Hash *h;
if (!DohCheck(k)) k = find_key(k);
h = (Hash *) ho;
hv = Hashval(k) % h->hashsize;
n = h->hashtable[hv];
@ -434,6 +512,11 @@ Hash_str(DOH *ho) {
h = (Hash *) ho;
s = NewString("");
if (h->flags & DOH_FLAG_PRINT) {
Printf(s,"Hash(0x%x)",h);
return s;
}
h->flags = h->flags | DOH_FLAG_PRINT;
Printf(s,"Hash {\n");
for (i = 0; i < h->hashsize; i++) {
n = h->hashtable[i];
@ -443,18 +526,7 @@ Hash_str(DOH *ho) {
}
}
Printf(s,"}\n");
#ifdef old
s = NewString("Hash");
Printf(s,"(%x) {",h);
for (i = 0; i < h->hashsize; i++) {
n = h->hashtable[i];
while (n) {
Printf(s,"'%o',", n->key);
n = n->next;
}
}
Printf(s,"}");
#endif
h->flags = h->flags & ~DOH_FLAG_PRINT;
return s;
}

View file

@ -36,6 +36,7 @@ typedef struct List {
DOH *CopyList(DOH *);
void DelList(DOH *);
void List_clear(DOH *);
void List_scope(DOH *, int s);
DOH *List_get(DOH *, int pos);
int List_set(DOH *, int pos, DOH *obj);
int List_insert(DOH *, int pos, DOH *item);
@ -63,6 +64,7 @@ static DohObjInfo ListType = {
DelList, /* doh_del */
CopyList, /* doh_copy */
List_clear, /* doh_clear */
List_scope, /* doh_scope */
List_str, /* doh_str */
0, /* doh_data */
List_dump, /* doh_dump */
@ -72,6 +74,7 @@ static DohObjInfo ListType = {
0, /* doh_cmp */
0, /* doh_mapping */
&ListSeqMethods, /* doh_sequence */
0, /* doh_file */
0, /* doh_string */
0, /* doh_callable */
};
@ -120,7 +123,6 @@ NewList() {
List *l;
int i;
l = (List *) DohObjMalloc(sizeof(List));
DohInit(l);
l->objinfo = &ListType;
l->nitems = 0;
l->maxitems = MAXLISTITEMS;
@ -142,7 +144,6 @@ CopyList(DOH *lo) {
int i;
l = (List *) lo;
nl = (List *) DohObjMalloc(sizeof(List));
DohInit(nl);
nl->objinfo = l->objinfo;
nl->nitems = l->nitems;
nl->maxitems = l->maxitems;
@ -171,6 +172,7 @@ DelList(DOH *lo) {
Delete(l->items[i]);
}
DohFree(l->items);
l->items = 0;
DohObjFree(l);
}
@ -190,6 +192,23 @@ List_clear(DOH *lo) {
l->nitems = 0;
}
/* -----------------------------------------------------------------------------
* void List_scope(DOH *lo, int s)
* ----------------------------------------------------------------------------- */
void
List_scope(DOH *lo, int s) {
List *l;
int i;
l = (List *) lo;
if (l->flags & DOH_FLAG_SETSCOPE) return;
l->flags = l->flags | DOH_FLAG_SETSCOPE;
if (s < l->scope) l->scope = (unsigned char) s;
for (i = 0; i < l->nitems; i++) {
Setscope(l->items[i],s);
}
l->flags = l->flags & ~DOH_FLAG_SETSCOPE;
}
/* -----------------------------------------------------------------------------
* void List_insert(DOH *lo, int pos, DOH *item) - Insert an element
* ----------------------------------------------------------------------------- */
@ -201,7 +220,7 @@ List_insert(DOH *lo, int pos, DOH *item)
DohBase *b;
int i;
if (!item) return;
if (!item) return -1;
b = (DohBase *) item;
l = (List *) lo;
@ -214,6 +233,7 @@ List_insert(DOH *lo, int pos, DOH *item)
}
l->items[pos] = item;
b->refcount++;
Setscope(b,l->scope);
l->nitems++;
return 0;
}
@ -232,7 +252,7 @@ List_remove(DOH *lo, int pos)
l = (List *) lo;
if (pos == DOH_END) pos = l->nitems-1;
if (pos == DOH_BEGIN) pos = 0;
if ((pos < 0) || (pos >= l->nitems)) return;
if ((pos < 0) || (pos >= l->nitems)) return -1;
item = l->items[pos];
for (i = pos; i < l->nitems-1; i++) {
l->items[i] = l->items[i+1];
@ -285,6 +305,7 @@ List_set(DOH *lo, int n, DOH *val)
Delete(l->items[n]);
l->items[n] = val;
Incref(val);
Setscope(val,l->scope);
return 0;
}
@ -324,6 +345,11 @@ List_str(DOH *lo)
List *l = (List *) lo;
s = NewString("");
if (l->flags & DOH_FLAG_PRINT) {
Printf(s,"List(0x%x)",l);
return s;
}
l->flags = l->flags | DOH_FLAG_PRINT;
Printf(s,"List[ ");
for (i = 0; i < l->nitems; i++) {
Printf(s, "%s", l->items[i]);
@ -331,6 +357,7 @@ List_str(DOH *lo)
Printf(s,", ");
}
Printf(s," ]\n");
l->flags = l->flags & ~DOH_FLAG_PRINT;
return s;
}
@ -341,7 +368,7 @@ List_dump(DOH *lo, DOH *out) {
List *l = (List *) lo;
for (i = 0; i < l->nitems; i++) {
ret = Dump(l->items[i],out);
if (ret < 0) ret;
if (ret < 0) return -1;
nsent += ret;
}
return nsent;

View file

@ -16,17 +16,23 @@
#include "dohint.h"
#ifndef DOH_POOL_SIZE
#define DOH_POOL_SIZE 65536
#define DOH_POOL_SIZE 128000
#endif
#ifndef DOH_MAX_FRAG
#define DOH_MAX_FRAG 1024
#endif
#ifndef DOH_MAX_SCOPES
#define DOH_MAX_SCOPES 256
#endif
static int _DohMemoryCurrent = 0;
static int _DohMemoryHigh = 0;
static int _PoolSize = DOH_POOL_SIZE;
DOH *DohNone = 0;
/* -----------------------------------------------------------------------------
* memory.c
*
@ -51,6 +57,9 @@ typedef struct pool {
static Pool *Pools = 0;
static int pools_initialized = 0;
static DohBase *scopes[DOH_MAX_SCOPES];
static int nscopes = 0;
/* ----------------------------------------------------------------------
* Pool *CreatePool(int size)
@ -87,6 +96,12 @@ static void InitPools() {
}
Pools = CreatePool(_PoolSize); /* Create initial pool */
pools_initialized = 1;
for (i = 0; i < DOH_MAX_SCOPES; i++) {
scopes[i] = 0;
}
DohNewScope(); /* Initialize the scope system */
DohNone = NewVoid(0,0);
DohIntern(DohNone);
}
/* ----------------------------------------------------------------------
@ -125,6 +140,122 @@ int DohObjFreeCheck(DOH *ptr) {
return 0;
}
/* ----------------------------------------------------------------------
* int DohNewScope()
*
* Create a new scope in which objects will be placed
* ---------------------------------------------------------------------- */
int DohNewScope()
{
assert(nscopes < DOH_MAX_SCOPES);
if (!pools_initialized) InitPools();
scopes[nscopes] = 0;
nscopes++;
return nscopes - 1;
}
/* ----------------------------------------------------------------------
* void DohDelScope(int s) - Delete scope s
* ---------------------------------------------------------------------- */
void DohDelScope(int s)
{
int ns;
DohBase *b, *b1;
ns = s;
assert((s >= 0) && (s < nscopes));
s = nscopes - 1;
while (s >= ns) {
b = scopes[s];
b1 = 0;
while (b) {
if (s <= b->scope) {
if (!(b->flags & DOH_FLAG_DELSCOPE)) {
Delete(b);
b->flags = b->flags | DOH_FLAG_DELSCOPE;
}
}
b1 = b;
b = (DohBase *) (b->nextptr);
}
if (ns > 0) { /* Add objects to highest non-deleted scope */
if (b1) {
b1->nextptr = (DOH *) scopes[ns-1];
scopes[ns-1] = (DohBase *) scopes[s];
}
}
scopes[s] = 0;
s--;
}
nscopes = ns;
}
/* ----------------------------------------------------------------------
* void real_objfree(DOH *ptr) - Free a DOH object for real.
* ---------------------------------------------------------------------- */
static void real_objfree(DOH *ptr) {
DohBase *b;
Fragment *f;
b = (DohBase *) ptr;
if (!b->objinfo) {
DohError(DOH_MEMORY,"DohObjFree. %x not properly defined. No objinfo structure.\n", ptr);
return; /* Improperly initialized object. leak some more */
}
f = (Fragment *) DohMalloc(sizeof(Fragment));
f->ptr = (char *) ptr;
f->len = (b->objinfo->objsize + 7) & ~0x07;
f->next = FreeFragments[f->len];
FreeFragments[f->len] = f;
}
/* ----------------------------------------------------------------------
* void DohGarbageCollect()
*
* This walks through all of the scopes and does garbage collection.
*
* 1. Objects with refcount <= 0 are released.
* 2. The scopes data structures are rebuilt and compacted.
* ---------------------------------------------------------------------- */
void
DohGarbageCollect() {
int s;
DohBase *b, *b1;
int ndeleted = 1;
DohError(DOH_MEMORY,"Garbage collecting.\n");
while (ndeleted) {
ndeleted = 0;
s = nscopes - 1;
while (s >= 0) {
b = scopes[s];
b1 = 0;
while (b) {
if ((b->refcount <= 0)) {
if (b1) {
b1->nextptr = b->nextptr;
} else {
scopes[s] = b->nextptr;
}
if (!(b->flags & DOH_FLAG_INTERN)) {
assert(!(b->flags & DOH_FLAG_GC));
real_objfree(b); /* Release the object */
b->flags = b->flags | DOH_FLAG_GC;
}
ndeleted++;
} else {
b1 = b;
}
b = (DohBase *) b->nextptr;
}
s--;
}
}
DohError(DOH_MEMORY,"Done garbage collecting.\n");
}
/* ----------------------------------------------------------------------
* void *DohObjMalloc(size_t size)
*
@ -135,26 +266,50 @@ void *DohObjMalloc(size_t size) {
Pool *p;
Fragment *f;
void *ptr = 0;
int garbage_collected = 0;
if (size > DOH_MAX_FRAG) return 0;
if (!pools_initialized) InitPools();
/* adjust the size for double word alignment */
size = (size + 7) & ~0x07;
retry:
p = Pools;
f = FreeFragments[size];
if (f) {
ptr = (void *) f->ptr;
FreeFragments[size] = f->next;
DohFree(f);
DohInit(ptr);
if (nscopes) {
((DohBase *) ptr)->scope = nscopes-1;
((DohBase *) ptr)->nextptr = scopes[nscopes-1];
scopes[nscopes-1] = (DohBase *) ptr;
}
return ptr;
}
/* No free fragments. See if the pool is large enough */
if (size < (p->len - p->current)) {
if ((int) size < (p->len - p->current)) {
ptr = (void *) (p->ptr + p->current);
p->current = (p->current + size + 7) & ~0x3;
/* p->current = (p->current + size + 7) & ~0x3; */
p->current = p->current + size;
DohInit(ptr);
if (nscopes) {
((DohBase *) ptr)->scope = nscopes-1;
((DohBase *) ptr)->nextptr = scopes[nscopes-1];
scopes[nscopes-1] = (DohBase *) ptr;
}
return ptr;
}
if (!garbage_collected) {
garbage_collected = 1;
DohGarbageCollect();
goto retry;
}
/* Pool is not large enough. Create a new pool */
if (p->len - p->current > 0) {
f = (Fragment *) DohMalloc(sizeof(Fragment));
@ -174,15 +329,11 @@ void *DohObjMalloc(size_t size) {
/* ----------------------------------------------------------------------
* void DohObjFree(DOH *ptr)
*
* Free a DOH object. Important! It must be a properly allocated
* DOH object. Not something else.
* Free a DOH object. This function doesn't do much of anything with GC.
* ---------------------------------------------------------------------- */
void DohObjFree(DOH *ptr) {
DohBase *b;
Fragment *f;
extern int doh_debug_level;
if (!DohCheck(ptr)) {
DohError(DOH_MEMORY,"DohObjFree. %x not a DOH object!\n", ptr);
@ -193,11 +344,6 @@ void DohObjFree(DOH *ptr) {
DohError(DOH_MEMORY,"DohObjFree. %x not properly defined. No objinfo structure.\n", ptr);
return; /* Improperly initialized object. leak some more */
}
f = (Fragment *) DohMalloc(sizeof(Fragment));
f->ptr = (char *) ptr;
f->len = b->objinfo->objsize;
f->next = FreeFragments[f->len];
FreeFragments[f->len] = f;
}
/* -----------------------------------------------------------------------------
@ -245,10 +391,10 @@ void *DohRealloc(void *ptr, size_t newsize) {
void DohFree(void *ptr) {
char *cptr = (char *) ptr;
int size;
if (!ptr) return;
size = *((int *) (cptr - 8));
free(cptr-8);
_DohMemoryCurrent = _DohMemoryCurrent - (size+8);
/* printf("Free %x %d\n", ptr, size);*/
}
/* -----------------------------------------------------------------------------
@ -273,3 +419,12 @@ int DohPoolSize(int poolsize) {
}
return ps;
}

View file

@ -56,7 +56,9 @@ int String_putc(DOH *s, int ch);
int String_ungetc(DOH *s, int ch);
int String_seek(DOH *s, long offset, int whence);
long String_tell(DOH *s);
int String_replace(DOH *str, DOH *token, DOH *rep, int flags);
void String_chop(DOH *str);
static DohSequenceMethods StringSeqMethods = {
0, /* doh_getitem */
0, /* doh_setitem */
@ -77,12 +79,17 @@ static DohFileMethods StringFileMethods = {
0,
};
static DohStringMethods StringStringMethods = {
String_replace,
};
static DohObjInfo StringType = {
"String", /* objname */
sizeof(String), /* objsize */
DelString, /* doh_del */
CopyString, /* doh_copy */
String_clear, /* doh_clear */
0, /* doh_scope */
String_str, /* doh_str */
String_data, /* doh_data */
String_dump, /* doh_dump */
@ -93,7 +100,7 @@ static DohObjInfo StringType = {
0, /* doh_mapping */
&StringSeqMethods, /* doh_sequence */
&StringFileMethods,/* doh_file */
0, /* doh_string */
&StringStringMethods, /* doh_string */
0, /* doh_callable */
};
@ -139,10 +146,9 @@ int String_dump(DOH *so, DOH *out) {
DOH *
NewString(char *s)
{
int l, max;
int l = 0, max;
String *str;
str = (String *) DohObjMalloc(sizeof(String));
DohInit(str);
str->objinfo = &StringType;
str->hashkey = -1;
str->sp = 0;
@ -172,11 +178,10 @@ NewString(char *s)
DOH *
CopyString(DOH *so) {
String *s;
int l, max;
int max;
String *str;
s = (String *) so;
str = (String *) DohObjMalloc(sizeof(String));
DohInit(str);
str->objinfo = &StringType;
str->hashkey = -1;
str->sp = 0;
@ -200,7 +205,9 @@ DelString(DOH *so) {
String *s;
s = (String *) so;
assert(s->refcount <= 0);
DohFree(s->str);
if (s->str)
DohFree(s->str);
s->str = 0;
DohObjFree(s);
}
@ -240,7 +247,7 @@ String_cmp(DOH *so1, DOH *so2)
{
String *s1, *s2;
char *c1, *c2;
int maxlen,i,ret;
int maxlen,i;
s1 = (String *) so1;
s2 = (String *) so2;
maxlen = s1->len;
@ -284,7 +291,7 @@ int String_hash(DOH *so) {
static void
add(String *s, const char *newstr) {
int newlen, newmaxsize, l;
int newlen, newmaxsize, l, i;
if (!newstr) return;
s->hashkey = -1;
l = (int) strlen(newstr);
@ -292,47 +299,39 @@ add(String *s, const char *newstr) {
if (newlen >= s->maxsize-1) {
newmaxsize = 2*s->maxsize;
if (newlen >= newmaxsize -1) newmaxsize = newlen + 1;
assert(s->str = (char *) DohRealloc(s->str,newmaxsize));
s->str = (char *) DohRealloc(s->str,newmaxsize);
assert(s->str);
s->maxsize = newmaxsize;
}
strcpy(s->str+s->len,newstr);
if (s->sp >= s->len)
s->sp+=l;
s->len += l;
}
static void
addstr(String *s, String *s1) {
int newlen, newmaxsize, l;
s->hashkey = -1;
l = s1->len;
newlen = s->len+l + 1;
if (newlen >= s->maxsize-1) {
newmaxsize = 2*s->maxsize;
if (newlen >= newmaxsize -1) newmaxsize = newlen + 1;
assert(s->str = (char *) DohRealloc(s->str,newmaxsize));
s->maxsize = newmaxsize;
if (s->sp >= s->len) {
#ifdef DOH_STRING_UPDATE_LINES
for (i = s->sp; i < s->len+l; i++) {
if (s->str[i] == '\n') s->line++;
}
#endif
s->sp = s->len+l;
}
memmove(s->str+s->len,s1->str,s1->len);
if (s->sp >= s->len) s->sp+=l;
s->len += l;
}
/* Add a single character to s */
void
String_addchar(DOH *so, char c) {
String *s = (String *) so;
s->hashkey = -1;
if ((s->len+1) > (s->maxsize-1)) {
assert(s->str = (char *) DohRealloc(s->str,2*s->maxsize));
s->str = (char *) DohRealloc(s->str,2*s->maxsize);
assert(s->str);
s->maxsize *= 2;
}
s->str[s->len] = c;
if (s->sp >= s->len) {
s->sp++;
s->sp = s->len+1;
s->str[s->len+1] = 0;
#ifdef DOH_STRING_UPDATE_LINES
if (c == '\n') s->line++;
#endif
}
s->len++;
}
@ -341,7 +340,8 @@ String_addchar(DOH *so, char c) {
void
String_expand(String *s, int width) {
if ((s->len + width) > (s->maxsize-1)) {
assert(s->str = (char *) DohRealloc(s->str,(s->len + width)+1));
s->str = (char *) DohRealloc(s->str,(s->len + width)+1);
assert(s->str);
s->maxsize = s->len + width + 1;
}
}
@ -357,7 +357,7 @@ String_clear(DOH *so)
s = (String *) so;
s->hashkey = -1;
s->len = 0;
s->str[0] = 0;
*(s->str) = 0;
s->sp = 0;
s->lsp = 0;
s->line = 1;
@ -380,11 +380,22 @@ raw_insert(String *s, int pos, char *data, int len)
/* See if there is room to insert the new data */
while (s->maxsize <= s->len+len) {
assert(s->str = (char *) DohRealloc(s->str,2*s->maxsize));
s->str = (char *) DohRealloc(s->str,2*s->maxsize);
assert(s->str);
s->maxsize *= 2;
}
memmove(s->str+pos+len, s->str+pos, (s->len - pos));
memcpy(s->str+pos,data,len);
if (s->sp >= s->len) {
int i;
s->sp = s->len;
#ifdef DOH_STRING_UPDATE_LINES
for (i = 0; i < len; i++) {
if (data[i] == '\n') s->line++;
}
#endif
s->sp+=len;
}
s->len += len;
s->str[s->len] = 0;
}
@ -399,7 +410,7 @@ String_insert(DOH *so, int pos, DOH *str)
char *c;
int len;
s = (String *) so;
assert(s->refcount <= 1);
/* assert(s->refcount <= 1); */
s1 = (String *) str;
len = s1->len;
c = s1->str;
@ -419,9 +430,14 @@ int String_delitem(DOH *so, int pos)
s->hashkey = -1;
if (pos == DOH_END) pos = s->len-1;
if (pos == DOH_BEGIN) pos = 0;
if (s->len == 0) return 0;
if (s->len == 0) return;
if (s->sp > pos) {
s->sp--;
#ifdef DOH_STRING_UPDATE_LINES
if (s->str[pos] == '\n') s->line--;
#endif
}
memmove(s->str+pos, s->str+pos+1, ((s->len-1) - pos));
s->len--;
s->str[s->len] = 0;
@ -448,10 +464,10 @@ String_str(DOH *so) {
int
String_read(DOH *so, void *buffer, int len) {
int reallen, retlen;
int i;
char *cb;
String *s = (String *) so;
if (((s->sp-s->pbi) + len) > s->len) reallen = (s->len - (s->sp-s->pbi));
else reallen = len;
cb = (char *) buffer;
retlen = reallen;
@ -476,12 +492,13 @@ String_read(DOH *so, void *buffer, int len) {
* ----------------------------------------------------------------------------- */
int
String_write(DOH *so, void *buffer, int len) {
int reallen, newlen, newmaxsize;
int newlen;
String *s = (String *) so;
s->hashkey = -1;
newlen = s->sp + len+1;
if (newlen > s->maxsize) {
assert(s->str = (char *) DohRealloc(s->str,newlen));
s->str = (char *) DohRealloc(s->str,newlen);
assert(s->str);
s->maxsize = newlen;
s->len = s->sp + len;
}
@ -499,23 +516,34 @@ String_write(DOH *so, void *buffer, int len) {
* ----------------------------------------------------------------------------- */
int
String_seek(DOH *so, long offset, int whence) {
int pos;
int pos, nsp, inc;
String *s = (String *) so;
if (whence == SEEK_SET) pos = 0;
if (whence == SEEK_CUR) pos = s->sp;
if (whence == SEEK_END) {
else if (whence == SEEK_CUR) pos = s->sp;
else if (whence == SEEK_END) {
pos = s->len;
offset = -offset;
}
s->sp = pos + offset;
if (s->sp < 0) s->sp = 0;
if (s->sp > s->len) s->sp = s->len;
else pos = s->sp;
nsp = pos + offset;
if (nsp < 0) nsp = 0;
if (nsp > s->len) nsp = s->len;
if (nsp > s->sp) inc = 1;
else inc = -1;
#ifdef DOH_STRING_UPDATE_LINES
while (s->sp != nsp) {
if (s->str[s->sp-1] == '\n') s->line += inc;
s->sp += inc;
}
#endif
s->sp = nsp;
s->pbi = 0;
return 0;
}
/* -----------------------------------------------------------------------------
* long String_seek(DOH *so)
* long String_tell(DOH *so)
*
* Return current position
* ----------------------------------------------------------------------------- */
@ -540,6 +568,9 @@ String_putc(DOH *so, int ch) {
} else {
s->str[s->sp] = (char) ch;
s->sp++;
#ifdef DOH_STRING_UPDATE_LINES
if (ch == '\n') s->line++;
#endif
}
s->pbi = 0;
return ch;
@ -548,28 +579,30 @@ String_putc(DOH *so, int ch) {
/* -----------------------------------------------------------------------------
* int String_getc(DOH *so)
*
* Get a character from the string
* Get a character from the string. Updates the line number.
* ----------------------------------------------------------------------------- */
int String_getc(DOH *so) {
int c;
String *s = (String *) so;
if (s->pbi) {
return (int) s->pb[--s->pbi];
}
if (s->sp >= s->len) return EOF;
else return (int) s->str[s->sp++];
c = (int) s->pb[--s->pbi];
} else if (s->sp >= s->len) c = EOF;
else c = (int) s->str[s->sp++];
#ifdef DOH_STRING_UPDATE_LINES
if (c == '\n') s->line++;
#endif
return c;
}
/* -----------------------------------------------------------------------------
* int String_ungetc(DOH *so, int ch)
*
* Put a character back on to the input stream.
* Put a character back on to the input stream. Updates the line count.
* ----------------------------------------------------------------------------- */
int String_ungetc(DOH *so, int ch) {
String *s = (String *) so;
int i;
if (ch == EOF) return ch;
if ((s->sp - s->pbi) <= 0) return EOF;
if (s->pbi == 4) {
@ -580,11 +613,14 @@ int String_ungetc(DOH *so, int ch) {
} else {
s->pb[s->pbi++] = (char) ch;
}
#ifdef DOH_STRING_UPDATE_LINES
if (ch == '\n') s->line--;
#endif
return ch;
}
/* -----------------------------------------------------------------------------
* static void replace_internal(String *str, char *token, char *rep, int flags, char *start, int count)
* int replace_internal(String *str, char *token, char *rep, int flags, char *start, int count)
*
* Replaces token with rep. flags is as follows:
*
@ -596,11 +632,13 @@ int String_ungetc(DOH *so, int ch) {
* start is a starting position. count is a count.
* ----------------------------------------------------------------------------- */
void replace_internal(String *str, char *token, char *rep, int flags, char *start, int count)
static
int replace_internal(String *str, char *token, char *rep, int flags, char *start, int count)
{
char *s, *c, *t;
int tokenlen;
int state;
int repcount = 0;
/* Copy the current string representation */
@ -646,6 +684,7 @@ void replace_internal(String *str, char *token, char *rep, int flags, char *star
c += (tokenlen-1);
t = c+1;
count--;
repcount++;
}
} else if (isalpha(*c) || (*c == '_') || (*c == '$')) {
char temp = *c;
@ -668,6 +707,7 @@ void replace_internal(String *str, char *token, char *rep, int flags, char *star
if (strcmp(token,t) == 0) {
add(str,rep);
count--;
repcount++;
} else {
add(str,t);
}
@ -698,20 +738,50 @@ void replace_internal(String *str, char *token, char *rep, int flags, char *star
}
DohFree(s);
}
return repcount;
}
/* -----------------------------------------------------------------------------
* void String_replace(DOH *str, DOH *token, DOH *rep, int flags)
* int String_replace(DOH *str, DOH *token, DOH *rep, int flags)
* ----------------------------------------------------------------------------- */
void
int
String_replace(DOH *stro, DOH *token, DOH *rep, int flags)
{
int count = -1;
String *str;
if (!String_check(stro)) return;
if (!String_check(stro)) return 0;
str = (String *) stro;
assert(!str->refcount);
assert(str->refcount);
/* assert(!str->refcount); */
if (flags & DOH_REPLACE_FIRST) count = 1;
replace_internal(str,Char(token),Char(rep),flags,str->str,count);
return replace_internal(str,Char(token),Char(rep),flags,str->str,count);
}
/* -----------------------------------------------------------------------------
* void String_chop(DOH *str)
* ----------------------------------------------------------------------------- */
void
String_chop(DOH *s) {
char *c;
String *str = (String *) s;
if (!String_check(s)) return;
/* assert(!str->refcount); */
/* Replace trailing whitespace */
c = str->str + str->len - 1;
while ((str->len >= 0) && (isspace(*c))) {
if (str->sp >= str->len) {
str->sp--;
#ifdef DOH_STRING_UPDATE_LINES
if (*c == '\n') str->line--;
#endif
}
str->len--;
c--;
}
str->hashkey = -1;
str->pbi = 0;
}

View file

@ -37,6 +37,7 @@ static DohObjInfo DohVoidType = {
Void_delete, /* doh_del */
Void_copy, /* doh_copy */
0, /* doh_clear */
0, /* doh_scope */
0, /* doh_str */
Void_data, /* doh_data */
0, /* doh_dump */
@ -62,7 +63,6 @@ static DohObjInfo DohVoidType = {
DOH *NewVoid(void *obj, void (*del)(void *)) {
VoidObj *v;
v = (VoidObj *) DohObjMalloc(sizeof(VoidObj));
DohInit(v);
v->objinfo = &DohVoidType;
v->ptr = obj;
v->del = del;
@ -74,6 +74,7 @@ void Void_delete(DOH *vo) {
if (v->del) {
(*v->del)(v->ptr);
}
v->del = 0;
DohObjFree(v);
}

View file

@ -103,6 +103,7 @@ typedef struct DohObjInfo {
void (*doh_del)(DOH *obj); /* Delete object */
DOH *(*doh_copy)(DOH *obj); /* Copy and object */
void (*doh_clear)(DOH *obj); /* Clear an object */
void (*doh_scope)(DOH *obj, int s); /* Change the scope on an object */
/* Output methods */
DOH *(*doh_str)(DOH *obj); /* Make a full string */
@ -133,6 +134,7 @@ typedef struct DohObjInfo {
/* Memory management */
extern void *DohMalloc(size_t size);
extern void *DohRealloc(void *, size_t size);
extern void *DohObjMalloc(size_t size);
extern void DohFree(DOH *ptr);
extern void DohObjFree(DOH *ptr);
@ -142,6 +144,11 @@ extern int DohFreeCheck(DOH *ptr);
extern int DohMemoryUse();
extern int DohMemoryHigh();
extern int DohPoolSize(int);
extern int DohNewScope();
extern void DohDelScope(int);
extern void DohGarbageCollect();
extern void DohSetScope(DOH *, int scp);
extern void DohIntern(DOH *);
/* Low-level doh methods. Do not call directly (well, unless you want to). */
extern void DohError(int level, char *fmt,...);
@ -184,7 +191,7 @@ extern void DohSetDouble(DOH *obj, DOH *name, double);
extern int DohWrite(DOH *obj, void *buffer, int length);
extern int DohRead(DOH *obj, void *buffer, int length);
extern int DohSeek(DOH *obj, long offser, int whence);
extern int DohSeek(DOH *obj, long offset, int whence);
extern long DohTell(DOH *obj);
extern int DohGetc(DOH *obj);
extern int DohPutc(int ch, DOH *obj);
@ -196,6 +203,7 @@ extern int DohvPrintf(DOH *obj, char *format, va_list ap);
/* extern int DohScanf(DOH *obj, char *format, ...);
extern int DohvScanf(DOH *obj, char *format, va_list ap); */
extern int DohReplace(DOH *src, DOH *token, DOH *rep, int flags);
extern DOH *DohReadline(DOH *in);
#ifndef DOH_LONG_NAMES
@ -247,6 +255,9 @@ extern DOH *DohReadline(DOH *in);
#define Firstitem DohFirstitem
#define Nextitem DohNextitem
#define Readline DohReadline
#define Replace DohReplace
#define NewScope DohNewScope
#define DelScope DohDelScope
#endif
@ -258,8 +269,11 @@ extern DOH *DohReadline(DOH *in);
#define DOHCOMMON \
DohObjInfo *objinfo; \
DOH *nextptr; \
int refcount; \
int line; \
short line; \
unsigned char flags; \
unsigned char scope; \
DOH *file
typedef struct {
@ -267,17 +281,31 @@ typedef struct {
} DohBase;
/* Macros for decrefing and increfing (safe for null objects). */
#define Decref(a) if (a) ((DohBase *) a)->refcount--;
#define Incref(a) if (a) ((DohBase *) a)->refcount++;
#define Decref(a) if (a) ((DohBase *) a)->refcount--
#define Incref(a) if (a) ((DohBase *) a)->refcount++
#define Refcount(a) ((DohBase *) a)->refcount
#define Getscope(a) ((DohBase *) a)->scope
#define Setscope(a,s) DohSetScope(a,s)
#define Objname(a) ((DohBase *) a)->objinfo->objname
/* Flags for various internal operations */
#define DOH_FLAG_SETSCOPE 0x01
#define DOH_FLAG_PRINT 0x02
#define DOH_FLAG_DELSCOPE 0x04
#define DOH_FLAG_GC 0x08
#define DOH_FLAG_INTERN 0x10
/* -----------------------------------------------------------------------------
* Strings.
* ----------------------------------------------------------------------------- */
extern DOH *NewString(char *c);
extern int String_check(DOH *s);
extern void String_replace(DOH *s, DOH *token, DOH *rep, int flags);
extern int String_replace(DOH *s, DOH *token, DOH *rep, int flags);
extern void String_chop(DOH *s);
/* String replacement flags */
@ -322,6 +350,8 @@ extern DOH *NewVoid(void *ptr, void (*del)(void *));
extern DOH *DohSplit(DOH *input, char *chs, int nsplits);
#define Split DohSplit
extern DOH *DohNone;
/* -----------------------------------------------------------------------------
* Error handling levels.
* ----------------------------------------------------------------------------- */