summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaoyu Bai <divinekid@gmail.com>2009-02-08 16:12:32 +0000
committerHaoyu Bai <divinekid@gmail.com>2009-02-08 16:12:32 +0000
commit9f16400e48eed600f56080deed0075cb20d60f9b (patch)
tree2c04c544d17002fc6c480e762cbdd630eaf72149
parentc2abab2ebbcfa40c171e0c583e198f70db1d70dc (diff)
downloadswig-9f16400e48eed600f56080deed0075cb20d60f9b.tar.gz
Initial commit of DOH2
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/branches/swig-2.0@11121 626c5289-ae23-0410-ae9c-e8d60b6d4f22
-rw-r--r--Source/DOH2/Makefile12
-rw-r--r--Source/DOH2/doh.cxx380
-rw-r--r--Source/DOH2/doh.h513
-rw-r--r--Source/DOH2/file.cxx83
-rw-r--r--Source/DOH2/fio.cxx623
-rw-r--r--Source/DOH2/hash.cxx174
-rw-r--r--Source/DOH2/list.cxx125
-rw-r--r--Source/DOH2/string.cxx639
-rw-r--r--Source/DOH2/test.cxx167
9 files changed, 2716 insertions, 0 deletions
diff --git a/Source/DOH2/Makefile b/Source/DOH2/Makefile
new file mode 100644
index 000000000..293cbc014
--- /dev/null
+++ b/Source/DOH2/Makefile
@@ -0,0 +1,12 @@
+SRCS=doh.cpp string.cpp list.cpp hash.cpp file.cpp fio.cpp test.cpp
+OBJS=doh.o string.o list.o hash.o file.o fio.o test.o
+
+CXXFLAGS=-ggdb3 -O0
+
+run_test: test
+ ./test
+
+test: $(OBJS)
+ $(CXX) -ggdb3 -O0 -o test $(OBJS)
+
+
diff --git a/Source/DOH2/doh.cxx b/Source/DOH2/doh.cxx
new file mode 100644
index 000000000..d8501ec98
--- /dev/null
+++ b/Source/DOH2/doh.cxx
@@ -0,0 +1,380 @@
+#include <string>
+#include <list>
+#include <iostream>
+#include <cassert>
+#include <exception>
+#include "doh.h"
+
+namespace doh {
+
+ /* class DOH */
+ DOH::DOH()
+ : _line(0), _file(0), meta(0)
+ {}
+
+ DOH::DOH(const DOH &x)
+ : _line(x._line), _file(x._file),
+ meta(x.meta->clone())
+ {}
+
+ DOH::~DOH() {
+ if (meta)
+ delete meta;
+ }
+
+ void DOH::clear() {
+ if (meta)
+ delete meta;
+ meta = 0;
+ _line = 0;
+ _file = 0;
+ return;
+ }
+
+ void DOH::line(int l) {
+ _line = l;
+ }
+
+ int DOH::line() {
+ return _line;
+ }
+
+ void DOH::file(DOH *f) {
+ _file = f;
+ }
+
+ DOH *DOH::file() {
+ return _file;
+ }
+
+ void DOH::setmeta(DOH *name, DOH *value) {
+ String &namestr = ref_cast<String>(name);
+ if (0==meta)
+ meta = new Hash;
+ Hash &ho = *doh_cast<Hash*>(meta);
+ ho[namestr] = value;
+ }
+
+ DOH *DOH::getmeta(DOH *name) {
+ String &namestr = ref_cast<String>(name);
+ if (0==meta)
+ return 0;
+ Hash &ho = ref_cast<Hash>(meta);
+ if (ho.count(namestr) > 0)
+ return ho[namestr];
+ else
+ return 0;
+ }
+
+ /* class Filelike */
+ Filelike::Filelike()
+ {}
+
+ Filelike::Filelike(const Filelike& f)
+ :DOH(f)
+ {}
+
+
+ /* class Container */
+ Container::Container()
+ {}
+ Container::Container(const Container &x)
+ :DOH(x)
+ {}
+
+ /* class _Iterator */
+ _Iterator::~_Iterator() {
+ }
+
+ /* struct Iterator */
+ Iterator::~Iterator() {
+ }
+
+ /* class DOHCaster */
+
+ DOHCaster::DOHCaster(DOH *obj)
+ :content(obj)
+ {}
+
+ DOHCaster::operator DOH* () {
+ return to_ptr<DOH>();
+ }
+
+ DOHCaster::operator const char* () {
+ return to_ptr<String>()->c_str();
+ }
+
+ DOHCaster::operator String* () {
+ return to_ptr<String>();
+ }
+
+ DOHCaster::operator List* () {
+ return to_ptr<List>();
+ }
+
+ template<class T>
+ T* DOHCaster::to_ptr() const {
+ return dynamic_cast<T*>(content);
+ }
+
+
+ /* class String_or_char_ptr */
+
+ String_or_char_ptr::String_or_char_ptr(const String_or_char_ptr& str)
+ :content_str(str.content_str),
+ content_charptr(str.content_charptr),
+ need_free(0) /* TODO: may potential memory leak/corrupt here */
+ {}
+
+ String_or_char_ptr::~String_or_char_ptr() {
+ if (need_free) {
+ delete content_str;
+ }
+ }
+
+ // Casters
+ // from const char*
+ String_or_char_ptr::String_or_char_ptr(const char *s)
+ :content_str(0), content_charptr(s),
+ need_free(false)
+ {}
+ // from DOH*
+ String_or_char_ptr::String_or_char_ptr(const DOH* str)
+ :content_str(dynamic_cast<const String*>(str)),
+ content_charptr(0),
+ need_free(false)
+ {}
+ // to const char*
+ String_or_char_ptr::operator const char* () const {
+ return content_charptr ? content_charptr : content_str->c_str();
+ }
+ // to const String*
+ String_or_char_ptr::operator const String* () const {
+ if (!content_str) {
+ content_str = new String(content_charptr);
+ need_free = true;
+ }
+ return content_str;
+ }
+
+ /* wrapper of dynamic_cast with error detection */
+ template<class T>
+ T doh_cast(DOH *obj) {
+ // TODO: raise exception
+ T result = dynamic_cast<T>(obj);
+ assert(result);
+ return result;
+ }
+
+ template<class T>
+ T doh_cast(const DOH *obj) {
+ T result = dynamic_cast<T>(obj);
+ assert(result);
+ return result;
+ }
+
+ /* shortcut which cast DOH object pointer to reference */
+ template<class T>
+ T& ref_cast(DOH *obj) {
+ return *doh_cast<T*>(obj);
+ }
+
+
+ /* Basic object methods */
+ int DohCheck(const DOH *ptr) {
+ if (ptr)
+ return true;
+ else
+ return false;
+ }
+
+ int Len(const DOH* obj) {
+ return obj->size();
+ }
+
+ DOHCaster Copy(const DOH* obj) {
+ return obj->clone();
+ }
+
+ void Clear(DOH *obj) {
+ obj->clear();
+ }
+
+ void Delete(DOH *obj) {
+ delete obj;
+ return;
+ }
+
+ /* Positional */
+
+ int Getline(DOH *obj) {
+ return obj->line();
+ }
+ void Setline(DOH *obj, int line) {
+ obj->line(line);
+ }
+
+ DOH *Getfile(DOH *obj) {
+ return obj->file();
+ }
+
+ void Setfile(DOH *obj, DOH *file) {
+ return obj->file(file);
+ }
+
+
+
+ /* Common methods for List and String */
+ int Dump(const DOH *obj, DOH *out) {
+ // XXX only support string dump
+ const String *so = doh_cast<const String*>(obj);
+ Write(out, so->data(), so->size());
+ }
+
+
+ int Insertitem(DOH *obj, int index, DOH *value) {
+ int len = obj->size();
+ if (DOH_END == index) {
+ index = len;
+ }
+ if (index < 0) {
+ index = 0;
+ }
+ if (index > len) {
+ index = len;
+ }
+
+ if (dynamic_cast<List*>(obj)) {
+ /* is List */
+ List *lo = doh_cast<List*>(obj);
+ lo->insert(index, value);
+ } else {
+ /* is String */
+ String *so = doh_cast<String*>(obj);
+ String &str = ref_cast<String>(value);
+ so->insert(index,str);
+ }
+ return 0;
+ }
+
+ int Append(DOH *x, DOH *item) {
+ if (!item)
+ return -1;
+ if (dynamic_cast<List*>(x)) {
+ /* the object is a list */
+ List *lo = doh_cast<List*>(x);
+ lo->push_back(item);
+ } else {
+ /* otherwise it is string */
+ String *so = doh_cast<String*>(x);
+ String &str = ref_cast<String>(item);
+ so->append(str);
+ }
+ return 0;
+ }
+
+ int Delslice(DOH *obj, int sindex, int eindex) {
+ int len = obj->size();
+ if (eindex == DOH_END)
+ eindex = len;
+ if (sindex == DOH_BEGIN)
+ sindex = 0;
+
+ if (dynamic_cast<List*>(obj)) {
+ /* is List */
+ List *lo = doh_cast<List*>(obj);
+ lo->erase(sindex, eindex - sindex);
+ } else {
+ /* is String */
+ String *so = doh_cast<String*>(obj);
+ so->erase(sindex, eindex - sindex);
+ }
+ return 0;
+ }
+
+ int Delitem(DOH *obj, int index) {
+ int len = obj->size();
+ if (index == DOH_END)
+ index = len-1;
+ if (index == DOH_BEGIN)
+ index = 0;
+ if (len == 0)
+ return 0;
+ return Delslice(obj, index, index+1);
+ }
+
+ /* Common methods for String and File */
+ int Write(DOH * obj, const char *buffer, int length) {
+ Filelike *fo = doh_cast<Filelike*>(obj);
+ return fo->write(buffer, length);
+ }
+
+ int Read(DOH * obj, char *buffer, int length) {
+ Filelike *fo = doh_cast<Filelike*>(obj);
+ return fo->read(buffer, length);
+ }
+
+ int Seek(DOH * obj, long offset, int whence) {
+ Filelike *fo = doh_cast<Filelike*>(obj);
+ return fo->seek(offset, whence);
+ }
+
+ long Tell(DOH * obj) {
+ Filelike *fo = doh_cast<Filelike*>(obj);
+ return fo->tell();
+ }
+
+ int Getc(DOH * obj) {
+ Filelike *fo = doh_cast<Filelike*>(obj);
+ return fo->getc();
+ }
+
+ int Putc(int ch, DOH * obj) {
+ Filelike *fo = doh_cast<Filelike*>(obj);
+ return fo->putc(ch);
+ }
+
+ int Ungetc(int ch, DOH * obj) {
+ Filelike *fo = doh_cast<Filelike*>(obj);
+ return fo->ungetc(ch);
+ }
+
+
+ /* Iterator */
+ Iterator First(DOH *obj) {
+ Container *cont = dynamic_cast<Container*>(obj);
+ assert(cont);
+ return cont->first();
+ }
+
+ Iterator& Next(Iterator& x) {
+ Container *cont = dynamic_cast<Container*>(x.object);
+ assert(cont);
+ return cont->next(x);
+ }
+
+ /* Miscellaneous */
+
+ int DohIsMapping(const DOH *obj) {
+ const Hash* o = dynamic_cast<const Hash*>(obj);
+ return o ? true : false;
+ }
+
+ int DohIsSequence(const DOH *obj) {
+ const List* o = dynamic_cast<const List*>(obj);
+ return o ? true : false;
+ }
+
+ int DohIsString(const DOH *obj) {
+ const String* o = dynamic_cast<const String*>(obj);
+ return o ? true : false;
+ }
+
+ int DohIsFile(const DOH *obj) {
+ const Filelike* o = dynamic_cast<const Filelike*>(obj);
+ return o ? true : false;
+ }
+
+}
+
+
diff --git a/Source/DOH2/doh.h b/Source/DOH2/doh.h
new file mode 100644
index 000000000..6bcc47251
--- /dev/null
+++ b/Source/DOH2/doh.h
@@ -0,0 +1,513 @@
+/*
+ * This file is part of SWIG.
+ *
+ * SWIG is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SWIG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SWIG. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _DOH_H
+#define _DOH_H
+
+#include <string>
+#include <list>
+#include <map>
+#include <fstream>
+
+/* Problems need to be solved:
+ *
+ * 1. String_or_char *: find a replacement so foo(String_or_char * c) works.
+ *
+ * 2. List and Hash require the ability to contain any DOH objects
+ * (No longer require things like boost::any!)
+ * All DOH types inherit from DOH
+ *
+ * 3. Auto cast return value to String* or List* etc. (for Getattr())
+ * Casters.
+ * All casters storage content as DOH*
+ * StringCaster : cast from const char*, std::string, String*
+ * to const char*, std::string&, String*
+ * DohCaster : StringCaster adds caster for List* and Hash*
+ *
+ * 4. Extra data attached to each object (file, line, meta)
+ * In DOH
+ *
+ * 5. Keep the DOH iterator interface
+ *
+ * 6. Co-operating with STL
+ *
+ * 7. DOH String is file-like
+ *
+ * 8. varargs
+ *
+ *
+ * Core types:
+ * String, List, Mapping, File, Iterator
+ */
+
+namespace doh {
+ /* Base class for DOH types */
+ class DOH {
+ public:
+ DOH();
+ DOH(const DOH &x);
+ virtual ~DOH();
+
+ virtual DOH *clone() const = 0;
+ virtual void clear();
+ virtual int size() const = 0;
+
+ void line(int l);
+ int line();
+ void file(DOH *f);
+ DOH *file();
+ void setmeta(DOH *name, DOH *value);
+ DOH *getmeta(DOH *name);
+
+ protected:
+ DOH *meta;
+ int _line;
+ DOH *_file;
+ };
+
+ /* Interface for file-like objects (String and File) */
+ class Filelike : public DOH {
+ public:
+ Filelike();
+ Filelike(const Filelike& f);
+
+ virtual int write(const char *buffer, size_t length) = 0;
+ virtual int read(char *buffer, size_t length) = 0;
+ virtual int seek(off_t offset, int whence) = 0;
+ virtual off_t tell() = 0;
+ virtual char getc() = 0;
+ virtual char putc(char c) = 0;
+ virtual char ungetc(char ch) = 0;
+ };
+
+ class String : public Filelike, public std::string {
+ public:
+ /* Constructors */
+ String();
+ String(const String& str);
+ String(const std::string& str);
+ String(const char *s);
+ String(const char *s, size_t n);
+
+ virtual DOH *clone() const;
+ virtual void clear();
+ virtual int size() const;
+
+ virtual int write(const char *buffer, size_t length);
+ virtual int read(char *buffer, size_t length);
+ virtual int seek(off_t offset, int whence);
+ virtual off_t tell();
+ virtual char getc();
+ virtual char putc(char c);
+ virtual char ungetc(char ch);
+
+ int doh_replace(const char *token, const char *rep, int flags);
+
+ /*TODO: override all modifiers of std::string
+ * to keep sp always at correct position
+ */
+ String& insert(size_t pos, const std::string &str);
+ String& erase(size_t pos, size_t n);
+
+ private:
+ off_t sp;
+ };
+
+ /* XXX Now we uses cstdio for file I/O, may switch to fstream */
+ //class File : public Filelike, public std::fstream {
+ class File : public Filelike {
+ public:
+ /* Constructors */
+ File();
+ File(const File &f);
+ File(const char *filename, const char *mode);
+
+ virtual DOH *clone() const;
+ virtual void clear();
+ virtual int size() const;
+
+ virtual int write(const char *buffer, size_t length);
+ virtual int read(char *buffer, size_t length);
+ virtual int seek(off_t offset, int whence);
+ virtual off_t tell();
+ virtual char getc();
+ virtual char putc(char c);
+ virtual char ungetc(char ch);
+ private:
+ FILE *fp;
+ };
+
+ /* Iterator */
+
+ /* class _Iterator, internal use for containers */
+ class _Iterator {
+ public:
+ virtual ~_Iterator();
+ };
+
+ /* Public iterator */
+ struct Iterator {
+ /* XXX key should be DOH*, but have to be
+ * const char * to prevent memory leak */
+ const char * key;
+ DOH* item;
+ DOH* object;
+ _Iterator *_iter;
+ ~Iterator();
+ };
+
+ class Container : public DOH {
+ public:
+ Container();
+ Container(const Container &x);
+ virtual Iterator first() = 0;
+ virtual Iterator& next(Iterator& i) = 0;
+ };
+
+ /* TODO containers must have own copy of contained objects */
+
+ typedef std::list<DOH*> list_doh;
+ class List : public Container, public list_doh {
+ public:
+ /* Constructors */
+ List();
+ List(const List &x);
+
+ virtual DOH *clone() const;
+ virtual void clear();
+ virtual int size() const;
+
+ virtual Iterator first();
+ virtual Iterator& next(Iterator& i);
+
+ void insert(size_t pos, DOH *x);
+ void erase(size_t pos, size_t n);
+ private:
+ //Internal iterator for List
+ class _iterator;
+ //Check and set state of iterator
+ void check_iter(Iterator &i);
+ };
+
+ typedef std::map<std::string, DOH*> map_doh;
+ class Hash : public Container, public map_doh {
+ public:
+ /* Constructors */
+ Hash();
+ /* Copy constructor */
+ Hash(const Hash &x);
+ virtual DOH *clone() const;
+ virtual void clear();
+ virtual int size() const;
+
+ virtual Iterator first();
+ virtual Iterator& next(Iterator& i);
+ private:
+ //Internal iterator for Hash
+ class _iterator;
+ //Check and set state of iterator
+ void check_iter(Iterator &i);
+ };
+
+
+ /* Caster */
+ class DOHCaster {
+ public:
+ // from DOH*
+ DOHCaster(DOH *obj);
+ // to DOH*
+ operator DOH* ();
+ // to const char*
+ operator const char* ();
+ // to String*
+ operator String* ();
+ // to List*
+ operator List* ();
+ // to Hash*
+ operator Hash* ();
+
+ private:
+ template<class T>
+ T* to_ptr() const;
+
+ DOH * const content;
+ };
+
+ /* wrapper of dynamic_cast with error detection */
+ template<class T>
+ T doh_cast(DOH *obj);
+
+ template<class T>
+ const T constdoh_cast(const DOH *obj);
+
+ /* shortcut which cast DOH object pointer to reference */
+ template<class T>
+ T& ref_cast(DOH *obj);
+
+ /* This class should only be used as
+ * function input argument type.
+ * It is the equivalence of
+ * const String_or_char *
+ */
+ class String_or_char_ptr {
+ public:
+ // Copy constructor
+ String_or_char_ptr(const String_or_char_ptr& str);
+ // Destructor
+ ~String_or_char_ptr();
+
+ /* Casters */
+ // from const char*
+ String_or_char_ptr(const char *s);
+ // from DOH*
+ String_or_char_ptr(const DOH* str);
+ // to const char*
+ operator const char* () const;
+ // to const String*
+ operator const String* () const;
+
+ private:
+ mutable bool need_free;
+ mutable const String *content_str;
+ const char *content_charptr;
+ };
+
+ /* -----------------------------------------------------------------------------
+ * Our own varargs mechanism, so Printf and Stringf works.
+ * This varargs implementation convert any DOH object to POD,
+ * and then store it in a union.
+ * -----------------------------------------------------------------------------*/
+ union vararg_item {
+ int _int;
+ double _double;
+ const char *_str;
+ void *_pointer;
+
+ inline vararg_item(doh::DOH *obj)
+ : _str(doh::doh_cast<String*>(obj)->c_str())
+ {}
+ inline vararg_item(const char *c)
+ : _str(c)
+ {}
+ inline vararg_item(int i)
+ : _int(i)
+ {}
+
+ inline vararg_item(double d)
+ : _double(d)
+ {}
+
+ inline vararg_item(void *p)
+ : _pointer(p)
+ {}
+ };
+
+#define VA_DECL vararg_item varg_0 = 0, \
+ vararg_item varg_1 = 0, \
+ vararg_item varg_2 = 0, \
+ vararg_item varg_3 = 0, \
+ vararg_item varg_4 = 0
+
+#define VA_DEF vararg_item varg_0, \
+ vararg_item varg_1, \
+ vararg_item varg_2, \
+ vararg_item varg_3, \
+ vararg_item varg_4
+#define VA_CALL varg_0, varg_1, varg_2, varg_3, varg_4
+#define VA_INIT int _varg_index = 0; \
+ vararg_item _varg_items[] = {VA_CALL};
+#define VA_GET (_varg_items[_varg_index++])
+
+
+
+ /* Basic object methods. Common to most objects */
+ int DohCheck(const DOH *ptr); /* Check if a DOH object */
+ void Delete(DOH *obj);
+ DOHCaster Copy(const DOH* obj); /* Shallow copy. Copy meta, file, line */
+ void Clear(DOH *obj);
+ String *Str(const DOH *obj); // Rare
+ void *Data(const DOH *obj); // Rare: only swig/typesys.c:1867
+ int Dump(const DOH *obj, DOH *out);
+ int Len(const DOH* obj);
+ /* Cmp removed to string method section */
+ int Hashval(const DOH *obj); // Never
+ void DohIncref(DOH *obj); //Rare. Is it really useful?
+
+ /* Mapping methods */
+ //XXX Removed all the const qulifier of 'DOH *value' argument
+ DOHCaster Getattr(DOH *obj, const String_or_char_ptr name);
+ int Setattr(DOH *obj, const String_or_char_ptr name, const char *value); // Overloaded
+ int Setattr(DOH *obj, const String_or_char_ptr name, DOH *value);
+ int Checkattr(DOH *obj, const String_or_char_ptr name, const String_or_char_ptr value);
+ DOHCaster Keys(DOH *obj);
+ int GetInt(DOH *obj, const String_or_char_ptr name);
+ void SetInt(DOH *obj, const String_or_char_ptr name, int value);
+ #define DohSetInt SetInt
+ double GetDouble(DOH *obj, const String_or_char_ptr name); // Never
+ double SetDouble(DOH *obj, const String_or_char_ptr name, double); // Never
+ char *GetChar(DOH *obj, const String_or_char_ptr name); // These are redundant
+ void SetChar(DOH *obj, const DOH *name, char *value);
+ DOHCaster GetFlagAttr(DOH *obj, const String_or_char_ptr name);
+ int GetFlag(DOH *obj, const String_or_char_ptr name);
+ void SetFlagAttr(DOH *obj, const String_or_char_ptr name, DOH *attr); // Rare
+ void SetFlag(DOH *obj, const String_or_char_ptr name);
+ void GetVoid(DOH *obj, const String_or_char_ptr name); // Rare, unable to support. Modules/allegrocl.cxx
+ void *SetVoid(DOH *obj, const String_or_char_ptr name, void *value);
+ #define UnsetFlag(o,n) SetFlagAttr(o,n,NULL)
+
+ /* Sequence methods */
+ DOHCaster Getitem(DOH *obj, int index);
+ int Setitem(DOH *obj, int index, DOH *value); // overloaded
+ int Setitem(DOH *obj, int index, const char *value);
+ int Delitem(DOH *obj, int index);
+ int Insertitem(DOH *obj, int index, DOH *value); // overloaded
+ int Insertitem(DOH *obj, int index, const char *value);
+ int Delslice(DOH *obj, int sindex, int eindex);
+ int Append(DOH *x, DOH *item); // was a macro
+ #define Insert DohInsertitem
+// #define Append(s,x) DohInsertitem(s,DOH_END,x)
+ #define Push(s,x) DohInsertitem(s,DOH_BEGIN,x)
+
+ /* Sequence position flags */
+ #define DOH_BEGIN -1
+ #define DOH_END -2
+ #define DOH_CUR -3
+ #define DOH_CURRENT -3
+
+ /* File methods */
+
+ int Write(DOH * obj, const char *buffer, int length);
+ int Read(DOH * obj, char *buffer, int length);
+ int Seek(DOH * obj, long offset, int whence);
+ long Tell(DOH * obj);
+ int Getc(DOH * obj);
+ int Putc(int ch, DOH * obj);
+ int Ungetc(int ch, DOH * obj);
+
+ /* Iterator */
+ Iterator First(DOH *obj);
+ Iterator& Next(Iterator& x);
+
+ /* Positional */
+
+ int Getline(DOH *obj);
+ void Setline(DOH *obj, int line);
+ DOH *Getfile(DOH *obj);
+ void Setfile(DOH *obj, DOH *file);
+
+ /* String Methods */
+ int Cmp(String_or_char_ptr obj1, String_or_char_ptr obj2);
+ int Equal(const String_or_char_ptr obj1, const String_or_char_ptr obj2);
+ int Replace(DOH * src, const String_or_char_ptr token, const String_or_char_ptr rep, int flags);
+ void Chop(DOH * src);
+
+ /* Meta-variables */
+ DOH *Getmeta(DOH *obj, const DOH *name);
+ int Setmeta(DOH *obj, const DOH *name, const DOH *value);
+ int Delmeta(DOH *obj, const DOH *name);
+
+ /* Utility functions */
+
+ void DohEncoding(char *name, DOH *(*fn) (DOH *s));
+ int Printf(DOH * obj, const char *format, VA_DECL);
+ int Printf(FILE *obj, const char *format, VA_DECL);
+ int vPrintf(DOH * obj, const char *format, VA_DECL);
+ int Printv(DOH * obj, VA_DECL);
+ int Printv(FILE * obj, VA_DECL);
+ DOH *Readline(DOH * in); // Never
+
+ /* Miscellaneous */
+
+ int DohIsMapping(const DOH *obj);
+ int DohIsSequence(const DOH *obj);
+ int DohIsString(const DOH *obj);
+ int DohIsFile(const DOH *obj);
+
+ void DohSetmark(DOH *obj, int x);
+ int DohGetmark(DOH *obj);
+
+ /* -----------------------------------------------------------------------------
+ * Strings.
+ * ----------------------------------------------------------------------------- */
+
+ String *NewStringEmpty(void);
+ String *NewString(String_or_char_ptr c);
+ String *NewStringWithSize(const String_or_char_ptr c, int len);
+ String *NewStringf(const String_or_char_ptr fmt, VA_DECL);
+
+ const char *Char(const String_or_char_ptr s);
+
+ int Strcmp(const String_or_char_ptr s1, const String_or_char_ptr s2);
+ int Strncmp(const String_or_char_ptr s1, const String_or_char_ptr s2, int n);
+ const char *Strstr(const String_or_char_ptr s1, const String_or_char_ptr s2);
+ const char *Strchr(const String_or_char_ptr 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) Replace(s,t,r,DOH_REPLACE_ANY)
+ #define Replaceid(s,t,r) Replace(s,t,r,DOH_REPLACE_ID)
+
+
+ /* -----------------------------------------------------------------------------
+ * Files
+ * ----------------------------------------------------------------------------- */
+
+ DOH *NewFile(DOH *filename, const char *mode, DOH *outfiles);
+ DOH *NewFileFromFile(FILE *f); // Never
+ DOH *NewFileFromFd(int fd); // Never
+ void FileErrorDisplay(DOH *filename);
+ int Close(DOH *file);
+ int Copyto(DOH *input, DOH *output); // Never
+
+ /* -----------------------------------------------------------------------------
+ * List
+ * ----------------------------------------------------------------------------- */
+
+ List *NewList();
+ //void SortList(DOH *lo, int (*cmp) (const DOH *, const DOH *));
+ void SortList(DOH *lo, int (*cmp)
+ (const String_or_char_ptr, const String_or_char_ptr));
+
+ /* -----------------------------------------------------------------------------
+ * Hash
+ * ----------------------------------------------------------------------------- */
+
+ Hash *NewHash(void);
+
+ /* -----------------------------------------------------------------------------
+ * Void
+ * ----------------------------------------------------------------------------- */
+
+ DOH *DohNewVoid(void *ptr, void (*del) (void *)); // Never
+ List *Split(DOH *input, char ch, int nsplits);
+ List *SplitLines(DOH *input);
+ #define DohSplitLines(x) SplitLines(x)
+ #define DohNone 0
+
+ extern void DohMemoryDebug(void);
+
+
+}
+
+#endif /* DOH_H */
diff --git a/Source/DOH2/file.cxx b/Source/DOH2/file.cxx
new file mode 100644
index 000000000..457b24bea
--- /dev/null
+++ b/Source/DOH2/file.cxx
@@ -0,0 +1,83 @@
+/*
+ * This file is part of SWIG.
+ *
+ * SWIG is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SWIG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SWIG. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "doh.h"
+#include <cstdarg>
+#include <cstdio>
+#include <cassert>
+namespace doh {
+
+ /* class File */
+
+ /* Constructors */
+ File::File()
+ {}
+
+ File::File(const File& f)
+ : Filelike(f), fp(f.fp)
+ {}
+
+ File::File(const char * filename, const char *mode)
+ : fp(fopen(filename, mode))
+ {}
+
+ /* inherit from DOH */
+ DOH* File::clone() const {
+ return new File(*this);
+ }
+
+ void File::clear() {
+ /* XXX should we have clear()? */
+ DOH::clear();
+ return;
+ }
+
+ int File::size() const {
+ /* XXX no size() operation */
+ return 0;
+ }
+
+ int File::write(const char *buffer, size_t length) {
+ return fwrite(buffer, 1, length, fp);
+ }
+
+ int File::read(char *buffer, size_t length) {
+ return fread(buffer, 1, length, fp);
+ }
+
+ int File::seek(off_t offset, int whence) {
+ return fseek(fp, offset, whence);
+ }
+
+ off_t File::tell() {
+ return ftell(fp);
+ }
+
+ char File::getc() {
+ return fgetc(fp);
+ }
+
+ char File::putc(char c) {
+ return fputc(c, fp);
+ }
+
+ char File::ungetc(char ch) {
+ return std::ungetc(ch, fp);
+ }
+
+
+}
diff --git a/Source/DOH2/fio.cxx b/Source/DOH2/fio.cxx
new file mode 100644
index 000000000..b7b3a026f
--- /dev/null
+++ b/Source/DOH2/fio.cxx
@@ -0,0 +1,623 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ * ----------------------------------------------------------------------------- */
+
+#include "doh.h"
+#include <map>
+#include <string>
+#include <cstring>
+#include <cstdarg>
+#include <cstdlib>
+using namespace std;
+namespace doh {
+#define OBUFLEN 512
+
+typedef DOH *(*encoding_fn) (DOH *s);
+typedef map<std::string, encoding_fn> encoding_map;
+
+static encoding_map *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 = new encoding_map();
+ (*encodings)[name] = fn;
+ //Setattr(encodings, (void *) name, NewVoid((void *) fn, 0));
+}
+
+/* internal function for processing an encoding */
+static DOH *encode(char *name, DOH *s) {
+ DOH *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))) {
+ if (!encodings || encodings->count(name)) {
+ return Copy(s);
+ } else {
+ fn = (*encodings)[name];
+ }
+ 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 vPrintf(DOH *so, const char *format, VA_DEF) {
+ static const 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;
+
+ VA_INIT;
+
+ 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_GET._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_GET._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 */
+ const char *str;
+ DOH *Sval;
+ DOH *enc = 0;
+ str = VA_GET._str;
+ /* 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 *) malloc(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) {
+ free(stemp);
+ }
+ } else */ {
+ //if (!doh)
+ // doh = (char *) "";
+
+ if (strlen(encoder)) {
+ //DOH *s = NewString(doh);
+ DOH *s = NewString(str);
+ Seek(s, 0, SEEK_SET);
+ enc = encode(encoder, s);
+ Delete(s);
+ str = Char(enc);
+ } else {
+ enc = 0;
+ }
+ maxwidth = maxwidth + strlen(newformat) + strlen((char *) str);
+ *(fmt++) = 's';
+ *fmt = 0;
+ if ((maxwidth + 1) < OBUFLEN) {
+ stemp = obuffer;
+ } else {
+ stemp = (char *) malloc(maxwidth + 1);
+ }
+ nbytes += sprintf(stemp, newformat, str);
+ if (Writen(so, stemp, strlen(stemp)) < 0)
+ return -1;
+ if (stemp != obuffer) {
+ free(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 *) malloc(maxwidth + 1);
+ switch (*p) {
+ case 'd':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ case 'c':
+ ivalue = VA_GET._int; //va_arg(ap, int);
+ nbytes += sprintf(stemp, newformat, ivalue);
+ break;
+ case 'f':
+ case 'g':
+ case 'e':
+ case 'E':
+ case 'G':
+ dvalue = VA_GET._double; //va_arg(ap, double);
+ nbytes += sprintf(stemp, newformat, dvalue);
+ break;
+ case 'p':
+ pvalue = VA_GET._pointer; //va_arg(ap, void *);
+ nbytes += sprintf(stemp, newformat, pvalue);
+ break;
+ default:
+ break;
+ }
+ if (Writen(so, stemp, strlen(stemp)) < 0)
+ return -1;
+ if (stemp != obuffer)
+ free(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 Printf(DOH *obj, const char *format, VA_DEF) {
+ int ret;
+ ret = vPrintf(obj, format, VA_CALL);
+ return ret;
+}
+
+int Printf(FILE *f, const char *format, VA_DEF) {
+ int ret;
+ String *tmp = NewStringEmpty();
+ ret = vPrintf(tmp, format, VA_CALL);
+ fprintf(f, tmp->c_str());
+ Delete(tmp);
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohPrintv()
+ *
+ * Print a null-terminated variable length list of DOH objects
+ * ----------------------------------------------------------------------------- */
+
+int Printv(DOH * obj, VA_DEF) {
+ int ret = 0;
+ const char *str;
+ VA_INIT;
+
+ while (1) {
+ /* Always assume const char* */
+ str = VA_GET._str;
+ if ((!str) || (str == DohNone))
+ break;
+ ret += Write(obj, str, strlen(str));
+ }
+ return ret;
+}
+
+int Printv(FILE * f, VA_DEF) {
+ int ret = 0;
+ const char *str;
+ VA_INIT;
+
+ while (1) {
+ /* Always assume const char* */
+ str = VA_GET._str;
+ if ((!str) || (str == DohNone))
+ break;
+ ret += fwrite(str, 1, strlen(str), f);
+ }
+ 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.
+ * ----------------------------------------------------------------------------- */
+
+List *Split(DOH *in, char ch, int nsplits) {
+ List *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.
+ * ----------------------------------------------------------------------------- */
+
+List *SplitLines(DOH *in) {
+ List *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 *Readline(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++;
+ }
+}
+
+} /* namespace doh */
diff --git a/Source/DOH2/hash.cxx b/Source/DOH2/hash.cxx
new file mode 100644
index 000000000..f519ee902
--- /dev/null
+++ b/Source/DOH2/hash.cxx
@@ -0,0 +1,174 @@
+/*
+ * This file is part of SWIG.
+ *
+ * SWIG is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SWIG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SWIG. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "doh.h"
+#include <cassert>
+#include <cstdlib>
+namespace doh {
+ /* class Hash */
+ /* Constructors */
+ Hash::Hash() {
+ }
+
+ Hash::Hash(const Hash &x)
+ : Container(x), map_doh(x)
+ {}
+
+ /* inherit from DOH */
+ DOH *Hash::clone() const {
+ return new Hash(*this);
+ }
+
+ void Hash::clear() {
+ map_doh::clear();
+ DOH::clear();
+ }
+
+ int Hash::size() const {
+ return map_doh::size();
+ }
+
+ /* internal iterator for Hash */
+ class Hash::_iterator
+ : public _Iterator, public map_doh::iterator {
+ public:
+ _iterator(const map_doh::iterator& i)
+ :map_doh::iterator(i)
+ {}
+ virtual ~_iterator() {
+ }
+ };
+
+
+ /* inherit from Container */
+ Iterator Hash::first() {
+ Iterator i;
+ /* XXX potential memory leak since we only
+ * delete i._iter when the iterator reached
+ * its end. */
+ i._iter = new _iterator(begin());
+ i.object = this;
+ check_iter(i);
+ return i;
+ }
+ Iterator& Hash::next(Iterator& i) {
+ _iterator* _i = dynamic_cast<_iterator*>(i._iter);
+ ++(*_i);
+ check_iter(i);
+ }
+
+ // Check and set state of iterator
+ void Hash::check_iter(Iterator &i) {
+ _iterator* _i = dynamic_cast<_iterator*>(i._iter);
+ if (0==_i)
+ return;
+ if (end() != *_i) {
+ i.key = (**_i).first.c_str();
+ i.item = (**_i).second;
+ } else {
+ i.key = 0;
+ i.item = 0;
+ delete i._iter;
+ i._iter = 0;
+ }
+ }
+
+ Hash *NewHash(void) {
+ return new Hash();
+ }
+
+ DOHCaster Getattr(DOH *obj, const String_or_char_ptr name) {
+ Hash &ho = ref_cast<Hash>(obj);
+ std::string key(name);
+ if (ho.count(key) > 0)
+ return ho[key];
+ else
+ return 0;
+ }
+
+ int Setattr(DOH *obj, const String_or_char_ptr name, const char *value) {
+ Hash &ho = ref_cast<Hash>(obj);
+ std::string key(name);
+ DOH *so = new String(value);
+ int r = ho.count(key);
+ ho[key] = so;
+ return r;
+ }
+
+ int Setattr(DOH *obj, const String_or_char_ptr name, DOH *value) {
+ Hash &ho = ref_cast<Hash>(obj);
+ std::string key(name);
+ int r = ho.count(key);
+ ho[key] = value;
+ return r;
+ }
+
+ int Checkattr(DOH *obj, const String_or_char_ptr name, const String_or_char_ptr value) {
+ DOH *attr = Getattr(obj, name);
+ if (!attr) return 0;
+ return Equal(doh_cast<String*>(attr), value);
+ }
+
+ DOHCaster Keys(DOH *obj) {
+ Hash &ho = ref_cast<Hash>(obj);
+ List *keys = new List();
+ map_doh::iterator iter = ho.begin();
+ for(;iter!=ho.end(); iter++) {
+ keys->push_back(new String(iter->first));
+ }
+ return keys;
+ }
+
+ int GetInt(DOH *obj, const String_or_char_ptr name) {
+ Hash &ho = ref_cast<Hash>(obj);
+ std::string key(name);
+ if (ho.count(key)>0) {
+ String *val = doh_cast<String*>(ho[key]);
+ return atoi(val->c_str());
+ } else
+ return 0;
+ }
+
+ void SetInt(DOH *obj, const String_or_char_ptr name, int value) {
+ String *val = NewStringEmpty();
+ Printf(val, "%d", value);
+ Setattr(obj, name, val);
+ }
+
+ DOHCaster GetFlagAttr(DOH *obj, const String_or_char_ptr name) {
+ DOH *val = Getattr(obj, name);
+ if (!val) {
+ return 0;
+ } else {
+ String &sval = ref_cast<String>(val);
+ return (sval != "0") ? val : NULL;
+ }
+ }
+
+ int GetFlag(DOH *obj, const String_or_char_ptr name) {
+ return (DOH*) GetFlagAttr(obj, name) ? 1 : 0;
+ }
+
+ void SetFlagAttr(DOH *obj, const String_or_char_ptr name, DOH *attr) {
+ Setattr(obj, name, attr ? attr : NewString("0"));
+ }
+
+ void SetFlag(DOH *obj, const String_or_char_ptr name) {
+ Setattr(obj, name, NewString("1"));
+ }
+
+}
diff --git a/Source/DOH2/list.cxx b/Source/DOH2/list.cxx
new file mode 100644
index 000000000..316b17428
--- /dev/null
+++ b/Source/DOH2/list.cxx
@@ -0,0 +1,125 @@
+/*
+ * This file is part of SWIG.
+ *
+ * SWIG is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SWIG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SWIG. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "doh.h"
+#include <cassert>
+namespace doh {
+
+ /* class List */
+
+ /* Constructors */
+
+ List::List() {
+ }
+
+ List::List(const List &x)
+ :list_doh(x), Container(x)
+ {}
+
+ /* inherit from DOH */
+
+ DOH* List::clone() const {
+ return new List(*this);
+ }
+
+ void List::clear() {
+ list_doh::clear();
+ DOH::clear();
+ return;
+ }
+
+ int List::size() const {
+ return list_doh::size();
+ }
+
+ /* internal iterator for List */
+ class List::_iterator
+ : public _Iterator, public list_doh::iterator {
+ public:
+ _iterator(const list_doh::iterator& i)
+ :list_doh::iterator(i)
+ {}
+ virtual ~_iterator() {
+ }
+ };
+
+ /* inherit from Container */
+
+ Iterator List::first() {
+ Iterator i;
+ /* XXX potential memory leak since we only
+ * delete i._iter when the iterator reached
+ * its end. */
+ i._iter = new _iterator(begin());
+ i.object = this;
+ i.key = 0;
+ check_iter(i);
+ return i;
+ }
+
+ Iterator& List::next(Iterator& i) {
+ _iterator* _i = dynamic_cast<_iterator*>(i._iter);
+ ++(*_i);
+ check_iter(i);
+ return i;
+ }
+
+ void List::check_iter(Iterator& i) {
+ _iterator* _i = dynamic_cast<_iterator*>(i._iter);
+ if (0==_i)
+ return;
+ if (end() != *_i) {
+ i.item = (**_i);
+ } else {
+ i.item = 0;
+ delete i._iter;
+ i._iter = 0;
+ }
+ }
+
+ /* Overloaded for convenience */
+ void List::insert(size_t pos, DOH *x) {
+ iterator iter = begin();
+ while (pos--)
+ iter++;
+ list_doh::insert(iter, x);
+ return;
+ }
+
+ void List::erase(size_t pos, size_t n) {
+ iterator iter = begin();
+ while (pos--)
+ iter++;
+ while (n--)
+ iter = list_doh::erase(iter);
+ return;
+ }
+
+ /* DOH List methods */
+
+ List *NewList() {
+ return new List();
+ }
+
+ void SortList(DOH *lo, int (*cmp) (const String_or_char_ptr, const String_or_char_ptr)) {
+ List *l = doh_cast<List*>(lo);
+ if (!cmp) {
+ cmp = Cmp;
+ }
+ l->sort(cmp);
+ }
+}
diff --git a/Source/DOH2/string.cxx b/Source/DOH2/string.cxx
new file mode 100644
index 000000000..8bed003c1
--- /dev/null
+++ b/Source/DOH2/string.cxx
@@ -0,0 +1,639 @@
+/*
+ * This file is part of SWIG.
+ *
+ * SWIG is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SWIG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SWIG. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "doh.h"
+#include <cstring>
+#include <cstdarg>
+#include <cassert>
+namespace doh {
+
+ /* class String */
+
+ /* Constructors */
+ String::String()
+ : sp(0)
+ {}
+
+ String::String(const String& str)
+ : Filelike(str), std::string(str), sp(str.sp)
+ {}
+
+ String::String(const std::string& str)
+ : Filelike(), std::string(str), sp(0)
+ {}
+
+
+ String::String(const char * s)
+ : std::string(s), sp(0) {
+ }
+
+ String::String(const char *s, size_t n)
+ : std::string(s, n), sp(0) {
+ }
+
+ /* inherit from DOH */
+ DOH* String::clone() const {
+ return new String(*this);
+ }
+
+ void String::clear() {
+ sp = 0;
+ std::string::clear();
+ DOH::clear();
+ return;
+ }
+
+ int String::size() const {
+ return std::string::size();
+ }
+
+ /* inherit from Filelike */
+
+ int String::write(const char *buffer, size_t length) {
+ replace(sp, length, buffer);
+ sp += length;
+ return length;
+ }
+
+ int String::read(char *buffer, size_t length) {
+ size_t readlen;
+ readlen = size() - sp;
+ if (readlen < 0)
+ return 0;
+ if (readlen > length)
+ readlen = length;
+ memmove(buffer, data(), readlen);
+ sp += readlen;
+ return readlen;
+ }
+
+ /* count the occurrence of '\n' in a closed range */
+ static int countline(const char *str, size_t l, size_t r) {
+ register int count = 0;
+ register const char *i = str + l;
+ register const char *rr = str + r;
+ while (i <= rr) {
+ /* XXX In the original DOH there is '++i',
+ * (accutally ++sp and --sp)
+ * but to conform with getc(), it should
+ * be i++. */
+ if (*(i++) == '\n')
+ ++count;
+ }
+ return count;
+ }
+ int String::seek(off_t offset, int whence) {
+ int pos, nsp, inc;
+ int len = size();
+
+ if (whence == SEEK_SET)
+ pos = 0;
+ else if (whence == SEEK_CUR)
+ pos = sp;
+ else if (whence == SEEK_END) {
+ pos = len;
+ offset = -offset;
+ } else
+ pos = sp;
+
+ nsp = pos + offset;
+ if (nsp < 0)
+ nsp = 0;
+ if ( len > 0 && nsp > len)
+ nsp = len;
+
+ /* Set line number */
+ if (sp < nsp)
+ _line += countline(c_str(), sp, nsp-1);
+ else
+ _line -= countline(c_str(), nsp+1, sp);
+
+ sp = nsp;
+ assert( sp >= 0 );
+ return 0;
+ }
+
+ off_t String::tell() {
+ return sp;
+ }
+
+ char String::getc() {
+ char c;
+ if (sp >= size())
+ c = EOF;
+ else
+ c = c_str()[sp++];
+ if (c == '\n')
+ _line++;
+ return c;
+ }
+ char String::putc(char ch) {
+ register int len = size();
+ if (sp < len) {
+ at(sp++) = ch;
+ } else {
+ /* append to tail of the string */
+ push_back(ch);
+ sp++;
+ }
+ return ch;
+ }
+
+ char String::ungetc(char ch) {
+ if (ch == EOF)
+ return ch;
+ if (sp <= 0)
+ return EOF;
+ sp--;
+ if (ch == '\n')
+ _line--;
+ return ch;
+ }
+
+ /* Override std::string methods */
+ String& String::insert(size_t pos, const std::string &str) {
+ size_t len = str.size();
+ std::string::insert(pos, str);
+ if (sp >= pos) {
+ _line += countline(str.c_str(), 0, len-1);
+ sp += len;
+ }
+ return *this;
+ }
+
+ String& String::erase(size_t pos, size_t n) {
+ int eindex = pos + n;
+ int end;
+ /* Adjust file pointer sp and line count */
+ if (sp > pos) {
+ if (sp > eindex) {
+ end = eindex;
+ sp -= n;
+ } else {
+ end = sp;
+ sp = pos;
+ }
+ _line -= countline(c_str(), pos, end-1);
+ }
+ std::string::erase(pos, n);
+ return *this;
+ }
+
+
+ /* DOH String methods */
+
+ String *NewStringEmpty() {
+ return new String();
+ }
+
+ String *NewString(String_or_char_ptr c) {
+ return new String(c);
+ }
+
+ String *NewStringWithSize(const String_or_char_ptr c, int len) {
+ const char *p = c;
+ return new String(c, len);
+ }
+
+ /*XXX const char* fmt is enough */
+ String *NewStringf(const String_or_char_ptr fmt, VA_DEF) {
+ //va_list ap;
+ String *r = new String();
+ const char * fmtstr = fmt;
+ //va_start(ap, fmt);
+ Printf(r, fmtstr, VA_CALL);
+ //va_end(ap);
+ return r;
+ }
+
+ int Cmp(String_or_char_ptr obj1, String_or_char_ptr obj2) {
+ const String *str1 = obj1; // implicit cast
+ const String *str2 = obj2;
+ return str1->compare(*str2);
+ }
+
+ const char *Char(const String_or_char_ptr s) {
+ return s;
+ }
+
+ int Equal(const String_or_char_ptr obj1, const String_or_char_ptr obj2) {
+ return Cmp(obj1, obj2)==0;
+ }
+
+ int Strcmp(const String_or_char_ptr s1, const String_or_char_ptr s2) {
+ const char *c1 = Char(s1);
+ const char *c2 = Char(s2);
+ if (c1 && c2) {
+ return strcmp(c1, c2);
+ } else {
+ return c1 < c2;
+ }
+ }
+
+ int Strncmp(const String_or_char_ptr s1, const String_or_char_ptr s2, int n) {
+ return strncmp(Char(s1), Char(s2), n);
+ }
+ const char *Strstr(const String_or_char_ptr s1, const String_or_char_ptr s2) {
+ const char *p1 = Char(s1);
+ const char *p2 = Char(s2);
+ return p1 == 0 || p2 == 0 || *p2 == '\0' ? p1 : strstr(p1, p2);
+ }
+
+ const char *Strchr(const String_or_char_ptr s1, int ch) {
+ return strchr(Char(s1), ch);
+ }
+
+void Chop(DOH *src) {
+ String &so = ref_cast<String>(src);
+ int len = so.size();
+ int i = len;
+ while (i>0 && isspace(so[i-1])) {
+ i--;
+ }
+ so.erase(i, len-i);
+}
+
+int Replace(DOH * src, const String_or_char_ptr token,
+ const String_or_char_ptr rep, int flags) {
+ String *so = doh_cast<String*>(src);
+ so->doh_replace(token, rep, flags);
+}
+
+
+ /* The powerful DOH string replace function */
+
+ static int replace_simple(char* &str, int &str_len, off_t &str_sp,
+ const char *token, const char *rep, int flags, int count,
+ char *(*match) (char *, char *, const char *, int));
+ static char *match_identifier(char *base, char *s, const char *token, int tokenlen);
+ static char *match_identifier_begin(char *base, char *s, const char *token, int tokenlen);
+ static char *match_identifier_end(char *base, char *s, const char *token, int tokenlen);
+ static char *match_simple(char *base, char *s, const char *token, int tokenlen);
+
+ int String::doh_replace(const char *token, const char *rep, int flags) {
+ int len = size();
+ int count = -1;
+ int ret;
+ char *str = new char[len+1];
+ strcpy(str, c_str());
+ if (flags & DOH_REPLACE_FIRST)
+ count = 1;
+
+ if (flags & DOH_REPLACE_ID_END) {
+ ret = replace_simple(str, len, sp, token, rep, flags, count,
+ match_identifier_end);
+ } else if (flags & DOH_REPLACE_ID_BEGIN) {
+ ret = replace_simple(str, len, sp, token, rep, flags, count,
+ match_identifier_begin);
+ } else if (flags & DOH_REPLACE_ID) {
+ ret = replace_simple(str, len, sp, token, rep, flags, count,
+ match_identifier);
+ } else {
+ ret = replace_simple(str, len, sp, token, rep, flags, count,
+ match_simple);
+ }
+
+ assert(strlen(str)==len);
+ assign(str);
+ delete[] str;
+ /* sp already set since we passed it as reference */
+ return ret;
+ }
+
+
+/* below code is adapted from old DOH */
+
+/* -----------------------------------------------------------------------------
+ * 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, const char *token, int tokenlen) {
+ (void) base;
+ (void) tokenlen;
+ return strstr(s, token);
+}
+
+static char *match_identifier(char *base, char *s, const 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, const 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, const 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(char* &str, int &str_len, off_t &str_sp,
+ const char *token, const char *rep, int flags, int count,
+ char *(*match) (char *, char *, const 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;
+ base = str;
+ tokenlen = strlen(token);
+ s = (*match) (base, base, token, tokenlen);
+
+ if (!s)
+ return 0; /* No matches. Who cares */
+
+
+ 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_len) - s + 1);
+ }
+ } else {
+ t += (c - s);
+ }
+ s = c;
+ ic--;
+ }
+ if (s && delta) {
+ memmove(t, s, (str + str_len) - s + 1);
+ }
+ str_len += expand;
+ 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;
+ newsize = str_len + expand + 1;
+
+ ns = new char[newsize];
+ assert(ns);
+ t = ns;
+ s = first;
+
+ /* Copy the first part of the string */
+ if (first > str) {
+ memcpy(t, str, (first - str));
+ t += (first - 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_len) - s + 1);
+ }
+ s = c;
+ }
+ c = str;
+ str = ns;
+ if (str_sp >= str_len)
+ str_sp += expand;
+ str_len += expand;
+ str[str_len] = 0;
+ //DohFree(c);
+ delete []c;
+ return rcount;
+ }
+}
+
+
+}
diff --git a/Source/DOH2/test.cxx b/Source/DOH2/test.cxx
new file mode 100644
index 000000000..fe0554e44
--- /dev/null
+++ b/Source/DOH2/test.cxx
@@ -0,0 +1,167 @@
+/*
+ * This file is part of SWIG.
+ *
+ * SWIG is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SWIG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SWIG. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "doh.h"
+#include <iostream>
+#include <cstdio>
+#include <cassert>
+/* Test */
+using namespace doh;
+using namespace std;
+
+void say(const String_or_char_ptr str) {
+ const String *s = str;
+ printf(str);
+ return;
+}
+
+void stringtest()
+{
+ /* Basic string test */
+ String *s = new String("Hello world\n");
+ DOH* d = s;
+ String* ss = DOHCaster(d);
+ //cout << ss << endl;
+ say(ss);
+ String *r = new String(" the");
+ Insertitem(s, 5, r);
+ cout << *s;
+ assert(*s=="Hello the world\n");
+ Delslice(s, 6, 10);
+ cout << *s;
+ assert(*s=="Hello world\n");
+ Delitem(s, DOH_END);
+ assert(*s=="Hello world");
+ Clear(s);
+ assert(*s=="");
+ Delete(s);
+
+}
+
+void fiotest()
+{
+ String *s = NewStringf("%d %d %d", 1, 2, 3);
+ cout << *s;
+ Printf(s, "Hello %s\n", "world");
+ cout << *s;
+ Printf(stdout, "(%s)\n", s);
+ Delete(s);
+}
+
+void consttest()
+{
+ /* const test */
+ say("Hello world!\n");
+ const String *cs = NewString("Const world!\n");
+ say(cs);
+}
+
+void listtest()
+{
+ /* Basic list test */
+ List *l = NewList();
+ String *s = NewString("Hello");
+ Append(l, s);
+ Append(l, NewString("World"));
+ Append(l, NewList());
+
+ String *r = dynamic_cast<String*>(l->front());
+ cout << *r <<endl;
+ cout << Len(l) << endl;
+ delete l;
+ }
+
+void itertest()
+ {
+ /* Iterator test */
+ List *l = NewList();
+ String *s = NewString("Hello");
+ Append(l, s);
+ Append(l, NewString(" world"));
+ Append(l, NewString("!\n"));
+ for (Iterator i=First(l); i.item; i=Next(i)) {
+ say(i.item);
+ }
+ Iterator i=First(l);
+ for (; i.item; i=Next(i)) {
+ say(i.item);
+ }
+ }
+
+void filetest() {
+ Printf(stdout, "foo\n");
+ Printf(stderr, "bar %d bar %p\n",0, 0);
+ Printv(stdout, "hello ", "hi ", NULL);
+}
+
+void hashtest() {
+ Hash *h = NewHash();
+ Setattr(h, "hello", "world");
+ String *s = Getattr(h, "hello");
+ String *s2 = Getattr(h, "world");
+ assert(*s=="world");
+ assert(!s2);
+ SetFlag(h, s);
+ assert(GetFlag(h, s));
+}
+
+void chopreplacetest() {
+ String *s = NewString("int abc() \n");
+ Chop(s);
+ assert(*s=="int abc()");
+ Chop(s);
+ assert(*s=="int abc()");
+ Replaceall(s, "int", "long");
+ assert(*s=="long abc()");
+//XXX Replaceall(0, "int", "long");
+}
+
+void splittest() {
+ String *s = NewString("ns:ns2:ns3:ns4");
+ List *l = Split(s, ':', -1);
+ Iterator i=First(l);
+ cout << Len(l) <<endl;
+ for(;i.item;i=Next(i)) {
+ Printf(stdout, "%s\n", i.item);
+ }
+}
+
+void sorttest() {
+ String *s = NewString("5:4:3:2:1:0");
+ List *l = Split(s, ':', -1);
+ SortList(l, 0);
+ Iterator i=First(l);
+ for(;i.item;i=Next(i))
+ Printf(stdout, "%s\n", i.item);
+}
+
+
+int main()
+{
+ stringtest();
+ consttest();
+ listtest();
+ itertest();
+ fiotest();
+ filetest();
+ hashtest();
+ chopreplacetest();
+ splittest();
+ sorttest();
+ return 0;
+}
+