diff options
| author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2009-08-18 20:56:02 +0000 |
|---|---|---|
| committer | Lorry <lorry@roadtrain.codethink.co.uk> | 2012-09-25 16:59:08 +0000 |
| commit | 9f8a09ed743cedd9547bf0661d518647966ab114 (patch) | |
| tree | 9c7803d3b27a8ec22e91792ac7f7932efa128b20 /Source/DOH | |
| download | swig-tarball-master.tar.gz | |
Imported from /srv/lorry/lorry-area/swig-tarball/swig-1.3.40.tar.gz.HEADswig-1.3.40master
Diffstat (limited to 'Source/DOH')
| -rw-r--r-- | Source/DOH/README | 118 | ||||
| -rw-r--r-- | Source/DOH/base.c | 943 | ||||
| -rw-r--r-- | Source/DOH/doh.h | 442 | ||||
| -rw-r--r-- | Source/DOH/dohint.h | 133 | ||||
| -rw-r--r-- | Source/DOH/file.c | 299 | ||||
| -rw-r--r-- | Source/DOH/fio.c | 589 | ||||
| -rw-r--r-- | Source/DOH/hash.c | 551 | ||||
| -rw-r--r-- | Source/DOH/list.c | 377 | ||||
| -rw-r--r-- | Source/DOH/memory.c | 220 | ||||
| -rw-r--r-- | Source/DOH/string.c | 1158 | ||||
| -rw-r--r-- | Source/DOH/void.c | 96 |
11 files changed, 4926 insertions, 0 deletions
diff --git a/Source/DOH/README b/Source/DOH/README new file mode 100644 index 0000000..9a42e8b --- /dev/null +++ b/Source/DOH/README @@ -0,0 +1,118 @@ +DOH (Dave's Object Hack) + +Overview: +--------- +DOH is a small C library that provides a number of simple yet powerful +data structures. The data structures are built around a dynamic typing +model in which any given object is allowed to support one or more +classes of operations. Furthermore, a simple garbage collection +scheme and a variety of interesting library methods are available. +All and all, the operation of DOH makes massive abuse of the C type +system and would probably make the language purists scream and +performance addicts run away in horror. However, I really don't +care--so there! However, for the rest of us, DOH is actually kind of +fun to use. This is only a short description of the methods and is no +way meant to be exhaustive. + +Common Operations (for all types) +--------------------------------- +Delete(obj) Decrease the reference count and destroy if zero +Copy(obj) Make a copy of an object. +Clear(obj) Clear an object. +Setscope(obj) Set scope of an object (guru's only) +Str(obj) Create a string representation of obj. +Data(obj) Return pointer to raw data in an object +Char(obj) Convert to a char * +Len(obj) Length of an object +Hash(obj) Hash value (used for mapping) +Cmp(obj1,obj2) Compare two objects. +Name(obj) Return the object name +First(obj) Return first object (iterator) +Next(obj) Return next object +Dump(obj,out) Serialize on out +Load(in) Unserialize from in +First(obj) Iterator +Next(iter) Next iterator + +Mapping Operations (for hash table behavior) +-------------------------------------------- +Getattr(hash,key) Get an attribute +Setattr(hash,key,value) Set an attribute +Delattr(hash,key) Delete an attribute +First(hash) Get first object (iterator) +Next(hash) Get next object +GetInt(hash,key) Get attribute as an 'int' +SetInt(hash,key,ivalue) Set attribute as an 'int' +GetDouble(hash,key) Get attribute as a 'double' +SetDouble(hash,key,dvalue) Set Attribute as a 'double' +GetChar(hash,key) Get attribute as a 'char *' + +Sequence Operations +------------------- +Getitem(list,index) Get an item +Setitem(list,index,val) Set an item +Delitem(list,index,val) Delete an item +Insert(list,index,val) Insert an item +Append(list,val) Append to end +Push(list,val) Insert at beginning + +File Operations +--------------- +Read(obj,buffer,len) Read data +Write(obj,buffer,len) Write data +Getc(obj) Get a character +Putc(ch,obj) Put a character +Ungetc(ch,obj) Put character back on input stream +Seek(obj,offset,whence) Seek +Tell(obj) Return file pointer +Close(obj) Close + +String Operations +----------------- +Replace(obj, orig, rep, flags) Replace occurences of orig with rep. +Chop(obj) Remove trailing whitespace + +flags is one of the following: + DOH_REPLACE_ANY + DOH_REPLACE_NOQUOTE + DOH_REPLACE_ID + DOH_REPLACE_FIRST + +Callable Operations +------------------- +Call(obj, args) Perform a function call with arguments args. + +Miscellaneous library functions +------------------------------- +NewScope() Create a new scope +DelScope(s) Delete scope s +Readline(in) Read a line of input from in +Printf(out,fmt,...) Formatted output +DohEncoding(name, fn) Register a format encoding for Printf + +Currently Available datatypes +------------------------------ +NewString(char *initial) Strings +NewHash() Hash +NewList() List +NewVoid(void *ptr, void (*del)(void *)) Void +NewFile(char *filename, char *mode, List *newfiles) File +NewCallable(DOH *(*func)(DOH *, DOH *)) Callable object + + +Odds and ends: + + 1. All objects are of type 'DOH *' + 2. When in doubt, see rule (1) + 3. In certain cases, DOH performs implicit conversions + of 'char *' to an appropriate DOH string representation. + For operations involving files, DOH works with many + kinds of objects including FILE *, DOH File objects, + and DOH strings. Don't even ask how this works. + + 4. More complete documentation is forthcoming. + + + + + diff --git a/Source/DOH/base.c b/Source/DOH/base.c new file mode 100644 index 0000000..4262e70 --- /dev/null +++ b/Source/DOH/base.c @@ -0,0 +1,943 @@ +/* ----------------------------------------------------------------------------- + * base.c + * + * This file contains the function entry points for dispatching methods on + * DOH objects. A number of small utility functions are also included. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_base_c[] = "$Id: base.c 11097 2009-01-30 10:27:37Z bhy $"; + +#include "dohint.h" + +/* ----------------------------------------------------------------------------- + * DohDelete() + * ----------------------------------------------------------------------------- */ + +#ifndef SWIG_DEBUG_DELETE +#define SWIG_DEBUG_DELETE 0 +#endif + +void DohDelete(DOH *obj) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo; + + if (!obj) + return; +#if SWIG_DEBUG_DELETE + if (!DohCheck(b)) { + fputs("DOH: Fatal error. Attempt to delete a non-doh object.\n", stderr); + abort(); + } +#endif + if (b->flag_intern) + return; + assert(b->refcount > 0); + b->refcount--; + if (b->refcount <= 0) { + objinfo = b->type; + if (objinfo->doh_del) { + (objinfo->doh_del) (b); + } else { + if (b->data) + DohFree(b->data); + } + DohObjFree(b); + } +} + +/* ----------------------------------------------------------------------------- + * DohCopy() + * ----------------------------------------------------------------------------- */ + +DOH *DohCopy(const DOH *obj) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo; + + if (!obj) + return 0; + objinfo = b->type; + if (objinfo->doh_copy) { + DohBase *bc = (DohBase *) (objinfo->doh_copy) (b); + if ((bc) && b->meta) { + bc->meta = Copy(b->meta); + } + return (DOH *) bc; + } + return 0; +} + +void DohIncref(DOH *obj) { + Incref(obj); +} + +/* ----------------------------------------------------------------------------- + * DohClear() + * ----------------------------------------------------------------------------- */ + +void DohClear(DOH *obj) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo = b->type; + if (objinfo->doh_clear) + (objinfo->doh_clear) (b); +} + +/* ----------------------------------------------------------------------------- + * DohStr() + * ----------------------------------------------------------------------------- */ + +DOH *DohStr(const DOH *obj) { + char buffer[512]; + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo; + if (DohCheck(b)) { + objinfo = b->type; + if (objinfo->doh_str) { + return (objinfo->doh_str) (b); + } + sprintf(buffer, "<Object '%s' at %p>", objinfo->objname, (void *) b); + return NewString(buffer); + } else { + return NewString(obj); + } +} + +/* ----------------------------------------------------------------------------- + * DohDump() + * ----------------------------------------------------------------------------- */ + +int DohDump(const DOH *obj, DOH *out) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo = b->type; + if (objinfo->doh_dump) { + return (objinfo->doh_dump) (b, out); + } + return 0; +} + +/* ----------------------------------------------------------------------------- + * DohLen() - Defaults to strlen() if not a DOH object + * ----------------------------------------------------------------------------- */ +int DohLen(const DOH *obj) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo; + if (!b) + return 0; + if (DohCheck(b)) { + objinfo = b->type; + if (objinfo->doh_len) { + return (objinfo->doh_len) (b); + } + return 0; + } else { + return strlen((char *) obj); + } +} + +/* ----------------------------------------------------------------------------- + * DohHashVal() + * ----------------------------------------------------------------------------- */ + +int DohHashval(const DOH *obj) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo; + /* obj is already checked and/or converted into DohBase* */ + /* if (DohCheck(b)) */ + { + objinfo = b->type; + if (objinfo->doh_hashval) { + return (objinfo->doh_hashval) (b); + } + } + return 0; +} + +/* ----------------------------------------------------------------------------- + * DohData() + * ----------------------------------------------------------------------------- */ + +void *DohData(const DOH *obj) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo; + if (DohCheck(obj)) { + objinfo = b->type; + if (objinfo->doh_data) { + return (objinfo->doh_data) (b); + } + return 0; + } + return (void *) obj; +} + +/* ----------------------------------------------------------------------------- + * RawData() + * ----------------------------------------------------------------------------- */ + +static void *RawData(DohBase *b) { + DohObjInfo *objinfo = b->type; + return (objinfo->doh_data) ? (objinfo->doh_data) (b) : 0; +} + + +/* ----------------------------------------------------------------------------- + * DohCmp() + * ----------------------------------------------------------------------------- */ + +int DohCmp(const DOH *obj1, const DOH *obj2) { + DohBase *b1, *b2; + DohObjInfo *b1info, *b2info; + int c1, c2; + b1 = (DohBase *) obj1; + b2 = (DohBase *) obj2; + c1 = DohCheck(b1); + c2 = DohCheck(b2); + /* most of the times, obj2 is a plain c string */ + if (!c1 || !c2) { + if ((b1 == 0) && (b2 == 0)) + return 0; + if (b1 && !b2) + return 1; + if (!b1 && b2) + return -1; + return strcmp((char *) (c1 ? RawData(b1) : (void *) obj1), (char *) (c2 ? RawData(b2) : (void *) obj2)); + } + b1info = b1->type; + b2info = b2->type; + if ((b1info == b2info) && (b1info->doh_cmp)) + return (b1info->doh_cmp) (b1, b2); + return 1; +} + +/* ----------------------------------------------------------------------------- + * DohEqual() + * ----------------------------------------------------------------------------- */ + +int DohEqual(const DOH *obj1, const DOH *obj2) { + DohBase *b1 = (DohBase *) obj1; + DohBase *b2 = (DohBase *) obj2; + if (!b1) { + return !b2; + } else if (!b2) { + return 0; + } else { + DohObjInfo *b1info = 0; + DohObjInfo *b2info = 0; + if (DohCheck(b1)) { + b1info = b1->type; + if (DohCheck(b2)) { + b2info = b2->type; + } else { + int len = (b1info->doh_len) (b1); + char *cobj = (char *) obj2; + return len == (int) strlen(cobj) ? (memcmp(RawData(b1), cobj, len) == 0) : 0; + } + } else if (DohCheck(b2)) { + int len = (b2->type->doh_len) (b2); + char *cobj = (char *) obj1; + return len == (int) strlen(cobj) ? (memcmp(RawData(b2), cobj, len) == 0) : 0; + } else { + return strcmp((char *) obj1, (char *) obj2) == 0; + } + + if (!b1info) { + return obj1 == obj2; + } else if ((b1info == b2info)) { + return b1info->doh_equal ? (b1info->doh_equal) (b1, b2) : (b1info->doh_cmp ? (b1info->doh_cmp) (b1, b2) == 0 : (b1 == b2)); + } else { + return 0; + } + } +} + +/* ----------------------------------------------------------------------------- + * DohFirst() + * ----------------------------------------------------------------------------- */ + +DohIterator DohFirst(DOH *obj) { + DohIterator iter; + DohBase *b; + DohObjInfo *binfo; + + b = (DohBase *) obj; + if (DohCheck(b)) { + binfo = b->type; + if (binfo->doh_first) { + return (binfo->doh_first) (b); + } + } + iter.object = 0; + iter.item = 0; + iter.key = 0; + iter._current = 0; + iter._index = 0; + return iter; +} + +/* ----------------------------------------------------------------------------- + * DohNext() + * ----------------------------------------------------------------------------- */ + +DohIterator DohNext(DohIterator iter) { + DohIterator niter; + + if (iter.object) { + DohBase *b; + DohObjInfo *binfo; + + b = (DohBase *) iter.object; + binfo = b->type; + if (binfo->doh_next) { + return (binfo->doh_next) (iter); + } + } + niter = iter; + return niter; +} + +/* ----------------------------------------------------------------------------- + * DohIsMapping() + * ----------------------------------------------------------------------------- */ +int DohIsMapping(const DOH *obj) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo; + if (!DohCheck(b)) + return 0; + objinfo = b->type; + if (objinfo->doh_hash) + return 1; + else + return 0; +} + +/* ----------------------------------------------------------------------------- + * DohGetattr() + * ----------------------------------------------------------------------------- */ + +DOH *DohGetattr(DOH *obj, const DOH *name) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo = b->type; + if (objinfo->doh_hash && objinfo->doh_hash->doh_getattr) { + DOH *r = (objinfo->doh_hash->doh_getattr) (b, (DOH *) name); + return (r == DohNone) ? 0 : r; + } + return 0; +} + +/* ----------------------------------------------------------------------------- + * DohSetattr() + * ----------------------------------------------------------------------------- */ + +int DohSetattr(DOH *obj, const DOH *name, const DOH *value) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo = b->type; + if (objinfo->doh_hash && objinfo->doh_hash->doh_setattr) { + return (objinfo->doh_hash->doh_setattr) (b, (DOH *) name, (DOH *) value); + } + return 0; +} + +/* ----------------------------------------------------------------------------- + * DohDelattr() + * ----------------------------------------------------------------------------- */ + +int DohDelattr(DOH *obj, const DOH *name) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo = b->type; + if (objinfo->doh_hash && objinfo->doh_hash->doh_delattr) { + return (objinfo->doh_hash->doh_delattr) (b, (DOH *) name); + } + return 0; +} + +/* ----------------------------------------------------------------------------- + * DohCheckattr() + * ----------------------------------------------------------------------------- */ + +int DohCheckattr(DOH *obj, const DOH *name, const DOH *value) { + DOH *attr = Getattr(obj,name); + if (!attr) return 0; + return DohEqual(attr,value); +} + +/* ----------------------------------------------------------------------------- + * DohKeys() + * ----------------------------------------------------------------------------- */ + +DOH *DohKeys(DOH *obj) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo = b->type; + if (objinfo && objinfo->doh_hash->doh_keys) { + return (objinfo->doh_hash->doh_keys) (b); + } + return 0; +} + +/* ----------------------------------------------------------------------------- + * DohGetInt() + * ----------------------------------------------------------------------------- */ + +int DohGetInt(DOH *obj, const DOH *name) { + DOH *val; + val = Getattr(obj, (DOH *) name); + if (!val) + return 0; + if (DohIsString(val)) { + return atoi((char *) Data(val)); + } + return 0; +} + +/* ----------------------------------------------------------------------------- + * DohGetDouble() + * ----------------------------------------------------------------------------- */ + +double DohGetDouble(DOH *obj, const DOH *name) { + DOH *val; + val = Getattr(obj, (DOH *) name); + if (!val) + return 0; + if (DohIsString(val)) { + return atof((char *) Data(val)); + } + return 0; +} + +/* ----------------------------------------------------------------------------- + * DohGetChar() + * ----------------------------------------------------------------------------- */ + +char *DohGetChar(DOH *obj, const DOH *name) { + DOH *val; + val = Getattr(obj, (DOH *) name); + if (!val) + return 0; + if (DohIsString(val)) { + return (char *) Data(val); + } + return 0; +} + +/* ----------------------------------------------------------------------------- + * DohGetFlagAttr() / DohGetFlag() + * A flag is unset if the attribute (name) does not exist on the node (obj), + * or it is set to "0". If the attribute is set to any other value, + * the flag is set. + * + * DohGetFlag() returns if the flag is set or not + * DohGetFlagAttr() returns the flag value if is set, NULL otherwise + * ----------------------------------------------------------------------------- */ + + +DOH *DohGetFlagAttr(DOH *obj, const DOH *name) { + DOH *val = Getattr(obj, (DOH *) name); + if (!val) { + return NULL; + } else { + const char *cval = Char(val); + if (!cval) + return val; + return (strcmp(cval, "0") != 0) ? val : NULL; + } +} + +int DohGetFlag(DOH *obj, const DOH *name) { + return DohGetFlagAttr(obj, name) ? 1 : 0; +} + + +/* ----------------------------------------------------------------------------- + * DohGetVoid() + * ----------------------------------------------------------------------------- */ + +void *DohGetVoid(DOH *obj, const DOH *name) { + DOH *val; + val = Getattr(obj, (DOH *) name); + if (!val) + return 0; + return (void *) Data(val); +} + +/* ----------------------------------------------------------------------------- + * DohSetInt() + * ----------------------------------------------------------------------------- */ + +void DohSetInt(DOH *obj, const DOH *name, int value) { + DOH *temp; + temp = NewStringEmpty(); + Printf(temp, "%d", value); + Setattr(obj, (DOH *) name, temp); +} + +/* ----------------------------------------------------------------------------- + * DohSetDouble() + * ----------------------------------------------------------------------------- */ + +void DohSetDouble(DOH *obj, const DOH *name, double value) { + DOH *temp; + temp = NewStringEmpty(); + Printf(temp, "%0.17f", value); + Setattr(obj, (DOH *) name, temp); +} + +/* ----------------------------------------------------------------------------- + * DohSetChar() + * ----------------------------------------------------------------------------- */ + +void DohSetChar(DOH *obj, const DOH *name, char *value) { + Setattr(obj, (DOH *) name, NewString(value)); +} + +/* ----------------------------------------------------------------------------- + * DohSetFlag() + * ----------------------------------------------------------------------------- */ + +void DohSetFlagAttr(DOH *obj, const DOH *name, const DOH *attr) { + Setattr(obj, (DOH *) name, attr ? attr : NewString("0")); +} + +void DohSetFlag(DOH *obj, const DOH *name) { + Setattr(obj, (DOH *) name, NewString("1")); +} + +/* ----------------------------------------------------------------------------- + * DohSetVoid() + * ----------------------------------------------------------------------------- */ + +void DohSetVoid(DOH *obj, const DOH *name, void *value) { + Setattr(obj, (DOH *) name, NewVoid(value, 0)); +} + +/* ----------------------------------------------------------------------------- + * DohIsSequence() + * ----------------------------------------------------------------------------- */ + +int DohIsSequence(const DOH *obj) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo; + if (!DohCheck(b)) + return 0; + objinfo = b->type; + if (objinfo->doh_list) + return 1; + else + return 0; +} + +/* ----------------------------------------------------------------------------- + * DohGetitem() + * ----------------------------------------------------------------------------- */ + +DOH *DohGetitem(DOH *obj, int index) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo = b->type; + if (objinfo->doh_list && objinfo->doh_list->doh_getitem) { + return (objinfo->doh_list->doh_getitem) (b, index); + } + return 0; +} + +/* ----------------------------------------------------------------------------- + * DohSetitem() + * ----------------------------------------------------------------------------- */ + +int DohSetitem(DOH *obj, int index, const DOH *value) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo = b->type; + if (objinfo->doh_list && objinfo->doh_list->doh_setitem) { + return (objinfo->doh_list->doh_setitem) (b, index, (DOH *) value); + } + return -1; +} + +/* ----------------------------------------------------------------------------- + * DohDelitem() + * ----------------------------------------------------------------------------- */ + +int DohDelitem(DOH *obj, int index) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo = b->type; + if (objinfo->doh_list && objinfo->doh_list->doh_delitem) { + return (objinfo->doh_list->doh_delitem) (b, index); + } + return -1; +} + +/* ----------------------------------------------------------------------------- + * DohInsertitem() + * ----------------------------------------------------------------------------- */ + +int DohInsertitem(DOH *obj, int index, const DOH *value) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo = b->type; + if (objinfo->doh_list && objinfo->doh_list->doh_insitem) { + return (objinfo->doh_list->doh_insitem) (b, index, (DOH *) value); + } + return -1; +} + + +/* ----------------------------------------------------------------------------- + * DohDelslice() + * ----------------------------------------------------------------------------- */ + +int DohDelslice(DOH *obj, int sindex, int eindex) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo = b->type; + if (objinfo->doh_list && objinfo->doh_list->doh_delslice) { + return (objinfo->doh_list->doh_delslice) (b, sindex, eindex); + } + return -1; +} + +/* ----------------------------------------------------------------------------- + * DohIsFile() + * ----------------------------------------------------------------------------- */ + +int DohIsFile(const DOH *obj) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo; + if (!DohCheck(b)) + return 0; + objinfo = b->type; + if (objinfo->doh_file) + return 1; + else + return 0; +} + +/* ----------------------------------------------------------------------------- + * DohRead() + * ----------------------------------------------------------------------------- */ + +int DohRead(DOH *obj, void *buffer, int length) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo; + if (DohCheck(obj)) { + objinfo = b->type; + if ((objinfo->doh_file) && (objinfo->doh_file->doh_read)) { + return (objinfo->doh_file->doh_read) (b, buffer, length); + } + return -1; + } + /* Hmmm. Not a file. Maybe it's a real FILE */ + return fread(buffer, 1, length, (FILE *) b); +} + +/* ----------------------------------------------------------------------------- + * DohWrite() + * ----------------------------------------------------------------------------- */ + +int DohWrite(DOH *obj, void *buffer, int length) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo; + if (DohCheck(obj)) { + objinfo = b->type; + if ((objinfo->doh_file) && (objinfo->doh_file->doh_write)) { + return (objinfo->doh_file->doh_write) (b, buffer, length); + } + return -1; + } + /* Hmmm. Not a file. Maybe it's a real FILE */ + return fwrite(buffer, 1, length, (FILE *) b); +} + +/* ----------------------------------------------------------------------------- + * DohSeek() + * ----------------------------------------------------------------------------- */ + +int DohSeek(DOH *obj, long offset, int whence) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo; + if (DohCheck(obj)) { + objinfo = b->type; + if ((objinfo->doh_file) && (objinfo->doh_file->doh_seek)) { + return (objinfo->doh_file->doh_seek) (b, offset, whence); + } + return -1; + } + return fseek((FILE *) b, offset, whence); +} + +/* ----------------------------------------------------------------------------- + * DohTell() + * ----------------------------------------------------------------------------- */ + +long DohTell(DOH *obj) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo; + if (DohCheck(obj)) { + objinfo = b->type; + if ((objinfo->doh_file) && (objinfo->doh_file->doh_tell)) { + return (objinfo->doh_file->doh_tell) (b); + } + return -1; + } + return ftell((FILE *) b); +} + +/* ----------------------------------------------------------------------------- + * DohGetc() + * ----------------------------------------------------------------------------- */ + +int DohGetc(DOH *obj) { + static DOH *lastdoh = 0; + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo; + if (obj == lastdoh) { + objinfo = b->type; + return (objinfo->doh_file->doh_getc) (b); + } + if (DohCheck(obj)) { + objinfo = b->type; + if (objinfo->doh_file->doh_getc) { + lastdoh = obj; + return (objinfo->doh_file->doh_getc) (b); + } + return EOF; + } + return fgetc((FILE *) b); +} + +/* ----------------------------------------------------------------------------- + * DohPutc() + * ----------------------------------------------------------------------------- */ + +int DohPutc(int ch, DOH *obj) { + static DOH *lastdoh = 0; + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo; + + if (obj == lastdoh) { + objinfo = b->type; + return (objinfo->doh_file->doh_putc) (b, ch); + } + if (DohCheck(obj)) { + objinfo = b->type; + if (objinfo->doh_file->doh_putc) { + lastdoh = obj; + return (objinfo->doh_file->doh_putc) (b, ch); + } + return EOF; + } + return fputc(ch, (FILE *) b); +} + +/* ----------------------------------------------------------------------------- + * DohUngetc() + * ----------------------------------------------------------------------------- */ + +int DohUngetc(int ch, DOH *obj) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo; + if (DohCheck(obj)) { + objinfo = b->type; + if (objinfo->doh_file->doh_ungetc) { + return (objinfo->doh_file->doh_ungetc) (b, ch); + } + return EOF; + } + return ungetc(ch, (FILE *) b); +} + +/* ----------------------------------------------------------------------------- + * DohClose() + * ----------------------------------------------------------------------------- */ + +int DohClose(DOH *obj) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo; + if (DohCheck(obj)) { + objinfo = b->type; + if (objinfo->doh_file->doh_close) { + return (objinfo->doh_file->doh_close) (b); + } + return 0; + } + return fclose((FILE *) obj); +} + +/* ----------------------------------------------------------------------------- + * DohIsString() + * ----------------------------------------------------------------------------- */ + +int DohIsString(const DOH *obj) { + DohBase *b = (DohBase *) obj; + DohObjInfo *objinfo; + if (!DohCheck(b)) + return 0; + objinfo = b->type; + if (objinfo->doh_string) + return 1; + else + return 0; +} + +/* ----------------------------------------------------------------------------- + * DohReplace() + * ----------------------------------------------------------------------------- */ + +int DohReplace(DOH *src, const DOH *token, const DOH *rep, int flags) { + DohBase *b = (DohBase *) src; + DohObjInfo *objinfo; + if (!token) + return 0; + if (!rep) + rep = ""; + if (DohIsString(src)) { + objinfo = b->type; + if (objinfo->doh_string->doh_replace) { + return (objinfo->doh_string->doh_replace) (b, (DOH *) token, (DOH *) rep, flags); + } + } + return 0; +} + +/* ----------------------------------------------------------------------------- + * DohChop() + * ----------------------------------------------------------------------------- */ + +void DohChop(DOH *src) { + DohBase *b = (DohBase *) src; + DohObjInfo *objinfo; + if (DohIsString(src)) { + objinfo = b->type; + if (objinfo->doh_string->doh_chop) { + (objinfo->doh_string->doh_chop) (b); + } + } +} + +/* ----------------------------------------------------------------------------- + * DohSetFile() + * ----------------------------------------------------------------------------- */ +void DohSetfile(DOH *ho, DOH *file) { + DohBase *h = (DohBase *) ho; + DohObjInfo *objinfo; + if (!h) + return; + objinfo = h->type; + if (objinfo->doh_setfile) + (objinfo->doh_setfile) (h, file); +} + +/* ----------------------------------------------------------------------------- + * DohGetFile() + * ----------------------------------------------------------------------------- */ +DOH *DohGetfile(const DOH *ho) { + DohBase *h = (DohBase *) ho; + DohObjInfo *objinfo; + if (!h) + return 0; + objinfo = h->type; + if (objinfo->doh_getfile) + return (objinfo->doh_getfile) (h); + return 0; +} + +/* ----------------------------------------------------------------------------- + * DohSetLine() + * ----------------------------------------------------------------------------- */ +void DohSetline(DOH *ho, int l) { + DohBase *h = (DohBase *) ho; + DohObjInfo *objinfo; + if (!h) + return; + objinfo = h->type; + if (objinfo->doh_setline) + (objinfo->doh_setline) (h, l); +} + +/* ----------------------------------------------------------------------------- + * DohGetLine() + * ----------------------------------------------------------------------------- */ +int DohGetline(const DOH *ho) { + DohBase *h = (DohBase *) ho; + DohObjInfo *objinfo; + if (!h) + return 0; + objinfo = h->type; + if (objinfo->doh_getline) + return (objinfo->doh_getline) (h); + return 0; +} + +/* ----------------------------------------------------------------------------- + * DohGetmeta() + * ----------------------------------------------------------------------------- */ + +DOH *DohGetmeta(DOH *ho, const DOH *name) { + DohBase *h = (DohBase *) ho; + if (!DohCheck(ho)) + return 0; + if (!h->meta) + return 0; + return DohGetattr(h->meta, name); +} + +/* ----------------------------------------------------------------------------- + * DohGetmeta() + * ----------------------------------------------------------------------------- */ + +int DohSetmeta(DOH *ho, const DOH *name, const DOH *value) { + DohBase *h = (DohBase *) ho; + if (!DohCheck(ho)) + return 0; + if (!h->meta) + h->meta = NewHash(); + return DohSetattr(h->meta, name, value); +} + +/* ----------------------------------------------------------------------------- + * DohDelmeta() + * ----------------------------------------------------------------------------- */ + +int DohDelmeta(DOH *ho, const DOH *name) { + DohBase *h = (DohBase *) ho; + if (!DohCheck(ho)) + return 0; + if (!h->meta) + return 0; + return DohDelattr(h->meta, name); +} + +/* ----------------------------------------------------------------------------- + * DohSetmark() + * ----------------------------------------------------------------------------- */ + +void DohSetmark(DOH *ho, int x) { + DohBase *h = (DohBase *) ho; + h->flag_usermark = x; +} + +int DohGetmark(DOH *ho) { + DohBase *h = (DohBase *) ho; + return h->flag_usermark; +} + +/* ----------------------------------------------------------------------------- + * DohCall() + * + * Invokes a function via DOH. A Function is represented by a hash table with + * the following attributes: + * + * "builtin" - Pointer to built-in function (if any) + * + * (Additional attributes may be added later) + * + * Returns a DOH object with result on success. Returns NULL on error + * ----------------------------------------------------------------------------- */ + +DOH *DohCall(DOH *func, DOH *args) { + DOH *result; + DOH *(*builtin) (DOH *); + + builtin = (DOH *(*)(DOH *)) GetVoid(func, "builtin"); + if (!builtin) + return 0; + result = (*builtin) (args); + return result; +} diff --git a/Source/DOH/doh.h b/Source/DOH/doh.h new file mode 100644 index 0000000..b731e95 --- /dev/null +++ b/Source/DOH/doh.h @@ -0,0 +1,442 @@ +/* ----------------------------------------------------------------------------- + * doh.h + * + * This file describes of the externally visible functions in DOH. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * + * $Id: doh.h 11097 2009-01-30 10:27:37Z bhy $ + * ----------------------------------------------------------------------------- */ + +#ifndef _DOH_H +#define _DOH_H + +#ifndef MACSWIG +#include "swigconfig.h" +#endif + +#include <stdio.h> +#include <stdarg.h> + +/* Set the namespace prefix for DOH API functions. This can be used to control + visibility of the functions in libraries */ + +/* Set this macro if you want to change DOH linkage. You would do this if you + wanted to hide DOH in a library using a different set of names. Note: simply + change "Doh" to a new name. */ + +/* +#define DOH_NAMESPACE(x) Doh ## x +*/ + +#ifdef DOH_NAMESPACE + +/* Namespace control. These macros define all of the public API names in DOH */ + +#define DohCheck DOH_NAMESPACE(Check) +#define DohIntern DOH_NAMESPACE(Intern) +#define DohDelete DOH_NAMESPACE(Delete) +#define DohCopy DOH_NAMESPACE(Copy) +#define DohClear DOH_NAMESPACE(Clear) +#define DohStr DOH_NAMESPACE(Str) +#define DohData DOH_NAMESPACE(Data) +#define DohDump DOH_NAMESPACE(Dump) +#define DohLen DOH_NAMESPACE(Len) +#define DohHashval DOH_NAMESPACE(Hashval) +#define DohCmp DOH_NAMESPACE(Cmp) +#define DohEqual DOH_NAMESPACE(Equal) +#define DohIncref DOH_NAMESPACE(Incref) +#define DohCheckattr DOH_NAMESPACE(Checkattr) +#define DohSetattr DOH_NAMESPACE(Setattr) +#define DohDelattr DOH_NAMESPACE(Delattr) +#define DohKeys DOH_NAMESPACE(Keys) +#define DohGetInt DOH_NAMESPACE(GetInt) +#define DohGetDouble DOH_NAMESPACE(GetDouble) +#define DohGetChar DOH_NAMESPACE(GetChar) +#define DohSetChar DOH_NAMESPACE(SetChar) +#define DohSetInt DOH_NAMESPACE(SetInt) +#define DohSetDouble DOH_NAMESPACE(SetDouble) +#define DohSetVoid DOH_NAMESPACE(SetVoid) +#define DohGetVoid DOH_NAMESPACE(GetVoid) +#define DohGetitem DOH_NAMESPACE(Getitem) +#define DohSetitem DOH_NAMESPACE(Setitem) +#define DohDelitem DOH_NAMESPACE(Delitem) +#define DohInsertitem DOH_NAMESPACE(Insertitem) +#define DohDelslice DOH_NAMESPACE(Delslice) +#define DohWrite DOH_NAMESPACE(Write) +#define DohRead DOH_NAMESPACE(Read) +#define DohSeek DOH_NAMESPACE(Seek) +#define DohTell DOH_NAMESPACE(Tell) +#define DohGetc DOH_NAMESPACE(Getc) +#define DohPutc DOH_NAMESPACE(Putc) +#define DohUngetc DOH_NAMESPACE(Ungetc) +#define DohGetline DOH_NAMESPACE(Getline) +#define DohSetline DOH_NAMESPACE(Setline) +#define DohGetfile DOH_NAMESPACE(Getfile) +#define DohSetfile DOH_NAMESPACE(Setfile) +#define DohReplace DOH_NAMESPACE(Replace) +#define DohChop DOH_NAMESPACE(Chop) +#define DohGetmeta DOH_NAMESPACE(Getmeta) +#define DohSetmeta DOH_NAMESPACE(Setmeta) +#define DohDelmeta DOH_NAMESPACE(Delmeta) +#define DohEncoding DOH_NAMESPACE(Encoding) +#define DohPrintf DOH_NAMESPACE(Printf) +#define DohvPrintf DOH_NAMESPACE(vPrintf) +#define DohPrintv DOH_NAMESPACE(Printv) +#define DohReadline DOH_NAMESPACE(Readline) +#define DohIsMapping DOH_NAMESPACE(IsMapping) +#define DohIsSequence DOH_NAMESPACE(IsSequence) +#define DohIsString DOH_NAMESPACE(IsString) +#define DohIsFile DOH_NAMESPACE(IsFile) +#define DohNewString DOH_NAMESPACE(NewString) +#define DohNewStringEmpty DOH_NAMESPACE(NewStringEmpty) +#define DohNewStringWithSize DOH_NAMESPACE(NewStringWithSize) +#define DohNewStringf DOH_NAMESPACE(NewStringf) +#define DohStrcmp DOH_NAMESPACE(Strcmp) +#define DohStrncmp DOH_NAMESPACE(Strncmp) +#define DohStrstr DOH_NAMESPACE(Strstr) +#define DohStrchr DOH_NAMESPACE(Strchr) +#define DohNewFile DOH_NAMESPACE(NewFile) +#define DohNewFileFromFile DOH_NAMESPACE(NewFileFromFile) +#define DohNewFileFromFd DOH_NAMESPACE(NewFileFromFd) +#define DohFileErrorDisplay DOH_NAMESPACE(FileErrorDisplay) +#define DohClose DOH_NAMESPACE(Close) +#define DohCopyto DOH_NAMESPACE(Copyto) +#define DohNewList DOH_NAMESPACE(NewList) +#define DohNewHash DOH_NAMESPACE(NewHash) +#define DohNewVoid DOH_NAMESPACE(NewVoid) +#define DohSplit DOH_NAMESPACE(Split) +#define DohSplitLines DOH_NAMESPACE(SplitLines) +#define DohNone DOH_NAMESPACE(None) +#define DohCall DOH_NAMESPACE(Call) +#define DohObjMalloc DOH_NAMESPACE(ObjMalloc) +#define DohObjFree DOH_NAMESPACE(ObjFree) +#define DohMemoryDebug DOH_NAMESPACE(MemoryDebug) +#define DohStringType DOH_NAMESPACE(StringType) +#define DohListType DOH_NAMESPACE(ListType) +#define DohHashType DOH_NAMESPACE(HashType) +#define DohFileType DOH_NAMESPACE(FileType) +#define DohVoidType DOH_NAMESPACE(VoidType) +#define DohIterator DOH_NAMESPACE(Iterator) +#define DohFirst DOH_NAMESPACE(First) +#define DohNext DOH_NAMESPACE(Next) +#endif + +#define DOH_MAJOR_VERSION 0 +#define DOH_MINOR_VERSION 1 + +typedef void DOH; + +/* + * With dynamic typing, all DOH objects are technically of type 'void *'. + * However, to clarify the reading of source code, the following symbolic + * names are used. + */ + +#define DOHString DOH +#define DOHList DOH +#define DOHHash DOH +#define DOHFile DOH +#define DOHVoid DOH +#define DOHString_or_char DOH +#define DOHObj_or_char DOH + +typedef const DOHString_or_char * const_String_or_char_ptr; +typedef const DOHString_or_char * DOHconst_String_or_char_ptr; + +#define DOH_BEGIN -1 +#define DOH_END -2 +#define DOH_CUR -3 +#define DOH_CURRENT -3 + +/* Iterator objects */ + +typedef struct { + void *key; /* Current key (if any) */ + void *item; /* Current item */ + void *object; /* Object being iterated over */ + void *_current; /* Internal use */ + int _index; /* Internal use */ +} DohIterator; + +/* Memory management */ + +#ifndef DohMalloc +#define DohMalloc malloc +#endif +#ifndef DohRealloc +#define DohRealloc realloc +#endif +#ifndef DohFree +#define DohFree free +#endif + +extern int DohCheck(const DOH *ptr); /* Check if a DOH object */ +extern void DohIntern(DOH *); /* Intern an object */ + +/* Basic object methods. Common to most objects */ + +extern void DohDelete(DOH *obj); /* Delete an object */ +extern DOH *DohCopy(const DOH *obj); +extern void DohClear(DOH *obj); +extern DOHString *DohStr(const DOH *obj); +extern void *DohData(const DOH *obj); +extern int DohDump(const DOH *obj, DOHFile * out); +extern int DohLen(const DOH *obj); +extern int DohHashval(const DOH *obj); +extern int DohCmp(const DOH *obj1, const DOH *obj2); +extern int DohEqual(const DOH *obj1, const DOH *obj2); +extern void DohIncref(DOH *obj); + +/* Mapping methods */ + +extern DOH *DohGetattr(DOH *obj, const DOHString_or_char *name); +extern int DohSetattr(DOH *obj, const DOHString_or_char *name, const DOHObj_or_char * value); +extern int DohDelattr(DOH *obj, const DOHString_or_char *name); +extern int DohCheckattr(DOH *obj, const DOHString_or_char *name, const DOHString_or_char *value); +extern DOH *DohKeys(DOH *obj); +extern int DohGetInt(DOH *obj, const DOHString_or_char *name); +extern void DohSetInt(DOH *obj, const DOHString_or_char *name, int); +extern double DohGetDouble(DOH *obj, const DOHString_or_char *name); +extern void DohSetDouble(DOH *obj, const DOHString_or_char *name, double); +extern char *DohGetChar(DOH *obj, const DOHString_or_char *name); +extern void DohSetChar(DOH *obj, const DOH *name, char *value); +extern void *DohGetFlagAttr(DOH *obj, const DOHString_or_char *name); +extern int DohGetFlag(DOH *obj, const DOHString_or_char *name); +extern void DohSetFlagAttr(DOH *obj, const DOHString_or_char *name, const DOHString_or_char *attr); +extern void DohSetFlag(DOH *obj, const DOHString_or_char *name); +extern void *DohGetVoid(DOH *obj, const DOHString_or_char *name); +extern void DohSetVoid(DOH *obj, const DOHString_or_char *name, void *value); + +/* Sequence methods */ + +extern DOH *DohGetitem(DOH *obj, int index); +extern int DohSetitem(DOH *obj, int index, const DOHObj_or_char * value); +extern int DohDelitem(DOH *obj, int index); +extern int DohInsertitem(DOH *obj, int index, const DOHObj_or_char * value); +extern int DohDelslice(DOH *obj, int sindex, int eindex); + +/* File methods */ + +extern int DohWrite(DOHFile * obj, void *buffer, int length); +extern int DohRead(DOHFile * obj, void *buffer, int length); +extern int DohSeek(DOHFile * obj, long offset, int whence); +extern long DohTell(DOHFile * obj); +extern int DohGetc(DOHFile * obj); +extern int DohPutc(int ch, DOHFile * obj); +extern int DohUngetc(int ch, DOHFile * obj); + + + +/* Iterators */ +extern DohIterator DohFirst(DOH *obj); +extern DohIterator DohNext(DohIterator x); + +/* Positional */ + +extern int DohGetline(const DOH *obj); +extern void DohSetline(DOH *obj, int line); +extern DOH *DohGetfile(const DOH *obj); +extern void DohSetfile(DOH *obj, DOH *file); + + /* String Methods */ + +extern int DohReplace(DOHString * src, const DOHString_or_char *token, const DOHString_or_char *rep, int flags); +extern void DohChop(DOHString * src); + +/* Meta-variables */ +extern DOH *DohGetmeta(DOH *, const DOH *); +extern int DohSetmeta(DOH *, const DOH *, const DOH *value); +extern int DohDelmeta(DOH *, const DOH *); + + /* Utility functions */ + +extern void DohEncoding(char *name, DOH *(*fn) (DOH *s)); +extern int DohPrintf(DOHFile * obj, const char *format, ...); +extern int DohvPrintf(DOHFile * obj, const char *format, va_list ap); +extern int DohPrintv(DOHFile * obj, ...); +extern DOH *DohReadline(DOHFile * in); + + /* Miscellaneous */ + +extern int DohIsMapping(const DOH *obj); +extern int DohIsSequence(const DOH *obj); +extern int DohIsString(const DOH *obj); +extern int DohIsFile(const DOH *obj); + +extern void DohSetmark(DOH *obj, int x); +extern int DohGetmark(DOH *obj); + +/* ----------------------------------------------------------------------------- + * Strings. + * ----------------------------------------------------------------------------- */ + +extern DOHString *DohNewStringEmpty(void); +extern DOHString *DohNewString(const DOH *c); +extern DOHString *DohNewStringWithSize(const DOH *c, int len); +extern DOHString *DohNewStringf(const DOH *fmt, ...); + +extern int DohStrcmp(const DOHString_or_char *s1, const DOHString_or_char *s2); +extern int DohStrncmp(const DOHString_or_char *s1, const DOHString_or_char *s2, int n); +extern char *DohStrstr(const DOHString_or_char *s1, const DOHString_or_char *s2); +extern char *DohStrchr(const DOHString_or_char *s1, int ch); + +/* String replacement flags */ + +#define DOH_REPLACE_ANY 0x01 +#define DOH_REPLACE_NOQUOTE 0x02 +#define DOH_REPLACE_ID 0x04 +#define DOH_REPLACE_FIRST 0x08 +#define DOH_REPLACE_ID_BEGIN 0x10 +#define DOH_REPLACE_ID_END 0x20 + +#define Replaceall(s,t,r) DohReplace(s,t,r,DOH_REPLACE_ANY) +#define Replaceid(s,t,r) DohReplace(s,t,r,DOH_REPLACE_ID) + +/* ----------------------------------------------------------------------------- + * Files + * ----------------------------------------------------------------------------- */ + +extern DOHFile *DohNewFile(DOH *filename, const char *mode, DOHList *outfiles); +extern DOHFile *DohNewFileFromFile(FILE *f); +extern DOHFile *DohNewFileFromFd(int fd); +extern void DohFileErrorDisplay(DOHString * filename); +extern int DohClose(DOH *file); +extern int DohCopyto(DOHFile * input, DOHFile * output); + + +/* ----------------------------------------------------------------------------- + * List + * ----------------------------------------------------------------------------- */ + +extern DOHList *DohNewList(void); +extern void DohSortList(DOH *lo, int (*cmp) (const DOH *, const DOH *)); + +/* ----------------------------------------------------------------------------- + * Hash + * ----------------------------------------------------------------------------- */ + +extern DOHHash *DohNewHash(void); + +/* ----------------------------------------------------------------------------- + * Void + * ----------------------------------------------------------------------------- */ + +extern DOHVoid *DohNewVoid(void *ptr, void (*del) (void *)); +extern DOHList *DohSplit(DOHFile * input, char ch, int nsplits); +extern DOHList *DohSplitLines(DOHFile * input); +extern DOH *DohNone; + +extern void DohMemoryDebug(void); + +#ifndef DOH_LONG_NAMES +/* Macros to invoke the above functions. Includes the location of + the caller to simplify debugging if something goes wrong */ + +#define Delete DohDelete +#define Copy DohCopy +#define Clear DohClear +#define Str DohStr +#define Dump DohDump +#define Getattr DohGetattr +#define Setattr DohSetattr +#define Delattr DohDelattr +#define Checkattr DohCheckattr +#define Hashval DohHashval +#define Getitem DohGetitem +#define Setitem DohSetitem +#define Delitem DohDelitem +#define Insert DohInsertitem +#define Delslice DohDelslice +#define Append(s,x) DohInsertitem(s,DOH_END,x) +#define Push(s,x) DohInsertitem(s,DOH_BEGIN,x) +#define Len DohLen +#define Data DohData +#define Char (char *) Data +#define Cmp DohCmp +#define Equal DohEqual +#define Setline DohSetline +#define Getline DohGetline +#define Setfile DohSetfile +#define Getfile DohGetfile +#define Write DohWrite +#define Read DohRead +#define Seek DohSeek +#define Tell DohTell +#define Printf DohPrintf +#define Printv DohPrintv +#define Getc DohGetc +#define Putc DohPutc +#define Ungetc DohUngetc + +/* #define StringPutc DohStringPutc */ +/* #define StringGetc DohStringGetc */ +/* #define StringUngetc DohStringUngetc */ +/* #define StringAppend Append */ +/* #define StringLen DohStringLen */ +/* #define StringChar DohStringChar */ +/* #define StringEqual DohStringEqual */ + +#define Close DohClose +#define vPrintf DohvPrintf +#define GetInt DohGetInt +#define GetDouble DohGetDouble +#define GetChar DohGetChar +#define GetVoid DohGetVoid +#define GetFlagAttr DohGetFlagAttr +#define GetFlag DohGetFlag +#define SetInt DohSetInt +#define SetDouble DohSetDouble +#define SetChar DohSetattr +#define SetVoid DohSetVoid +#define SetFlagAttr DohSetFlagAttr +#define SetFlag DohSetFlag +#define UnsetFlag(o,n) DohSetFlagAttr(o,n,NULL) +#define ClearFlag(o,n) DohSetFlagAttr(o,n,"") +#define Readline DohReadline +#define Replace DohReplace +#define Chop DohChop +#define Getmeta DohGetmeta +#define Setmeta DohSetmeta +#define Delmeta DohDelmeta +#define NewString DohNewString +#define NewStringEmpty DohNewStringEmpty +#define NewStringWithSize DohNewStringWithSize +#define NewStringf DohNewStringf +#define NewHash DohNewHash +#define NewList DohNewList +#define NewFile DohNewFile +#define NewFileFromFile DohNewFileFromFile +#define NewFileFromFd DohNewFileFromFd +#define FileErrorDisplay DohFileErrorDisplay +#define Close DohClose +#define NewVoid DohNewVoid +#define Keys DohKeys +#define Strcmp DohStrcmp +#define Strncmp DohStrncmp +#define Strstr DohStrstr +#define Strchr DohStrchr +#define Copyto DohCopyto +#define Split DohSplit +#define SplitLines DohSplitLines +#define Setmark DohSetmark +#define Getmark DohGetmark +#define None DohNone +#define Call DohCall +#define First DohFirst +#define Next DohNext +#define Iterator DohIterator +#define SortList DohSortList +#endif + +#ifdef NIL +#undef NIL +#endif + +#define NIL (char *) NULL + + +#endif /* DOH_H */ diff --git a/Source/DOH/dohint.h b/Source/DOH/dohint.h new file mode 100644 index 0000000..8f52d28 --- /dev/null +++ b/Source/DOH/dohint.h @@ -0,0 +1,133 @@ + +/* ----------------------------------------------------------------------------- + * dohint.h + * + * This file describes internally managed objects. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * + * $Id: dohint.h 9607 2006-12-05 22:11:40Z beazley $ + * ----------------------------------------------------------------------------- */ + +#ifndef _DOHINT_H +#define _DOHINT_H + +#include "doh.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include <ctype.h> +#include <stdarg.h> + +/* Hash objects */ +typedef struct { + DOH *(*doh_getattr) (DOH *obj, DOH *name); /* Get attribute */ + int (*doh_setattr) (DOH *obj, DOH *name, DOH *value); /* Set attribute */ + int (*doh_delattr) (DOH *obj, DOH *name); /* Del attribute */ + DOH *(*doh_keys) (DOH *obj); /* All keys as a list */ +} DohHashMethods; + +/* List objects */ +typedef struct { + DOH *(*doh_getitem) (DOH *obj, int index); /* Get item */ + int (*doh_setitem) (DOH *obj, int index, DOH *value); /* Set item */ + int (*doh_delitem) (DOH *obj, int index); /* Delete item */ + int (*doh_insitem) (DOH *obj, int index, DOH *value); /* Insert item */ + int (*doh_delslice) (DOH *obj, int sindex, int eindex); /* Delete slice */ +} DohListMethods; + +/* File methods */ +typedef struct { + int (*doh_read) (DOH *obj, void *buffer, int nbytes); /* Read bytes */ + int (*doh_write) (DOH *obj, void *buffer, int nbytes); /* Write bytes */ + int (*doh_putc) (DOH *obj, int ch); /* Put character */ + int (*doh_getc) (DOH *obj); /* Get character */ + int (*doh_ungetc) (DOH *obj, int ch); /* Unget character */ + int (*doh_seek) (DOH *obj, long offset, int whence); /* Seek */ + long (*doh_tell) (DOH *obj); /* Tell */ + int (*doh_close) (DOH *obj); /* Close */ +} DohFileMethods; + +/* String methods */ +typedef struct { + int (*doh_replace) (DOH *obj, DOH *old, DOH *rep, int flags); + void (*doh_chop) (DOH *obj); +} DohStringMethods; + +/* ----------------------------------------------------------------------------- + * DohObjInfo + * ----------------------------------------------------------------------------- */ + +typedef struct DohObjInfo { + char *objname; /* Object name */ + + /* Basic object methods */ + void (*doh_del) (DOH *obj); /* Delete object */ + DOH *(*doh_copy) (DOH *obj); /* Copy and object */ + void (*doh_clear) (DOH *obj); /* Clear an object */ + + /* I/O methods */ + DOH *(*doh_str) (DOH *obj); /* Make a full string */ + void *(*doh_data) (DOH *obj); /* Return raw data */ + int (*doh_dump) (DOH *obj, DOH *out); /* Serialize on out */ + + /* Length and hash values */ + int (*doh_len) (DOH *obj); + int (*doh_hashval) (DOH *obj); + + /* Compare */ + int (*doh_cmp) (DOH *obj1, DOH *obj2); + + /* Equal */ + int (*doh_equal) (DOH *obj1, DOH *obj2); + + /* Iterators */ + DohIterator (*doh_first) (DOH *obj); + DohIterator (*doh_next) (DohIterator); + + /* Positional */ + void (*doh_setfile) (DOH *obj, DOHString_or_char *file); + DOH *(*doh_getfile) (DOH *obj); + void (*doh_setline) (DOH *obj, int line); + int (*doh_getline) (DOH *obj); + + DohHashMethods *doh_hash; /* Hash methods */ + DohListMethods *doh_list; /* List methods */ + DohFileMethods *doh_file; /* File methods */ + DohStringMethods *doh_string; /* String methods */ + void *doh_reserved; /* Reserved */ + void *clientdata; /* User data */ +} DohObjInfo; + +typedef struct { + void *data; /* Data pointer */ + DohObjInfo *type; + void *meta; /* Meta data */ + unsigned int flag_intern:1; /* Interned object */ + unsigned int flag_marked:1; /* Mark flag. Used to avoid recursive loops in places */ + unsigned int flag_user:1; /* User flag */ + unsigned int flag_usermark:1; /* User marked */ + unsigned int refcount:28; /* Reference count (max 16 million) */ +} 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 Refcount(a) ((DohBase *) a)->refcount + +/* Macros for manipulating objects in a safe manner */ +#define ObjData(a) ((DohBase *)a)->data +#define ObjSetMark(a,x) ((DohBase *)a)->flag_marked = x +#define ObjGetMark(a) ((DohBase *)a)->flag_marked +#define ObjType(a) ((DohBase *)a)->type + +extern DOH *DohObjMalloc(DohObjInfo *type, void *data); /* Allocate a DOH object */ +extern void DohObjFree(DOH *ptr); /* Free a DOH object */ + +#endif /* DOHINT_H */ diff --git a/Source/DOH/file.c b/Source/DOH/file.c new file mode 100644 index 0000000..2384850 --- /dev/null +++ b/Source/DOH/file.c @@ -0,0 +1,299 @@ +/* ----------------------------------------------------------------------------- + * file.c + * + * This file implements a file-like object that can be built around an + * ordinary FILE * or integer file descriptor. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_file_c[] = "$Id: file.c 10898 2008-11-03 12:51:45Z wsfulton $"; + +#include "dohint.h" + +#ifdef DOH_INTFILE +#include <unistd.h> +#endif +#include <errno.h> + +typedef struct { + FILE *filep; + int fd; + int closeondel; +} DohFile; + +/* ----------------------------------------------------------------------------- + * DelFile() + * ----------------------------------------------------------------------------- */ + +static void DelFile(DOH *fo) { + DohFile *f = (DohFile *) ObjData(fo); + if (f->closeondel) { + if (f->filep) { + fclose(f->filep); + } +#ifdef DOH_INTFILE + if (f->fd) { + close(f->fd); + } +#endif + } + DohFree(f); +} + +/* ----------------------------------------------------------------------------- + * File_read() + * ----------------------------------------------------------------------------- */ + +static int File_read(DOH *fo, void *buffer, int len) { + DohFile *f = (DohFile *) ObjData(fo); + + if (f->filep) { + return fread(buffer, 1, len, f->filep); + } else if (f->fd) { +#ifdef DOH_INTFILE + return read(f->fd, buffer, len); +#endif + } + return -1; +} + +/* ----------------------------------------------------------------------------- + * File_write() + * ----------------------------------------------------------------------------- */ + +static int File_write(DOH *fo, void *buffer, int len) { + DohFile *f = (DohFile *) ObjData(fo); + if (f->filep) { + int ret = (int) fwrite(buffer, 1, len, f->filep); + int err = (ret != len) ? ferror(f->filep) : 0; + return err ? -1 : ret; + } else if (f->fd) { +#ifdef DOH_INTFILE + return write(f->fd, buffer, len); +#endif + } + return -1; +} + +/* ----------------------------------------------------------------------------- + * File_seek() + * ----------------------------------------------------------------------------- */ + +static int File_seek(DOH *fo, long offset, int whence) { + DohFile *f = (DohFile *) ObjData(fo); + if (f->filep) { + return fseek(f->filep, offset, whence); + } else if (f->fd) { +#ifdef DOH_INTFILE + return lseek(f->fd, offset, whence); +#endif + } + return -1; +} + +/* ----------------------------------------------------------------------------- + * File_tell() + * ----------------------------------------------------------------------------- */ + +static long File_tell(DOH *fo) { + DohFile *f = (DohFile *) ObjData(fo); + if (f->filep) { + return ftell(f->filep); + } else if (f->fd) { +#ifdef DOH_INTFILE + return lseek(f->fd, 0, SEEK_CUR); +#endif + } + return -1; +} + +/* ----------------------------------------------------------------------------- + * File_putc() + * ----------------------------------------------------------------------------- */ + +static int File_putc(DOH *fo, int ch) { + DohFile *f = (DohFile *) ObjData(fo); + if (f->filep) { + return fputc(ch, f->filep); + } else if (f->fd) { +#ifdef DOH_INTFILE + char c; + c = (char) ch; + return write(f->fd, &c, 1); +#endif + } + return -1; +} + +/* ----------------------------------------------------------------------------- + * File_getc() + * ----------------------------------------------------------------------------- */ + +static int File_getc(DOH *fo) { + DohFile *f = (DohFile *) ObjData(fo); + if (f->filep) { + return fgetc(f->filep); + } else if (f->fd) { +#ifdef DOH_INTFILE + unsigned char c; + if (read(f->fd, &c, 1) < 0) + return EOF; + return c; +#endif + } + return EOF; +} + +/* ----------------------------------------------------------------------------- + * File_ungetc() + * + * Put a character back onto the input + * ----------------------------------------------------------------------------- */ + +static int File_ungetc(DOH *fo, int ch) { + DohFile *f = (DohFile *) ObjData(fo); + if (f->filep) { + return ungetc(ch, f->filep); + } else if (f->fd) { +#ifdef DOH_INTFILE + /* Not implemented yet */ +#endif + } + return -1; +} + +/* ----------------------------------------------------------------------------- + * File_close() + * + * Close the file + * ----------------------------------------------------------------------------- */ + +static int File_close(DOH *fo) { + int ret = 0; + DohFile *f = (DohFile *) ObjData(fo); + if (f->filep) { + ret = fclose(f->filep); + f->filep = 0; + } else if (f->fd) { +#ifdef DOH_INTFILE + ret = close(f->fd); + f->fd = 0; +#endif + } + return ret; +} + +static DohFileMethods FileFileMethods = { + File_read, + File_write, + File_putc, + File_getc, + File_ungetc, + File_seek, + File_tell, + File_close, /* close */ +}; + +static DohObjInfo DohFileType = { + "DohFile", /* objname */ + DelFile, /* doh_del */ + 0, /* doh_copy */ + 0, /* doh_clear */ + 0, /* doh_str */ + 0, /* doh_data */ + 0, /* doh_dump */ + 0, /* doh_len */ + 0, /* doh_hash */ + 0, /* doh_cmp */ + 0, /* doh_equal */ + 0, /* doh_first */ + 0, /* doh_next */ + 0, /* doh_setfile */ + 0, /* doh_getfile */ + 0, /* doh_setline */ + 0, /* doh_getline */ + 0, /* doh_mapping */ + 0, /* doh_sequence */ + &FileFileMethods, /* doh_file */ + 0, /* doh_string */ + 0, /* doh_callable */ + 0, /* doh_position */ +}; + +/* ----------------------------------------------------------------------------- + * NewFile() + * + * Create a new file from a given filename and mode. + * If newfiles is non-zero, the filename is added to the list of new files. + * ----------------------------------------------------------------------------- */ + +DOH *DohNewFile(DOH *filename, const char *mode, DOHList *newfiles) { + DohFile *f; + FILE *file; + char *filen; + + filen = Char(filename); + file = fopen(filen, mode); + if (!file) + return 0; + + f = (DohFile *) DohMalloc(sizeof(DohFile)); + if (!f) { + fclose(file); + return 0; + } + if (newfiles) + Append(newfiles, filename); + f->filep = file; + f->fd = 0; + f->closeondel = 1; + return DohObjMalloc(&DohFileType, f); +} + +/* ----------------------------------------------------------------------------- + * NewFileFromFile() + * + * Create a file object from an already open FILE *. + * ----------------------------------------------------------------------------- */ + +DOH *DohNewFileFromFile(FILE *file) { + DohFile *f; + f = (DohFile *) DohMalloc(sizeof(DohFile)); + if (!f) + return 0; + f->filep = file; + f->fd = 0; + f->closeondel = 0; + return DohObjMalloc(&DohFileType, f); +} + +/* ----------------------------------------------------------------------------- + * NewFileFromFd() + * + * Create a file object from an already open FILE *. + * ----------------------------------------------------------------------------- */ + +DOH *DohNewFileFromFd(int fd) { + DohFile *f; + f = (DohFile *) DohMalloc(sizeof(DohFile)); + if (!f) + return 0; + f->filep = 0; + f->fd = fd; + f->closeondel = 0; + return DohObjMalloc(&DohFileType, f); +} + +/* ----------------------------------------------------------------------------- + * FileErrorDisplay() + * + * Display cause of one of the NewFile functions failing. + * ----------------------------------------------------------------------------- */ + +void DohFileErrorDisplay(DOHString * filename) { + Printf(stderr, "Unable to open file %s: %s\n", filename, strerror(errno)); +} diff --git a/Source/DOH/fio.c b/Source/DOH/fio.c new file mode 100644 index 0000000..7f3eb8b --- /dev/null +++ b/Source/DOH/fio.c @@ -0,0 +1,589 @@ +/* ----------------------------------------------------------------------------- + * fio.c + * + * This file implements a number of standard I/O operations included + * formatted output, readline, and splitting. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_fio_c[] = "$Id: fio.c 9607 2006-12-05 22:11:40Z beazley $"; + +#include "dohint.h" + +#define OBUFLEN 512 + +static DOH *encodings = 0; /* Encoding hash */ + +/* ----------------------------------------------------------------------------- + * Writen() + * + * Write's N characters of output and retries until all characters are + * written. This is useful should a write operation encounter a spurious signal. + * ----------------------------------------------------------------------------- */ + +static int Writen(DOH *out, void *buffer, int len) { + int nw = len, ret; + char *cb = (char *) buffer; + while (nw) { + ret = Write(out, cb, nw); + if (ret < 0) + return -1; + nw = nw - ret; + cb += ret; + } + return len; +} + +/* ----------------------------------------------------------------------------- + * DohEncoding() + * + * Registers a new printf encoding method. An encoder function should accept + * two file-like objects and operate as a filter. + * ----------------------------------------------------------------------------- */ + +void DohEncoding(char *name, DOH *(*fn) (DOH *s)) { + if (!encodings) + encodings = NewHash(); + Setattr(encodings, (void *) name, NewVoid((void *) fn, 0)); +} + +/* internal function for processing an encoding */ +static DOH *encode(char *name, DOH *s) { + DOH *handle, *ns; + DOH *(*fn) (DOH *); + long pos; + char *cfmt = strchr(name, ':'); + DOH *tmp = 0; + if (cfmt) { + tmp = NewString(cfmt + 1); + Append(tmp, s); + Setfile(tmp, Getfile((DOH *) s)); + Setline(tmp, Getline((DOH *) s)); + *cfmt = '\0'; + } + if (!encodings || !(handle = Getattr(encodings, name))) { + return Copy(s); + } + if (tmp) + s = tmp; + pos = Tell(s); + Seek(s, 0, SEEK_SET); + fn = (DOH *(*)(DOH *)) Data(handle); + ns = (*fn) (s); + Seek(s, pos, SEEK_SET); + if (tmp) + Delete(tmp); + return ns; +} + +/* ----------------------------------------------------------------------------- + * DohvPrintf() + * + * DOH implementation of printf. Output can be directed to any file-like object + * including bare FILE * objects. The same formatting codes as printf are + * recognized with two extensions: + * + * %s - Prints a "char *" or the string representation of any + * DOH object. This will implicitly result in a call to + * Str(obj). + * + * %(encoder)* - Filters the output through an encoding function registered + * with DohEncoder(). + * + * Note: This function is not particularly memory efficient with large strings. + * It's better to use Dump() or some other method instead. + * ----------------------------------------------------------------------------- */ + +int DohvPrintf(DOH *so, const char *format, va_list ap) { + static char *fmt_codes = "dioxXucsSfeEgGpn"; + int state = 0; + const char *p = format; + char newformat[256]; + char obuffer[OBUFLEN]; + char *fmt = 0; + char temp[64]; + int widthval = 0; + int precval = 0; + int maxwidth; + char *w = 0; + int ivalue; + double dvalue; + void *pvalue; + char *stemp; + int nbytes = 0; + char encoder[128], *ec = 0; + int plevel = 0; + + memset(newformat, 0, sizeof(newformat)); + + while (*p) { + switch (state) { + case 0: /* Ordinary text */ + if (*p != '%') { + Putc(*p, so); + nbytes++; + } else { + fmt = newformat; + widthval = 0; + precval = 0; + *(fmt++) = *p; + encoder[0] = 0; + state = 10; + } + break; + case 10: /* Look for a width and precision */ + if (isdigit((int) *p) && (*p != '0')) { + w = temp; + *(w++) = *p; + *(fmt++) = *p; + state = 20; + } else if (strchr(fmt_codes, *p)) { + /* Got one of the formatting codes */ + p--; + state = 100; + } else if (*p == '*') { + /* Width field is specified in the format list */ + widthval = va_arg(ap, int); + sprintf(temp, "%d", widthval); + for (w = temp; *w; w++) { + *(fmt++) = *w; + } + state = 30; + } else if (*p == '%') { + Putc(*p, so); + fmt = newformat; + nbytes++; + state = 0; + } else if (*p == '(') { + ++plevel; + ec = encoder; + state = 60; + } else { + *(fmt++) = *p; + } + break; + + case 20: /* Hmmm. At the start of a width field */ + if (isdigit((int) *p)) { + *(w++) = *p; + *(fmt++) = *p; + } else if (strchr(fmt_codes, *p)) { + /* Got one of the formatting codes */ + /* Figure out width */ + *w = 0; + widthval = atoi(temp); + p--; + state = 100; + } else if (*p == '.') { + *w = 0; + widthval = atoi(temp); + w = temp; + *(fmt++) = *p; + state = 40; + } else { + /* ??? */ + *w = 0; + widthval = atoi(temp); + state = 50; + } + break; + + case 30: /* Parsed a width from an argument. Look for a . */ + if (*p == '.') { + w = temp; + *(fmt++) = *p; + state = 40; + } else if (strchr(fmt_codes, *p)) { + /* Got one of the formatting codes */ + /* Figure out width */ + p--; + state = 100; + } else { + /* hmmm. Something else. */ + state = 50; + } + break; + + case 40: + /* Start of precision expected */ + if (isdigit((int) *p) && (*p != '0')) { + *(fmt++) = *p; + *(w++) = *p; + state = 41; + } else if (*p == '*') { + /* Precision field is specified in the format list */ + precval = va_arg(ap, int); + sprintf(temp, "%d", precval); + for (w = temp; *w; w++) { + *(fmt++) = *w; + } + state = 50; + } else if (strchr(fmt_codes, *p)) { + p--; + state = 100; + } else { + *(fmt++) = *p; + state = 50; + } + break; + case 41: + if (isdigit((int) *p)) { + *(fmt++) = *p; + *(w++) = *p; + } else if (strchr(fmt_codes, *p)) { + /* Got one of the formatting codes */ + /* Figure out width */ + *w = 0; + precval = atoi(temp); + p--; + state = 100; + } else { + *w = 0; + precval = atoi(temp); + *(fmt++) = *p; + state = 50; + } + break; + /* Hang out, wait for format specifier */ + case 50: + if (strchr(fmt_codes, *p)) { + p--; + state = 100; + } else { + *(fmt++) = *p; + } + break; + + /* Got an encoding header */ + case 60: + if (*p == '(') { + ++plevel; + *ec = *p; + ec++; + } else if (*p == ')') { + --plevel; + if (plevel <= 0) { + *ec = 0; + state = 10; + } else { + *ec = *p; + ec++; + } + } else { + *ec = *p; + ec++; + } + break; + case 100: + /* Got a formatting code */ + if (widthval < precval) + maxwidth = precval; + else + maxwidth = widthval; + if ((*p == 's') || (*p == 'S')) { /* Null-Terminated string */ + DOH *doh; + DOH *Sval; + DOH *enc = 0; + doh = va_arg(ap, DOH *); + if (DohCheck(doh)) { + /* Is a DOH object. */ + if (DohIsString(doh)) { + Sval = doh; + } else { + Sval = Str(doh); + } + if (strlen(encoder)) { + enc = encode(encoder, Sval); + maxwidth = maxwidth + strlen(newformat) + Len(enc); + } else { + maxwidth = maxwidth + strlen(newformat) + Len(Sval); + } + *(fmt++) = 's'; + *fmt = 0; + if ((maxwidth + 1) < OBUFLEN) { + stemp = obuffer; + } else { + stemp = (char *) DohMalloc(maxwidth + 1); + } + if (enc) { + nbytes += sprintf(stemp, newformat, Data(enc)); + } else { + nbytes += sprintf(stemp, newformat, Data(Sval)); + } + if (Writen(so, stemp, strlen(stemp)) < 0) + return -1; + if ((DOH *) Sval != doh) { + Delete(Sval); + } + if (enc) + Delete(enc); + if (*p == 'S') { + Delete(doh); + } + if (stemp != obuffer) { + DohFree(stemp); + } + } else { + if (!doh) + doh = (char *) ""; + + if (strlen(encoder)) { + DOH *s = NewString(doh); + Seek(s, 0, SEEK_SET); + enc = encode(encoder, s); + Delete(s); + doh = Char(enc); + } else { + enc = 0; + } + maxwidth = maxwidth + strlen(newformat) + strlen((char *) doh); + *(fmt++) = 's'; + *fmt = 0; + if ((maxwidth + 1) < OBUFLEN) { + stemp = obuffer; + } else { + stemp = (char *) DohMalloc(maxwidth + 1); + } + nbytes += sprintf(stemp, newformat, doh); + if (Writen(so, stemp, strlen(stemp)) < 0) + return -1; + if (stemp != obuffer) { + DohFree(stemp); + } + if (enc) + Delete(enc); + } + } else { + *(fmt++) = *p; + *fmt = 0; + maxwidth = maxwidth + strlen(newformat) + 64; + + /* Only allocate a buffer if it is too big to fit. Shouldn't have to do + this very often */ + + if (maxwidth < OBUFLEN) + stemp = obuffer; + else + stemp = (char *) DohMalloc(maxwidth + 1); + switch (*p) { + case 'd': + case 'i': + case 'o': + case 'u': + case 'x': + case 'X': + case 'c': + ivalue = va_arg(ap, int); + nbytes += sprintf(stemp, newformat, ivalue); + break; + case 'f': + case 'g': + case 'e': + case 'E': + case 'G': + dvalue = va_arg(ap, double); + nbytes += sprintf(stemp, newformat, dvalue); + break; + case 'p': + pvalue = va_arg(ap, void *); + nbytes += sprintf(stemp, newformat, pvalue); + break; + default: + break; + } + if (Writen(so, stemp, strlen(stemp)) < 0) + return -1; + if (stemp != obuffer) + DohFree(stemp); + } + state = 0; + break; + } + p++; + } + if (state) { + int r; + *fmt = 0; + r = Writen(so, fmt, strlen(fmt)); + if (r < 0) + return -1; + nbytes += r; + } + return nbytes; +} + +/* ----------------------------------------------------------------------------- + * DohPrintf() + * + * Variable length argument entry point to Printf + * ----------------------------------------------------------------------------- */ + +int DohPrintf(DOH *obj, const char *format, ...) { + va_list ap; + int ret; + va_start(ap, format); + ret = DohvPrintf(obj, format, ap); + va_end(ap); + return ret; +} + +/* ----------------------------------------------------------------------------- + * DohPrintv() + * + * Print a null-terminated variable length list of DOH objects + * ----------------------------------------------------------------------------- */ + +int DohPrintv(DOHFile * f, ...) { + va_list ap; + int ret = 0; + DOH *obj; + va_start(ap, f); + while (1) { + obj = va_arg(ap, void *); + if ((!obj) || (obj == DohNone)) + break; + if (DohCheck(obj)) { + ret += DohDump(obj, f); + } else { + ret += DohWrite(f, obj, strlen((char *) obj)); + } + } + va_end(ap); + return ret; +} + +/* ----------------------------------------------------------------------------- + * DohCopyto() + * + * Copies all of the input from an input stream to an output stream. Returns the + * number of bytes copied. + * ----------------------------------------------------------------------------- */ + +int DohCopyto(DOH *in, DOH *out) { + int nbytes = 0, ret; + int nwrite = 0, wret; + char *cw; + char buffer[16384]; + + if ((!in) || (!out)) + return 0; + while (1) { + ret = Read(in, buffer, 16384); + if (ret > 0) { + nwrite = ret; + cw = buffer; + while (nwrite) { + wret = Write(out, cw, nwrite); + if (wret < 0) + return -1; + nwrite = nwrite - wret; + cw += wret; + } + nbytes += ret; + } else { + return nbytes; + } + } +} + + +/* ----------------------------------------------------------------------------- + * DohSplit() + * + * Split an input stream into a list of strings delimited by the specified + * character. Optionally accepts a maximum number of splits to perform. + * ----------------------------------------------------------------------------- */ + +DOH *DohSplit(DOH *in, char ch, int nsplits) { + DOH *list; + DOH *str; + int c; + + list = NewList(); + + if (DohIsString(in)) { + Seek(in, 0, SEEK_SET); + } + + while (1) { + str = NewStringEmpty(); + do { + c = Getc(in); + } while ((c != EOF) && (c == ch)); + if (c != EOF) { + Putc(c, str); + while (1) { + c = Getc(in); + if ((c == EOF) || ((c == ch) && (nsplits != 0))) + break; + Putc(c, str); + } + nsplits--; + } + Append(list, str); + Delete(str); + if (c == EOF) + break; + } + return list; +} + +/* ----------------------------------------------------------------------------- + * DohSplitLines() + * + * Split an input stream into a list of strings delimited by newline characters. + * ----------------------------------------------------------------------------- */ + +DOH *DohSplitLines(DOH *in) { + DOH *list; + DOH *str; + int c = 0; + + list = NewList(); + + if (DohIsString(in)) { + Seek(in, 0, SEEK_SET); + } + + while (c != EOF) { + str = NewStringEmpty(); + while ((c = Getc(in)) != '\n' && c != EOF) { + Putc(c, str); + } + Append(list, str); + Delete(str); + } + return list; +} + + +/* ----------------------------------------------------------------------------- + * DohReadline() + * + * Read a single input line and return it as a string. + * ----------------------------------------------------------------------------- */ + +DOH *DohReadline(DOH *in) { + char c; + int n = 0; + DOH *s = NewStringEmpty(); + while (1) { + if (Read(in, &c, 1) < 0) { + if (n == 0) { + Delete(s); + return 0; + } + return s; + } + if (c == '\n') + return s; + if (c == '\r') + continue; + Putc(c, s); + n++; + } +} diff --git a/Source/DOH/hash.c b/Source/DOH/hash.c new file mode 100644 index 0000000..071a6a6 --- /dev/null +++ b/Source/DOH/hash.c @@ -0,0 +1,551 @@ +/* ----------------------------------------------------------------------------- + * hash.c + * + * Implements a simple hash table object. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_hash_c[] = "$Id: hash.c 10926 2008-11-11 22:17:40Z wsfulton $"; + +#include "dohint.h" + +extern DohObjInfo DohHashType; + +/* Hash node */ +typedef struct HashNode { + DOH *key; + DOH *object; + struct HashNode *next; +} HashNode; + +/* Hash object */ +typedef struct Hash { + DOH *file; + int line; + HashNode **hashtable; + int hashsize; + int nitems; +} Hash; + +/* Key interning structure */ +typedef struct KeyValue { + char *cstr; + DOH *sstr; + struct KeyValue *left; + struct KeyValue *right; +} KeyValue; + +static KeyValue *root = 0; + +/* Find or create a key in the interned key table */ +static DOH *find_key(DOH *doh_c) { + char *c = (char *) doh_c; + KeyValue *r, *s; + int d = 0; + /* OK, sure, we use a binary tree for maintaining interned + symbols. Then we use their hash values for accessing secondary + hash tables. */ + 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; +} + +#define HASH_INIT_SIZE 7 + +/* Create a new hash node */ +static HashNode *NewNode(DOH *k, void *obj) { + HashNode *hn = (HashNode *) DohMalloc(sizeof(HashNode)); + hn->key = k; + Incref(hn->key); + hn->object = obj; + Incref(obj); + hn->next = 0; + return hn; +} + +/* Delete a hash node */ +static void DelNode(HashNode *hn) { + Delete(hn->key); + Delete(hn->object); + DohFree(hn); +} + +/* ----------------------------------------------------------------------------- + * DelHash() + * + * Delete a hash table. + * ----------------------------------------------------------------------------- */ + +static void DelHash(DOH *ho) { + Hash *h = (Hash *) ObjData(ho); + HashNode *n, *next; + int i; + + for (i = 0; i < h->hashsize; i++) { + n = h->hashtable[i]; + while (n) { + next = n->next; + DelNode(n); + n = next; + } + } + DohFree(h->hashtable); + h->hashtable = 0; + h->hashsize = 0; + DohFree(h); +} + +/* ----------------------------------------------------------------------------- + * Hash_clear() + * + * Clear all of the entries in the hash table. + * ----------------------------------------------------------------------------- */ + +static void Hash_clear(DOH *ho) { + Hash *h = (Hash *) ObjData(ho); + HashNode *n, *next; + int i; + + for (i = 0; i < h->hashsize; i++) { + n = h->hashtable[i]; + while (n) { + next = n->next; + DelNode(n); + n = next; + } + h->hashtable[i] = 0; + } + h->nitems = 0; +} + +/* resize the hash table */ +static void resize(Hash *h) { + HashNode *n, *next, **table; + int oldsize, newsize; + int i, p, hv; + + if (h->nitems < 2 * h->hashsize) + return; + + /* Too big. We have to rescale everything now */ + oldsize = h->hashsize; + + /* Calculate a new size */ + newsize = 2 * oldsize + 1; + p = 3; + while (p < (newsize >> 1)) { + if (((newsize / p) * p) == newsize) { + newsize += 2; + p = 3; + continue; + } + p = p + 2; + } + + table = (HashNode **) DohMalloc(newsize * sizeof(HashNode *)); + for (i = 0; i < newsize; i++) { + table[i] = 0; + } + + /* Walk down the old set of nodes and re-place */ + h->hashsize = newsize; + for (i = 0; i < oldsize; i++) { + n = h->hashtable[i]; + while (n) { + hv = Hashval(n->key) % newsize; + next = n->next; + n->next = table[hv]; + table[hv] = n; + n = next; + } + } + DohFree(h->hashtable); + h->hashtable = table; +} + +/* ----------------------------------------------------------------------------- + * Hash_setattr() + * + * Set an attribute in the hash table. Deletes the existing entry if it already + * exists. + * ----------------------------------------------------------------------------- */ + +static int Hash_setattr(DOH *ho, DOH *k, DOH *obj) { + int hv; + HashNode *n, *prev; + Hash *h = (Hash *) ObjData(ho); + + if (!obj) { + return DohDelattr(ho, k); + } + if (!DohCheck(k)) + k = find_key(k); + if (!DohCheck(obj)) { + obj = NewString((char *) obj); + Decref(obj); + } + hv = (Hashval(k)) % h->hashsize; + n = h->hashtable[hv]; + prev = 0; + while (n) { + if (Cmp(n->key, k) == 0) { + /* Node already exists. Just replace its contents */ + if (n->object == obj) { + /* Whoa. Same object. Do nothing */ + return 1; + } + Delete(n->object); + n->object = obj; + Incref(obj); + return 1; /* Return 1 to indicate a replacement */ + } else { + prev = n; + n = n->next; + } + } + /* Add this to the table */ + n = NewNode(k, obj); + if (prev) + prev->next = n; + else + h->hashtable[hv] = n; + h->nitems++; + resize(h); + return 0; +} + +/* ----------------------------------------------------------------------------- + * Hash_getattr() + * + * Get an attribute from the hash table. Returns 0 if it doesn't exist. + * ----------------------------------------------------------------------------- */ +typedef int (*binop) (DOH *obj1, DOH *obj2); + + +static DOH *Hash_getattr(DOH *h, DOH *k) { + DOH *obj = 0; + Hash *ho = (Hash *) ObjData(h); + DOH *ko = DohCheck(k) ? k : find_key(k); + int hv = Hashval(ko) % ho->hashsize; + DohObjInfo *k_type = ((DohBase*)ko)->type; + HashNode *n = ho->hashtable[hv]; + if (k_type->doh_equal) { + binop equal = k_type->doh_equal; + while (n) { + DohBase *nk = (DohBase *)n->key; + if ((k_type == nk->type) && equal(ko, nk)) obj = n->object; + n = n->next; + } + } else { + binop cmp = k_type->doh_cmp; + while (n) { + DohBase *nk = (DohBase *)n->key; + if ((k_type == nk->type) && (cmp(ko, nk) == 0)) obj = n->object; + n = n->next; + } + } + return obj; +} + +/* ----------------------------------------------------------------------------- + * Hash_delattr() + * + * Delete an object from the hash table. + * ----------------------------------------------------------------------------- */ + +static int Hash_delattr(DOH *ho, DOH *k) { + HashNode *n, *prev; + int hv; + Hash *h = (Hash *) ObjData(ho); + + if (!DohCheck(k)) + k = find_key(k); + hv = Hashval(k) % h->hashsize; + n = h->hashtable[hv]; + prev = 0; + while (n) { + if (Cmp(n->key, k) == 0) { + /* Found it, kill it */ + + if (prev) { + prev->next = n->next; + } else { + h->hashtable[hv] = n->next; + } + DelNode(n); + h->nitems--; + return 1; + } + prev = n; + n = n->next; + } + return 0; +} + +static DohIterator Hash_firstiter(DOH *ho) { + DohIterator iter; + Hash *h = (Hash *) ObjData(ho); + iter.object = ho; + iter._current = 0; + iter.item = 0; + iter.key = 0; + iter._index = 0; /* Index in hash table */ + while ((iter._index < h->hashsize) && !h->hashtable[iter._index]) + iter._index++; + + if (iter._index >= h->hashsize) { + return iter; + } + iter._current = h->hashtable[iter._index]; + iter.item = ((HashNode *) iter._current)->object; + iter.key = ((HashNode *) iter._current)->key; + + /* Actually save the next slot in the hash. This makes it possible to + delete the item being iterated over without trashing the universe */ + iter._current = ((HashNode *) iter._current)->next; + return iter; +} + +static DohIterator Hash_nextiter(DohIterator iter) { + Hash *h = (Hash *) ObjData(iter.object); + if (!iter._current) { + iter._index++; + while ((iter._index < h->hashsize) && !h->hashtable[iter._index]) { + iter._index++; + } + if (iter._index >= h->hashsize) { + iter.item = 0; + iter.key = 0; + iter._current = 0; + return iter; + } + iter._current = h->hashtable[iter._index]; + } + iter.key = ((HashNode *) iter._current)->key; + iter.item = ((HashNode *) iter._current)->object; + + /* Store the next node to iterator on */ + iter._current = ((HashNode *) iter._current)->next; + return iter; +} + +/* ----------------------------------------------------------------------------- + * Hash_keys(DOH *) + * + * Return a list of keys + * ----------------------------------------------------------------------------- */ + +static DOH *Hash_keys(DOH *so) { + DOH *keys; + Iterator i; + + keys = NewList(); + for (i = First(so); i.key; i = Next(i)) { + Append(keys, i.key); + } + return keys; +} + +/* ----------------------------------------------------------------------------- + * Hash_str() + * + * Create a string representation of a hash table (mainly for debugging). + * ----------------------------------------------------------------------------- */ + +static DOH *Hash_str(DOH *ho) { + int i, j; + HashNode *n; + DOH *s; + static int indent = 4; + Hash *h = (Hash *) ObjData(ho); + + s = NewStringEmpty(); + if (ObjGetMark(ho)) { + Printf(s, "Hash(0x%x)", ho); + return s; + } + ObjSetMark(ho, 1); + Printf(s, "Hash {\n"); + for (i = 0; i < h->hashsize; i++) { + n = h->hashtable[i]; + while (n) { + for (j = 0; j < indent; j++) + Putc(' ', s); + indent += 4; + Printf(s, "'%s' : %s, \n", n->key, n->object); + indent -= 4; + n = n->next; + } + } + for (j = 0; j < (indent - 4); j++) + Putc(' ', s); + Printf(s, "}\n"); + ObjSetMark(ho, 0); + return s; +} + +/* ----------------------------------------------------------------------------- + * Hash_len() + * + * Return number of entries in the hash table. + * ----------------------------------------------------------------------------- */ + +static int Hash_len(DOH *ho) { + Hash *h = (Hash *) ObjData(ho); + return h->nitems; +} + +/* ----------------------------------------------------------------------------- + * CopyHash() + * + * Make a copy of a hash table. Note: this is a shallow copy. + * ----------------------------------------------------------------------------- */ + +static DOH *CopyHash(DOH *ho) { + Hash *h, *nh; + HashNode *n; + DOH *nho; + + int i; + h = (Hash *) ObjData(ho); + nh = (Hash *) DohMalloc(sizeof(Hash)); + nh->hashsize = h->hashsize; + nh->hashtable = (HashNode **) DohMalloc(nh->hashsize * sizeof(HashNode *)); + for (i = 0; i < nh->hashsize; i++) { + nh->hashtable[i] = 0; + } + nh->nitems = 0; + nh->line = h->line; + nh->file = h->file; + if (nh->file) + Incref(nh->file); + + nho = DohObjMalloc(&DohHashType, nh); + for (i = 0; i < h->hashsize; i++) { + n = h->hashtable[i]; + while (n) { + Hash_setattr(nho, n->key, n->object); + n = n->next; + } + } + return nho; +} + + + +static void Hash_setfile(DOH *ho, DOH *file) { + DOH *fo; + Hash *h = (Hash *) ObjData(ho); + + if (!DohCheck(file)) { + fo = NewString(file); + Decref(fo); + } else + fo = file; + Incref(fo); + Delete(h->file); + h->file = fo; +} + +static DOH *Hash_getfile(DOH *ho) { + Hash *h = (Hash *) ObjData(ho); + return h->file; +} + +static void Hash_setline(DOH *ho, int line) { + Hash *h = (Hash *) ObjData(ho); + h->line = line; +} + +static int Hash_getline(DOH *ho) { + Hash *h = (Hash *) ObjData(ho); + return h->line; +} + +/* ----------------------------------------------------------------------------- + * type information + * ----------------------------------------------------------------------------- */ + +static DohHashMethods HashHashMethods = { + Hash_getattr, + Hash_setattr, + Hash_delattr, + Hash_keys, +}; + +DohObjInfo DohHashType = { + "Hash", /* objname */ + DelHash, /* doh_del */ + CopyHash, /* doh_copy */ + Hash_clear, /* doh_clear */ + Hash_str, /* doh_str */ + 0, /* doh_data */ + 0, /* doh_dump */ + Hash_len, /* doh_len */ + 0, /* doh_hash */ + 0, /* doh_cmp */ + 0, /* doh_equal */ + Hash_firstiter, /* doh_first */ + Hash_nextiter, /* doh_next */ + Hash_setfile, /* doh_setfile */ + Hash_getfile, /* doh_getfile */ + Hash_setline, /* doh_setline */ + Hash_getline, /* doh_getline */ + &HashHashMethods, /* doh_mapping */ + 0, /* doh_sequence */ + 0, /* doh_file */ + 0, /* doh_string */ + 0, /* doh_positional */ + 0, +}; + +/* ----------------------------------------------------------------------------- + * NewHash() + * + * Create a new hash table. + * ----------------------------------------------------------------------------- */ + +DOH *DohNewHash(void) { + Hash *h; + int i; + h = (Hash *) DohMalloc(sizeof(Hash)); + h->hashsize = HASH_INIT_SIZE; + h->hashtable = (HashNode **) DohMalloc(h->hashsize * sizeof(HashNode *)); + for (i = 0; i < h->hashsize; i++) { + h->hashtable[i] = 0; + } + h->nitems = 0; + h->file = 0; + h->line = 0; + return DohObjMalloc(&DohHashType, h); +} diff --git a/Source/DOH/list.c b/Source/DOH/list.c new file mode 100644 index 0000000..b7e23ad --- /dev/null +++ b/Source/DOH/list.c @@ -0,0 +1,377 @@ +/* ----------------------------------------------------------------------------- + * list.c + * + * Implements a simple list object. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_list_c[] = "$Id: list.c 10926 2008-11-11 22:17:40Z wsfulton $"; + +#include "dohint.h" + +typedef struct List { + int maxitems; /* Max size */ + int nitems; /* Num items */ + DOH *file; + int line; + DOH **items; +} List; + +extern DohObjInfo DohListType; + +/* Doubles amount of memory in a list */ +static +void more(List *l) { + l->items = (void **) DohRealloc(l->items, l->maxitems * 2 * sizeof(void *)); + assert(l->items); + l->maxitems *= 2; +} + +/* ----------------------------------------------------------------------------- + * CopyList() + * + * Make a shallow copy of a list. + * ----------------------------------------------------------------------------- */ +static DOH *CopyList(DOH *lo) { + List *l, *nl; + int i; + l = (List *) ObjData(lo); + nl = (List *) DohMalloc(sizeof(List)); + nl->nitems = l->nitems; + nl->maxitems = l->maxitems; + nl->items = (void **) DohMalloc(l->maxitems * sizeof(void *)); + for (i = 0; i < l->nitems; i++) { + nl->items[i] = l->items[i]; + Incref(nl->items[i]); + } + nl->file = l->file; + if (nl->file) + Incref(nl->file); + nl->line = l->line; + return DohObjMalloc(&DohListType, nl); +} + +/* ----------------------------------------------------------------------------- + * DelList() + * + * Delete a list. + * ----------------------------------------------------------------------------- */ + +static void DelList(DOH *lo) { + List *l = (List *) ObjData(lo); + int i; + for (i = 0; i < l->nitems; i++) + Delete(l->items[i]); + DohFree(l->items); + DohFree(l); +} + +/* ----------------------------------------------------------------------------- + * List_clear() + * + * Remove all of the list entries, but keep the list object intact. + * ----------------------------------------------------------------------------- */ + +static void List_clear(DOH *lo) { + List *l = (List *) ObjData(lo); + int i; + for (i = 0; i < l->nitems; i++) { + Delete(l->items[i]); + } + l->nitems = 0; +} + +/* ----------------------------------------------------------------------------- + * List_insert() + * + * Insert an item into the list. If the item is not a DOH object, it is assumed + * to be a 'char *' and is used to construct an equivalent string object. + * ----------------------------------------------------------------------------- */ + +static int List_insert(DOH *lo, int pos, DOH *item) { + List *l = (List *) ObjData(lo); + int i; + + if (!item) + return -1; + if (!DohCheck(item)) { + item = NewString(item); + Decref(item); + } + if (pos == DOH_END) + pos = l->nitems; + if (pos < 0) + pos = 0; + if (pos > l->nitems) + pos = l->nitems; + if (l->nitems == l->maxitems) + more(l); + for (i = l->nitems; i > pos; i--) { + l->items[i] = l->items[i - 1]; + } + l->items[pos] = item; + Incref(item); + l->nitems++; + return 0; +} + +/* ----------------------------------------------------------------------------- + * List_remove() + * + * Remove an item from a list. + * ----------------------------------------------------------------------------- */ + +static int List_remove(DOH *lo, int pos) { + List *l = (List *) ObjData(lo); + int i; + if (pos == DOH_END) + pos = l->nitems - 1; + if (pos == DOH_BEGIN) + pos = 0; + assert(!((pos < 0) || (pos >= l->nitems))); + Delete(l->items[pos]); + for (i = pos; i < l->nitems - 1; i++) { + l->items[i] = l->items[i + 1]; + } + l->nitems--; + return 0; +} + +/* ----------------------------------------------------------------------------- + * List_len() + * + * Return the number of elements in the list + * ----------------------------------------------------------------------------- */ + +static int List_len(DOH *lo) { + List *l = (List *) ObjData(lo); + return l->nitems; +} + +/* ----------------------------------------------------------------------------- + * List_get() + * + * Get the nth item from the list. + * ----------------------------------------------------------------------------- */ + +static DOH *List_get(DOH *lo, int n) { + List *l = (List *) ObjData(lo); + if (n == DOH_END) + n = l->nitems - 1; + if (n == DOH_BEGIN) + n = 0; + assert(!((n < 0) || (n >= l->nitems))); + return l->items[n]; +} + +/* ----------------------------------------------------------------------------- + * List_set() + * + * Set the nth item in the list replacing any previous item. + * ----------------------------------------------------------------------------- */ + +static int List_set(DOH *lo, int n, DOH *val) { + List *l = (List *) ObjData(lo); + if (!val) + return -1; + assert(!((n < 0) || (n >= l->nitems))); + if (!DohCheck(val)) { + val = NewString(val); + Decref(val); + } + Delete(l->items[n]); + l->items[n] = val; + Incref(val); + Delete(val); + return 0; +} + +/* ----------------------------------------------------------------------------- + * List_first() + * + * Return the first item in the list. + * ----------------------------------------------------------------------------- */ + +static DohIterator List_first(DOH *lo) { + DohIterator iter; + List *l = (List *) ObjData(lo); + iter.object = lo; + iter._index = 0; + iter._current = 0; + iter.key = 0; + if (l->nitems > 0) { + iter.item = l->items[0]; + } else { + iter.item = 0; + } + return iter; +} + +/* ----------------------------------------------------------------------------- + * List_next() + * + * Return the next item in the list. + * ----------------------------------------------------------------------------- */ + +static DohIterator List_next(DohIterator iter) { + List *l = (List *) ObjData(iter.object); + iter._index = iter._index + 1; + if (iter._index >= l->nitems) { + iter.item = 0; + iter.key = 0; + } else { + iter.item = l->items[iter._index]; + } + return iter; +} + +/* ----------------------------------------------------------------------------- + * List_str() + * + * Create a string representation of the list. + * ----------------------------------------------------------------------------- */ +static DOH *List_str(DOH *lo) { + DOH *s; + int i; + List *l = (List *) ObjData(lo); + s = NewStringEmpty(); + if (ObjGetMark(lo)) { + Printf(s, "List(%x)", lo); + return s; + } + ObjSetMark(lo, 1); + Printf(s, "List[ "); + for (i = 0; i < l->nitems; i++) { + Printf(s, "%s", l->items[i]); + if ((i + 1) < l->nitems) + Printf(s, ", "); + } + Printf(s, " ]\n"); + ObjSetMark(lo, 0); + return s; +} + +/* ----------------------------------------------------------------------------- + * List_dump() + * + * Dump the items to an output stream. + * ----------------------------------------------------------------------------- */ + +static int List_dump(DOH *lo, DOH *out) { + int nsent = 0; + int i, ret; + List *l = (List *) ObjData(lo); + for (i = 0; i < l->nitems; i++) { + ret = Dump(l->items[i], out); + if (ret < 0) + return -1; + nsent += ret; + } + return nsent; +} + +static void List_setfile(DOH *lo, DOH *file) { + DOH *fo; + List *l = (List *) ObjData(lo); + + if (!DohCheck(file)) { + fo = NewString(file); + Decref(fo); + } else + fo = file; + Incref(fo); + Delete(l->file); + l->file = fo; +} + +static DOH *List_getfile(DOH *lo) { + List *l = (List *) ObjData(lo); + return l->file; +} + +static void List_setline(DOH *lo, int line) { + List *l = (List *) ObjData(lo); + l->line = line; +} + +static int List_getline(DOH *lo) { + List *l = (List *) ObjData(lo); + return l->line; +} + +static DohListMethods ListListMethods = { + List_get, + List_set, + List_remove, + List_insert, + 0, /* delslice */ +}; + +DohObjInfo DohListType = { + "List", /* objname */ + DelList, /* doh_del */ + CopyList, /* doh_copy */ + List_clear, /* doh_clear */ + List_str, /* doh_str */ + 0, /* doh_data */ + List_dump, /* doh_dump */ + List_len, /* doh_len */ + 0, /* doh_hash */ + 0, /* doh_cmp */ + 0, /* doh_equal */ + List_first, /* doh_first */ + List_next, /* doh_next */ + List_setfile, /* doh_setfile */ + List_getfile, /* doh_getfile */ + List_setline, /* doh_setline */ + List_getline, /* doh_getline */ + 0, /* doh_mapping */ + &ListListMethods, /* doh_sequence */ + 0, /* doh_file */ + 0, /* doh_string */ + 0, /* doh_callable */ + 0, /* doh_position */ +}; + +/* ----------------------------------------------------------------------------- + * NewList() + * + * Create a new list. + * ----------------------------------------------------------------------------- */ + +#define MAXLISTITEMS 8 + +DOH *DohNewList(void) { + List *l; + int i; + l = (List *) DohMalloc(sizeof(List)); + l->nitems = 0; + l->maxitems = MAXLISTITEMS; + l->items = (void **) DohMalloc(l->maxitems * sizeof(void *)); + for (i = 0; i < MAXLISTITEMS; i++) { + l->items[i] = 0; + } + l->file = 0; + l->line = 0; + return DohObjMalloc(&DohListType, l); +} + +static int (*List_sort_compare_func) (const DOH *, const DOH *); +static int List_qsort_compare(const void *a, const void *b) { + return List_sort_compare_func(*((DOH **) a), *((DOH **) b)); +} + +/* Sort a list */ +void DohSortList(DOH *lo, int (*cmp) (const DOH *, const DOH *)) { + List *l = (List *) ObjData(lo); + if (cmp) { + List_sort_compare_func = cmp; + } else { + List_sort_compare_func = DohCmp; + } + qsort(l->items, l->nitems, sizeof(DOH *), List_qsort_compare); +} diff --git a/Source/DOH/memory.c b/Source/DOH/memory.c new file mode 100644 index 0000000..79ff21c --- /dev/null +++ b/Source/DOH/memory.c @@ -0,0 +1,220 @@ +/* ----------------------------------------------------------------------------- + * memory.c + * + * This file implements all of DOH's memory management including allocation + * of objects and checking of objects. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_memory_c[] = "$Id: memory.c 9607 2006-12-05 22:11:40Z beazley $"; + +#include "dohint.h" + +#ifndef DOH_POOL_SIZE +#define DOH_POOL_SIZE 16384 +#endif + +static int PoolSize = DOH_POOL_SIZE; + +DOH *DohNone = 0; /* The DOH None object */ + +typedef struct pool { + DohBase *ptr; /* Start of pool */ + int len; /* Length of pool */ + int blen; /* Byte length of pool */ + int current; /* Current position for next allocation */ + char *pbeg; /* Beg of pool */ + char *pend; /* End of pool */ + struct pool *next; /* Next pool */ +} Pool; + +static DohBase *FreeList = 0; /* List of free objects */ +static Pool *Pools = 0; +static int pools_initialized = 0; + +/* ---------------------------------------------------------------------- + * CreatePool() - Create a new memory pool + * ---------------------------------------------------------------------- */ + +static void CreatePool() { + Pool *p = 0; + p = (Pool *) DohMalloc(sizeof(Pool)); + assert(p); + p->ptr = (DohBase *) DohMalloc(sizeof(DohBase) * PoolSize); + assert(p->ptr); + memset(p->ptr, 0, sizeof(DohBase) * PoolSize); + p->len = PoolSize; + p->blen = PoolSize * sizeof(DohBase); + p->current = 0; + p->pbeg = ((char *) p->ptr); + p->pend = p->pbeg + p->blen; + p->next = Pools; + Pools = p; +} + +/* ---------------------------------------------------------------------- + * InitPools() - Initialize the memory allocator + * ---------------------------------------------------------------------- */ + +static void InitPools() { + if (pools_initialized) + return; + CreatePool(); /* Create initial pool */ + pools_initialized = 1; + DohNone = NewVoid(0, 0); /* Create the None object */ + DohIntern(DohNone); +} + +/* ---------------------------------------------------------------------- + * DohCheck() + * + * Returns 1 if an arbitrary pointer is a DOH object. + * ---------------------------------------------------------------------- */ + +int DohCheck(const DOH *ptr) { + register Pool *p = Pools; + register char *cptr = (char *) ptr; + while (p) { + if ((cptr >= p->pbeg) && (cptr < p->pend)) + return 1; + /* + pptr = (char *) p->ptr; + if ((cptr >= pptr) && (cptr < (pptr+(p->current*sizeof(DohBase))))) return 1; */ + p = p->next; + } + return 0; +} + +/* ----------------------------------------------------------------------------- + * DohIntern() + * ----------------------------------------------------------------------------- */ + +void DohIntern(DOH *obj) { + DohBase *b = (DohBase *) obj; + b->flag_intern = 1; +} + +/* ---------------------------------------------------------------------- + * DohObjMalloc() + * + * Allocate memory for a new object. + * ---------------------------------------------------------------------- */ + +DOH *DohObjMalloc(DohObjInfo *type, void *data) { + DohBase *obj; + if (!pools_initialized) + InitPools(); + if (FreeList) { + obj = FreeList; + FreeList = (DohBase *) obj->data; + } else { + while (Pools->current == Pools->len) { + CreatePool(); + } + obj = Pools->ptr + Pools->current; + ++Pools->current; + } + obj->type = type; + obj->data = data; + obj->meta = 0; + obj->refcount = 1; + obj->flag_intern = 0; + obj->flag_marked = 0; + obj->flag_user = 0; + obj->flag_usermark = 0; + return (DOH *) obj; +} + +/* ---------------------------------------------------------------------- + * DohObjFree() - Free a DOH object + * ---------------------------------------------------------------------- */ + +void DohObjFree(DOH *ptr) { + DohBase *b, *meta; + b = (DohBase *) ptr; + if (b->flag_intern) + return; + meta = (DohBase *) b->meta; + b->data = (void *) FreeList; + b->meta = 0; + b->type = 0; + FreeList = b; + if (meta) { + Delete(meta); + } +} + +/* ---------------------------------------------------------------------- + * DohMemoryDebug() + * + * Display memory usage statistics + * ---------------------------------------------------------------------- */ + +void DohMemoryDebug(void) { + extern DohObjInfo DohStringType; + extern DohObjInfo DohListType; + extern DohObjInfo DohHashType; + + Pool *p; + int totsize = 0; + int totused = 0; + int totfree = 0; + + int numstring = 0; + int numlist = 0; + int numhash = 0; + + printf("Memory statistics:\n\n"); + printf("Pools:\n"); + + p = Pools; + while (p) { + /* Calculate number of used, free items */ + int i; + int nused = 0, nfree = 0; + for (i = 0; i < p->len; i++) { + if (p->ptr[i].refcount <= 0) + nfree++; + else { + nused++; + if (p->ptr[i].type == &DohStringType) + numstring++; + else if (p->ptr[i].type == &DohListType) + numlist++; + else if (p->ptr[i].type == &DohHashType) + numhash++; + } + } + printf(" Pool %8p: size = %10d. used = %10d. free = %10d\n", (void *) p, p->len, nused, nfree); + totsize += p->len; + totused += nused; + totfree += nfree; + p = p->next; + } + printf("\n Total: size = %10d, used = %10d, free = %10d\n", totsize, totused, totfree); + + printf("\nObject types\n"); + printf(" Strings : %d\n", numstring); + printf(" Lists : %d\n", numlist); + printf(" Hashes : %d\n", numhash); + +#if 0 + p = Pools; + while (p) { + int i; + for (i = 0; i < p->len; i++) { + if (p->ptr[i].refcount > 0) { + if (p->ptr[i].type == &DohStringType) { + Printf(stdout, "%s\n", p->ptr + i); + } + } + } + p = p->next; + } +#endif + +} diff --git a/Source/DOH/string.c b/Source/DOH/string.c new file mode 100644 index 0000000..425a39f --- /dev/null +++ b/Source/DOH/string.c @@ -0,0 +1,1158 @@ +/* ----------------------------------------------------------------------------- + * string.c + * + * Implements a string object that supports both sequence operations and + * file semantics. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_string_c[] = "$Id: string.c 10926 2008-11-11 22:17:40Z wsfulton $"; + +#include "dohint.h" + +extern DohObjInfo DohStringType; + +typedef struct String { + DOH *file; + int line; + int maxsize; /* Max size allocated */ + int len; /* Current length */ + int hashkey; /* Hash key value */ + int sp; /* Current position */ + char *str; /* String data */ +} String; + +/* ----------------------------------------------------------------------------- + * void *String_data() - Return as a 'void *' + * ----------------------------------------------------------------------------- */ + +static void *String_data(DOH *so) { + String *s = (String *) ObjData(so); + s->str[s->len] = 0; + return (void *) s->str; +} + +/* static char *String_char(DOH *so) { + return (char *) String_data(so); +} +*/ + +/* ----------------------------------------------------------------------------- + * int String_dump() - Serialize a string onto out + * ----------------------------------------------------------------------------- */ + +static int String_dump(DOH *so, DOH *out) { + int nsent; + int ret; + String *s = (String *) ObjData(so); + nsent = 0; + while (nsent < s->len) { + ret = Write(out, s->str + nsent, (s->len - nsent)); + if (ret < 0) + return ret; + nsent += ret; + } + return nsent; +} + +/* ----------------------------------------------------------------------------- + * CopyString() - Copy a string + * ----------------------------------------------------------------------------- */ + +static DOH *CopyString(DOH *so) { + String *str; + String *s = (String *) ObjData(so); + str = (String *) DohMalloc(sizeof(String)); + str->hashkey = s->hashkey; + str->sp = s->sp; + str->line = s->line; + str->file = s->file; + if (str->file) + Incref(str->file); + str->str = (char *) DohMalloc(s->len + 1); + memcpy(str->str, s->str, s->len); + str->maxsize = s->len; + str->len = s->len; + str->str[str->len] = 0; + + return DohObjMalloc(&DohStringType, str); +} + +/* ----------------------------------------------------------------------------- + * DelString() - Delete a string + * ----------------------------------------------------------------------------- */ + +static void DelString(DOH *so) { + String *s = (String *) ObjData(so); + DohFree(s->str); + DohFree(s); +} + +/* ----------------------------------------------------------------------------- + * DohString_len() - Length of a string + * ----------------------------------------------------------------------------- */ + +static int String_len(DOH *so) { + String *s = (String *) ObjData(so); + return s->len; +} + + +/* ----------------------------------------------------------------------------- + * int String_cmp() - Compare two strings + * ----------------------------------------------------------------------------- */ + +static int String_cmp(DOH *so1, DOH *so2) { + String *s1, *s2; + char *c1, *c2; + int maxlen, i; + s1 = (String *) ObjData(so1); + s2 = (String *) ObjData(so2); + maxlen = s1->len; + if (s2->len < maxlen) + maxlen = s2->len; + c1 = s1->str; + c2 = s2->str; + for (i = maxlen; i; --i, c1++, c2++) { + if (*c1 != *c2) + break; + } + if (i != 0) { + if (*c1 < *c2) + return -1; + else + return 1; + } + if (s1->len == s2->len) + return 0; + if (s1->len > s2->len) + return 1; + return -1; +} + +/* ----------------------------------------------------------------------------- + * int String_equal() - Say if two string are equal + * ----------------------------------------------------------------------------- */ + +static int String_equal(DOH *so1, DOH *so2) { + String *s1 = (String *) ObjData(so1); + String *s2 = (String *) ObjData(so2); + register int len = s1->len; + if (len != s2->len) { + return 0; + } else { + register char *c1 = s1->str; + register char *c2 = s2->str; +#if 0 + register int mlen = len >> 2; + register int i = mlen; + for (; i; --i) { + if (*(c1++) != *(c2++)) + return 0; + if (*(c1++) != *(c2++)) + return 0; + if (*(c1++) != *(c2++)) + return 0; + if (*(c1++) != *(c2++)) + return 0; + } + for (i = len - (mlen << 2); i; --i) { + if (*(c1++) != *(c2++)) + return 0; + } + return 1; +#else + return memcmp(c1, c2, len) == 0; +#endif + } +} + +/* ----------------------------------------------------------------------------- + * int String_hash() - Compute string hash value + * ----------------------------------------------------------------------------- */ + +static int String_hash(DOH *so) { + String *s = (String *) ObjData(so); + if (s->hashkey >= 0) { + return s->hashkey; + } else { + register char *c = s->str; + register int len = s->len > 50 ? 50 : s->len; + register int h = 0; + register int mlen = len >> 2; + register int i = mlen; + for (; i; --i) { + h = (h << 5) + *(c++); + h = (h << 5) + *(c++); + h = (h << 5) + *(c++); + h = (h << 5) + *(c++); + } + for (i = len - (mlen << 2); i; --i) { + h = (h << 5) + *(c++); + } + h &= 0x7fffffff; + s->hashkey = h; + return h; + } +} + +/* ----------------------------------------------------------------------------- + * DohString_append(String *s, const char *newstr) - Append to s + * ----------------------------------------------------------------------------- */ + +void DohString_append(DOH *so, DOH *str) { + int oldlen, newlen, newmaxsize, l, sp; + char *tc; + String *s = (String *) ObjData(so); + char *newstr = 0; + + if (DohCheck(str)) { + String *ss = (String *) ObjData(str); + newstr = (char *) String_data((DOH *) str); + l = ss->len; + } else { + newstr = (char *) (str); + l = (int) strlen(newstr); + } + if (!newstr) + return; + s->hashkey = -1; + + oldlen = s->len; + newlen = oldlen + l + 1; + if (newlen >= s->maxsize - 1) { + newmaxsize = 2 * s->maxsize; + if (newlen >= newmaxsize - 1) + newmaxsize = newlen + 1; + s->str = (char *) DohRealloc(s->str, newmaxsize); + assert(s->str); + s->maxsize = newmaxsize; + } + tc = s->str; + memcpy(tc + oldlen, newstr, l + 1); + sp = s->sp; + if (sp >= oldlen) { + int i = oldlen + l - sp; + tc += sp; + for (; i; --i) { + if (*(tc++) == '\n') + s->line++; + } + s->sp = oldlen + l; + } + s->len += l; +} + + +/* ----------------------------------------------------------------------------- + * void String_clear() - Clear a string + * ----------------------------------------------------------------------------- */ + +static void String_clear(DOH *so) { + String *s = (String *) ObjData(so); + s->hashkey = -1; + s->len = 0; + *(s->str) = 0; + s->sp = 0; + s->line = 1; +} + +/* ----------------------------------------------------------------------------- + * void String_insert() - Insert a string + * ----------------------------------------------------------------------------- */ + +static int String_insert(DOH *so, int pos, DOH *str) { + String *s; + char *nstr; + int len; + char *data; + + if (pos == DOH_END) { + DohString_append(so, str); + return 0; + } + + + s = (String *) ObjData(so); + s->hashkey = -1; + if (DohCheck(str)) { + String *ss = (String *) ObjData(str); + data = (char *) String_data(str); + len = ss->len; + } else { + data = (char *) (str); + len = (int) strlen(data); + } + nstr = s->str; + + if (pos < 0) + pos = 0; + else if (pos > s->len) + pos = s->len; + + /* See if there is room to insert the new data */ + while (s->maxsize <= s->len + len) { + int newsize = 2 * s->maxsize; + s->str = (char *) DohRealloc(s->str, newsize); + assert(s->str); + s->maxsize = newsize; + } + memmove(s->str + pos + len, s->str + pos, (s->len - pos)); + memcpy(s->str + pos, data, len); + if (s->sp >= pos) { + int i; + + for (i = 0; i < len; i++) { + if (data[i] == '\n') + s->line++; + } + s->sp += len; + } + s->len += len; + s->str[s->len] = 0; + return 0; +} + +/* ----------------------------------------------------------------------------- + * int String_delitem() - Delete a character + * ----------------------------------------------------------------------------- */ + +static int String_delitem(DOH *so, int pos) { + String *s = (String *) ObjData(so); + 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->sp > pos) { + s->sp--; + assert(s->sp >= 0); + if (s->str[pos] == '\n') + s->line--; + } + memmove(s->str + pos, s->str + pos + 1, ((s->len - 1) - pos)); + s->len--; + s->str[s->len] = 0; + return 0; +} + +/* ----------------------------------------------------------------------------- + * int String_delslice() - Delete a range + * ----------------------------------------------------------------------------- */ + +static int String_delslice(DOH *so, int sindex, int eindex) { + String *s = (String *) ObjData(so); + int size; + if (s->len == 0) + return 0; + s->hashkey = -1; + if (eindex == DOH_END) + eindex = s->len; + if (sindex == DOH_BEGIN) + sindex = 0; + + size = eindex - sindex; + if (s->sp > sindex) { + /* Adjust the file pointer and line count */ + int i, end; + if (s->sp > eindex) { + end = eindex; + s->sp -= size; + } else { + end = s->sp; + s->sp = sindex; + } + for (i = sindex; i < end; i++) { + if (s->str[i] == '\n') + s->line--; + } + assert(s->sp >= 0); + } + memmove(s->str + sindex, s->str + eindex, s->len - eindex); + s->len -= size; + s->str[s->len] = 0; + return 0; +} + +/* ----------------------------------------------------------------------------- + * DOH *String_str() - Returns a string (used by printing commands) + * ----------------------------------------------------------------------------- */ + +static DOH *String_str(DOH *so) { + String *s = (String *) ObjData(so); + s->str[s->len] = 0; + return NewString(s->str); +} + +/* ----------------------------------------------------------------------------- + * int String_read() - Read data from a string + * ----------------------------------------------------------------------------- */ + +static int String_read(DOH *so, void *buffer, int len) { + int reallen, retlen; + char *cb; + String *s = (String *) ObjData(so); + if ((s->sp + len) > s->len) + reallen = (s->len - s->sp); + else + reallen = len; + + cb = (char *) buffer; + retlen = reallen; + + if (reallen > 0) { + memmove(cb, s->str + s->sp, reallen); + s->sp += reallen; + } + return retlen; +} + +/* ----------------------------------------------------------------------------- + * int String_write() - Write data to a string + * ----------------------------------------------------------------------------- */ +static int String_write(DOH *so, void *buffer, int len) { + int newlen; + String *s = (String *) ObjData(so); + s->hashkey = -1; + if (s->sp > s->len) + s->sp = s->len; + newlen = s->sp + len + 1; + if (newlen > s->maxsize) { + s->str = (char *) DohRealloc(s->str, newlen); + assert(s->str); + s->maxsize = newlen; + s->len = s->sp + len; + } + if ((s->sp + len) > s->len) + s->len = s->sp + len; + memmove(s->str + s->sp, buffer, len); + s->sp += len; + s->str[s->len] = 0; + return len; +} + +/* ----------------------------------------------------------------------------- + * int String_seek() - Seek to a new position + * ----------------------------------------------------------------------------- */ + +static int String_seek(DOH *so, long offset, int whence) { + int pos, nsp, inc; + String *s = (String *) ObjData(so); + if (whence == SEEK_SET) + pos = 0; + else if (whence == SEEK_CUR) + pos = s->sp; + else if (whence == SEEK_END) { + pos = s->len; + offset = -offset; + } else + pos = s->sp; + + nsp = pos + offset; + if (nsp < 0) + nsp = 0; + if (s->len > 0 && nsp > s->len) + nsp = s->len; + + inc = (nsp > s->sp) ? 1 : -1; + + { +#if 0 + register int sp = s->sp; + register char *tc = s->str; + register int len = s->len; + while (sp != nsp) { + int prev = sp + inc; + if (prev >= 0 && prev <= len && tc[prev] == '\n') + s->line += inc; + sp += inc; + } +#else + register int sp = s->sp; + register char *tc = s->str; + if (inc > 0) { + while (sp != nsp) { + if (tc[++sp] == '\n') + ++s->line; + } + } else { + while (sp != nsp) { + if (tc[--sp] == '\n') + --s->line; + } + } +#endif + s->sp = sp; + } + assert(s->sp >= 0); + return 0; +} + +/* ----------------------------------------------------------------------------- + * long String_tell() - Return current position + * ----------------------------------------------------------------------------- */ + +static long String_tell(DOH *so) { + String *s = (String *) ObjData(so); + return (long) (s->sp); +} + +/* ----------------------------------------------------------------------------- + * int String_putc() + * ----------------------------------------------------------------------------- */ + +static int String_putc(DOH *so, int ch) { + String *s = (String *) ObjData(so); + register int len = s->len; + register int sp = s->sp; + s->hashkey = -1; + if (sp >= len) { + register int maxsize = s->maxsize; + register char *tc = s->str; + if (len > (maxsize - 2)) { + maxsize *= 2; + tc = (char *) DohRealloc(tc, maxsize); + assert(tc); + s->maxsize = (int) maxsize; + s->str = tc; + } + tc += sp; + *tc = (char) ch; + *(++tc) = 0; + s->len = s->sp = sp + 1; + } else { + s->str[s->sp++] = (char) ch; + } + if (ch == '\n') + s->line++; + return ch; +} + +/* ----------------------------------------------------------------------------- + * int String_getc() + * ----------------------------------------------------------------------------- */ + +static int String_getc(DOH *so) { + int c; + String *s = (String *) ObjData(so); + if (s->sp >= s->len) + c = EOF; + else + c = (int)(unsigned char) s->str[s->sp++]; + if (c == '\n') + s->line++; + return c; +} + +/* ----------------------------------------------------------------------------- + * int String_ungetc() + * ----------------------------------------------------------------------------- */ + +static int String_ungetc(DOH *so, int ch) { + String *s = (String *) ObjData(so); + if (ch == EOF) + return ch; + if (s->sp <= 0) + return EOF; + s->sp--; + if (ch == '\n') + s->line--; + return ch; +} + +/* ----------------------------------------------------------------------------- + * replace_simple(String *str, char *token, char *rep, int flags, int count) + * + * Replaces count non-overlapping occurrences of token with rep in a string. + * ----------------------------------------------------------------------------- */ + +static char *end_quote(char *s) { + char *qs; + char qc; + char *q; + char *nl; + qc = *s; + qs = s; + while (1) { + q = strpbrk(s + 1, "\"\'"); + nl = strchr(s + 1, '\n'); + if (nl && (nl < q)) { + /* A new line appears before the end of the string */ + if (*(nl - 1) == '\\') { + s = nl + 1; + continue; + } + /* String was terminated by a newline. Wing it */ + return qs; + } + if (!q && nl) { + return qs; + } + if (!q) + return 0; + if ((*q == qc) && (*(q - 1) != '\\')) + return q; + s = q; + } +} + +static char *match_simple(char *base, char *s, char *token, int tokenlen) { + (void) base; + (void) tokenlen; + return strstr(s, token); +} + +static char *match_identifier(char *base, char *s, char *token, int tokenlen) { + while (s) { + s = strstr(s, token); + if (!s) + return 0; + if ((s > base) && (isalnum((int) *(s - 1)) || (*(s - 1) == '_'))) { + s += tokenlen; + continue; + } + if (isalnum((int) *(s + tokenlen)) || (*(s + tokenlen) == '_')) { + s += tokenlen; + continue; + } + return s; + } + return 0; +} + + +static char *match_identifier_begin(char *base, char *s, char *token, int tokenlen) { + while (s) { + s = strstr(s, token); + if (!s) + return 0; + if ((s > base) && (isalnum((int) *(s - 1)) || (*(s - 1) == '_'))) { + s += tokenlen; + continue; + } + return s; + } + return 0; +} + +static char *match_identifier_end(char *base, char *s, char *token, int tokenlen) { + (void) base; + while (s) { + s = strstr(s, token); + if (!s) + return 0; + if (isalnum((int) *(s + tokenlen)) || (*(s + tokenlen) == '_')) { + s += tokenlen; + continue; + } + return s; + } + return 0; +} + +static int replace_simple(String *str, char *token, char *rep, int flags, int count, char *(*match) (char *, char *, char *, int)) { + int tokenlen; /* Length of the token */ + int replen; /* Length of the replacement */ + int delta, expand = 0; + int ic; + int rcount = 0; + int noquote = 0; + char *c, *s, *t, *first; + char *q, *q2; + register char *base; + int i; + + /* Figure out if anything gets replaced */ + if (!strlen(token)) + return 0; + + base = str->str; + tokenlen = strlen(token); + s = (*match) (base, base, token, tokenlen); + + if (!s) + return 0; /* No matches. Who cares */ + + str->hashkey = -1; + + if (flags & DOH_REPLACE_NOQUOTE) + noquote = 1; + + /* If we are not replacing inside quotes, we need to do a little extra work */ + if (noquote) { + q = strpbrk(base, "\"\'"); + if (!q) { + noquote = 0; /* Well, no quotes to worry about. Oh well */ + } else { + while (q && (q < s)) { + /* First match was found inside a quote. Try to find another match */ + q2 = end_quote(q); + if (!q2) { + return 0; + } + if (q2 > s) { + /* Find next match */ + s = (*match) (base, q2 + 1, token, tokenlen); + } + if (!s) + return 0; /* Oh well, no matches */ + q = strpbrk(q2 + 1, "\"\'"); + if (!q) + noquote = 0; /* No more quotes */ + } + } + } + + first = s; + replen = strlen(rep); + + delta = (replen - tokenlen); + + if (delta <= 0) { + /* String is either shrinking or staying the same size */ + /* In this case, we do the replacement in place without memory reallocation */ + ic = count; + t = s; /* Target of memory copies */ + while (ic && s) { + if (replen) { + memcpy(t, rep, replen); + t += replen; + } + rcount++; + expand += delta; + /* Find the next location */ + s += tokenlen; + if (ic == 1) + break; + c = (*match) (base, s, token, tokenlen); + + if (noquote) { + q = strpbrk(s, "\"\'"); + if (!q) { + noquote = 0; + } else { + while (q && (q < c)) { + /* First match was found inside a quote. Try to find another match */ + q2 = end_quote(q); + if (!q2) { + c = 0; + break; + } + if (q2 > c) + c = (*match) (base, q2 + 1, token, tokenlen); + if (!c) + break; + q = strpbrk(q2 + 1, "\"\'"); + if (!q) + noquote = 0; /* No more quotes */ + } + } + } + if (delta) { + if (c) { + memmove(t, s, c - s); + t += (c - s); + } else { + memmove(t, s, (str->str + str->len) - s + 1); + } + } else { + t += (c - s); + } + s = c; + ic--; + } + if (s && delta) { + memmove(t, s, (str->str + str->len) - s + 1); + } + str->len += expand; + str->str[str->len] = 0; + if (str->sp >= str->len) + str->sp += expand; /* Fix the end of file pointer */ + return rcount; + } + /* The string is expanding as a result of the replacement */ + /* Figure out how much expansion is going to occur and allocate a new string */ + { + char *ns; + int newsize; + + rcount++; + ic = count - 1; + s += tokenlen; + while (ic && (c = (*match) (base, s, token, tokenlen))) { + if (noquote) { + q = strpbrk(s, "\"\'"); + if (!q) { + break; + } else { + while (q && (q < c)) { + /* First match was found inside a quote. Try to find another match */ + q2 = end_quote(q); + if (!q2) { + c = 0; + break; + } + if (q2 > c) { + c = (*match) (base, q2 + 1, token, tokenlen); + if (!c) + break; + } + q = strpbrk(q2 + 1, "\"\'"); + if (!q) + noquote = 0; + } + } + } + if (c) { + rcount++; + ic--; + s = c + tokenlen; + } else { + break; + } + } + + expand = delta * rcount; /* Total amount of expansion for the replacement */ + newsize = str->maxsize; + while ((str->len + expand) >= newsize) + newsize *= 2; + + ns = (char *) DohMalloc(newsize); + assert(ns); + t = ns; + s = first; + + /* Copy the first part of the string */ + if (first > str->str) { + memcpy(t, str->str, (first - str->str)); + t += (first - str->str); + } + for (i = 0; i < rcount; i++) { + memcpy(t, rep, replen); + t += replen; + s += tokenlen; + c = (*match) (base, s, token, tokenlen); + if (noquote) { + q = strpbrk(s, "\"\'"); + if (!q) { + noquote = 0; + } else { + while (q && (q < c)) { + /* First match was found inside a quote. Try to find another match */ + q2 = end_quote(q); + if (!q2) { + c = 0; + break; + } + if (q2 > c) { + c = (*match) (base, q2 + 1, token, tokenlen); + if (!c) + break; + } + q = strpbrk(q2 + 1, "\"\'"); + if (!q) + noquote = 0; /* No more quotes */ + } + } + } + if (i < (rcount - 1)) { + memcpy(t, s, c - s); + t += (c - s); + } else { + memcpy(t, s, (str->str + str->len) - s + 1); + } + s = c; + } + c = str->str; + str->str = ns; + if (str->sp >= str->len) + str->sp += expand; + str->len += expand; + str->str[str->len] = 0; + str->maxsize = newsize; + DohFree(c); + return rcount; + } +} + +/* ----------------------------------------------------------------------------- + * int String_replace() + * ----------------------------------------------------------------------------- */ + +static int String_replace(DOH *stro, DOH *token, DOH *rep, int flags) { + int count = -1; + String *str = (String *) ObjData(stro); + + if (flags & DOH_REPLACE_FIRST) + count = 1; + + if (flags & DOH_REPLACE_ID_END) { + return replace_simple(str, Char(token), Char(rep), flags, count, match_identifier_end); + } else if (flags & DOH_REPLACE_ID_BEGIN) { + return replace_simple(str, Char(token), Char(rep), flags, count, match_identifier_begin); + } else if (flags & DOH_REPLACE_ID) { + return replace_simple(str, Char(token), Char(rep), flags, count, match_identifier); + } else { + return replace_simple(str, Char(token), Char(rep), flags, count, match_simple); + } +} + +/* ----------------------------------------------------------------------------- + * void String_chop(DOH *str) + * ----------------------------------------------------------------------------- */ + +static void String_chop(DOH *so) { + char *c; + String *str = (String *) ObjData(so); + /* Replace trailing whitespace */ + c = str->str + str->len - 1; + while ((str->len > 0) && (isspace((int) *c))) { + if (str->sp >= str->len) { + str->sp--; + if (*c == '\n') + str->line--; + } + str->len--; + c--; + } + str->str[str->len] = 0; + assert(str->sp >= 0); + str->hashkey = -1; +} + +static void String_setfile(DOH *so, DOH *file) { + DOH *fo; + String *str = (String *) ObjData(so); + + if (!DohCheck(file)) { + fo = NewString(file); + Decref(fo); + } else + fo = file; + Incref(fo); + Delete(str->file); + str->file = fo; +} + +static DOH *String_getfile(DOH *so) { + String *str = (String *) ObjData(so); + return str->file; +} + +static void String_setline(DOH *so, int line) { + String *str = (String *) ObjData(so); + str->line = line; +} + +static int String_getline(DOH *so) { + String *str = (String *) ObjData(so); + return str->line; +} + +static DohListMethods StringListMethods = { + 0, /* doh_getitem */ + 0, /* doh_setitem */ + String_delitem, /* doh_delitem */ + String_insert, /* doh_insitem */ + String_delslice, /* doh_delslice */ +}; + +static DohFileMethods StringFileMethods = { + String_read, + String_write, + String_putc, + String_getc, + String_ungetc, + String_seek, + String_tell, + 0, /* close */ +}; + +static DohStringMethods StringStringMethods = { + String_replace, + String_chop, +}; + +DohObjInfo DohStringType = { + "String", /* objname */ + DelString, /* doh_del */ + CopyString, /* doh_copy */ + String_clear, /* doh_clear */ + String_str, /* doh_str */ + String_data, /* doh_data */ + String_dump, /* doh_dump */ + String_len, /* doh_len */ + String_hash, /* doh_hash */ + String_cmp, /* doh_cmp */ + String_equal, /* doh_equal */ + 0, /* doh_first */ + 0, /* doh_next */ + String_setfile, /* doh_setfile */ + String_getfile, /* doh_getfile */ + String_setline, /* doh_setline */ + String_getline, /* doh_getline */ + 0, /* doh_mapping */ + &StringListMethods, /* doh_sequence */ + &StringFileMethods, /* doh_file */ + &StringStringMethods, /* doh_string */ + 0, /* doh_position */ + 0 +}; + + +#define INIT_MAXSIZE 16 + +/* ----------------------------------------------------------------------------- + * NewString(const char *c) - Create a new string + * ----------------------------------------------------------------------------- */ + +DOHString *DohNewString(const DOH *so) { + int l = 0, max; + String *str; + char *s; + int hashkey = -1; + if (DohCheck(so)) { + str = (String *) ObjData(so); + s = (char *) String_data((String *) so); + l = s ? str->len : 0; + hashkey = str->hashkey; + } else { + s = (char *) so; + l = s ? (int) strlen(s) : 0; + } + + str = (String *) DohMalloc(sizeof(String)); + str->hashkey = hashkey; + str->sp = 0; + str->line = 1; + str->file = 0; + max = INIT_MAXSIZE; + if (s) { + if ((l + 1) > max) + max = l + 1; + } + str->str = (char *) DohMalloc(max); + str->maxsize = max; + if (s) { + strcpy(str->str, s); + str->len = l; + str->sp = l; + } else { + str->str[0] = 0; + str->len = 0; + } + return DohObjMalloc(&DohStringType, str); +} + + +/* ----------------------------------------------------------------------------- + * NewStringEmpty() - Create a new string + * ----------------------------------------------------------------------------- */ + +DOHString *DohNewStringEmpty(void) { + int max = INIT_MAXSIZE; + String *str = (String *) DohMalloc(sizeof(String)); + str->hashkey = 0; + str->sp = 0; + str->line = 1; + str->file = 0; + str->str = (char *) DohMalloc(max); + str->maxsize = max; + str->str[0] = 0; + str->len = 0; + return DohObjMalloc(&DohStringType, str); +} + +/* ----------------------------------------------------------------------------- + * NewStringWithSize(const char *c, int len) - Create a new string + * ----------------------------------------------------------------------------- */ + +DOHString *DohNewStringWithSize(const DOH *so, int len) { + int l = 0, max; + String *str; + char *s; + if (DohCheck(so)) { + s = (char *) String_data((String *) so); + } else { + s = (char *) so; + } + + str = (String *) DohMalloc(sizeof(String)); + str->hashkey = -1; + str->sp = 0; + str->line = 1; + str->file = 0; + max = INIT_MAXSIZE; + if (s) { + l = (int) len; + if ((l + 1) > max) + max = l + 1; + } + str->str = (char *) DohMalloc(max); + str->maxsize = max; + if (s) { + strncpy(str->str, s, len); + str->len = l; + str->sp = l; + } else { + str->str[0] = 0; + str->len = 0; + } + return DohObjMalloc(&DohStringType, str); +} + +/* ----------------------------------------------------------------------------- + * NewStringf(DOH *fmt, ...) + * + * Create a new string from a list of objects. + * ----------------------------------------------------------------------------- */ + +DOHString *DohNewStringf(const DOH *fmt, ...) { + va_list ap; + DOH *r; + va_start(ap, fmt); + r = NewStringEmpty(); + DohvPrintf(r, Char(fmt), ap); + va_end(ap); + return (DOHString *) r; +} + +/* ----------------------------------------------------------------------------- + * Strcmp() + * Strncmp() + * Strstr() + * Strchr() + * + * Some utility functions. + * ----------------------------------------------------------------------------- */ + +int DohStrcmp(const DOHString_or_char *s1, const DOHString_or_char *s2) { + const char *c1 = Char(s1); + const char *c2 = Char(s2); + if (c1 && c2) { + return strcmp(c1, c2); + } else { + return c1 < c2; + } +} + +int DohStrncmp(const DOHString_or_char *s1, const DOHString_or_char *s2, int n) { + return strncmp(Char(s1), Char(s2), n); +} + +char *DohStrstr(const DOHString_or_char *s1, const DOHString_or_char *s2) { + char *p1 = Char(s1); + char *p2 = Char(s2); + return p1 == 0 || p2 == 0 || *p2 == '\0' ? p1 : strstr(p1, p2); +} + +char *DohStrchr(const DOHString_or_char *s1, int ch) { + return strchr(Char(s1), ch); +} diff --git a/Source/DOH/void.c b/Source/DOH/void.c new file mode 100644 index 0000000..ed34da1 --- /dev/null +++ b/Source/DOH/void.c @@ -0,0 +1,96 @@ +/* ----------------------------------------------------------------------------- + * void.c + * + * Implements a "void" object that is really just a DOH container around + * an arbitrary C object represented as a void *. + * + * Author(s) : David Beazley (beazley@cs.uchicago.edu) + * + * Copyright (C) 1999-2000. The University of Chicago + * See the file LICENSE for information on usage and redistribution. + * ----------------------------------------------------------------------------- */ + +char cvsroot_void_c[] = "$Id: void.c 9607 2006-12-05 22:11:40Z beazley $"; + +#include "dohint.h" + +typedef struct { + void *ptr; + void (*del) (void *); +} VoidObj; + +/* ----------------------------------------------------------------------------- + * Void_delete() + * + * Delete a void object. Invokes the destructor supplied at the time of creation. + * ----------------------------------------------------------------------------- */ + +static void Void_delete(DOH *vo) { + VoidObj *v = (VoidObj *) ObjData(vo); + if (v->del) + (*v->del) (v->ptr); + DohFree(v); +} + +/* ----------------------------------------------------------------------------- + * Void_copy() + * + * Copies a void object. This is only a shallow copy. The object destruction + * function is not copied in order to avoid potential double-free problems. + * ----------------------------------------------------------------------------- */ + +static DOH *Void_copy(DOH *vo) { + VoidObj *v = (VoidObj *) ObjData(vo); + return NewVoid(v->ptr, 0); +} + +/* ----------------------------------------------------------------------------- + * Void_data() + * + * Returns the void * stored in the object. + * ----------------------------------------------------------------------------- */ + +static void *Void_data(DOH *vo) { + VoidObj *v = (VoidObj *) ObjData(vo); + return v->ptr; +} + +static DohObjInfo DohVoidType = { + "VoidObj", /* objname */ + Void_delete, /* doh_del */ + Void_copy, /* doh_copy */ + 0, /* doh_clear */ + 0, /* doh_str */ + Void_data, /* doh_data */ + 0, /* doh_dump */ + 0, /* doh_len */ + 0, /* doh_hash */ + 0, /* doh_cmp */ + 0, /* doh_equal */ + 0, /* doh_first */ + 0, /* doh_next */ + 0, /* doh_setfile */ + 0, /* doh_getfile */ + 0, /* doh_setline */ + 0, /* doh_getline */ + 0, /* doh_mapping */ + 0, /* doh_sequence */ + 0, /* doh_file */ + 0, /* doh_string */ + 0, /* doh_reserved */ + 0, /* clientdata */ +}; + +/* ----------------------------------------------------------------------------- + * NewVoid() + * + * Creates a new Void object given a void * and an optional destructor function. + * ----------------------------------------------------------------------------- */ + +DOH *DohNewVoid(void *obj, void (*del) (void *)) { + VoidObj *v; + v = (VoidObj *) DohMalloc(sizeof(VoidObj)); + v->ptr = obj; + v->del = del; + return DohObjMalloc(&DohVoidType, v); +} |
