summaryrefslogtreecommitdiff
path: root/src/lib/libast/cdt
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2012-06-24 22:28:35 +0000
committerIgor Pashev <pashev.igor@gmail.com>2012-06-24 22:28:35 +0000
commit3950ffe2a485479f6561c27364d3d7df5a21d124 (patch)
tree468c6e14449d1b1e279222ec32f676b0311917d2 /src/lib/libast/cdt
downloadksh-upstream.tar.gz
Imported Upstream version 93u+upstream
Diffstat (limited to 'src/lib/libast/cdt')
-rw-r--r--src/lib/libast/cdt/cdtlib.h183
-rw-r--r--src/lib/libast/cdt/dtclose.c66
-rw-r--r--src/lib/libast/cdt/dtcomp.c60
-rw-r--r--src/lib/libast/cdt/dtdisc.c91
-rw-r--r--src/lib/libast/cdt/dthash.c431
-rw-r--r--src/lib/libast/cdt/dthdr.h37
-rw-r--r--src/lib/libast/cdt/dtlist.c387
-rw-r--r--src/lib/libast/cdt/dtmethod.c107
-rw-r--r--src/lib/libast/cdt/dtnew.c81
-rw-r--r--src/lib/libast/cdt/dtopen.c177
-rw-r--r--src/lib/libast/cdt/dtstrhash.c61
-rw-r--r--src/lib/libast/cdt/dttree.c696
-rw-r--r--src/lib/libast/cdt/dtview.c157
-rw-r--r--src/lib/libast/cdt/dtwalk.c53
14 files changed, 2587 insertions, 0 deletions
diff --git a/src/lib/libast/cdt/cdtlib.h b/src/lib/libast/cdt/cdtlib.h
new file mode 100644
index 0000000..1972dd2
--- /dev/null
+++ b/src/lib/libast/cdt/cdtlib.h
@@ -0,0 +1,183 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#ifndef _CDTLIB_H
+#define _CDTLIB_H 1
+
+/* cdt library/method implementation header
+** this header is exported to the method libraries
+** Written by Kiem-Phong Vo (5/25/96)
+*/
+
+#if _PACKAGE_ast
+#include <ast.h>
+#if !_BLD_cdt
+#include <dlldefs.h>
+#endif
+#endif
+
+#include <cdt.h>
+#include <unistd.h>
+#include <aso.h>
+
+#include "debug.h"
+
+/* short-hand notations */
+#define NIL(t) ((t)0)
+#define reg register
+
+/* min #bits for a hash table. (1<<this) is table size */
+#define DT_HTABLE 10
+
+/* convenient types */
+#if !defined(uint)
+#define uint unsigned int
+#endif
+#if !defined(uchar)
+#define uchar unsigned char
+#endif
+
+/* This struct holds private method data created on DT_OPEN */
+struct _dtdata_s
+{ unsigned int lock; /* general dictionary lock */
+ Dtuser_t user; /* application's data */
+ unsigned int type; /* method type, control flags */
+ ssize_t size; /* number of objects */
+ Dt_t dict; /* when DT_INDATA is requested */
+};
+
+/* this structure holds the plugin information */
+typedef struct _dtlib_s
+{
+ char* name; /* short name */
+ char* description; /* short description */
+ char* release; /* release info */
+ char* prefix; /* name prefix */
+ Dtmethod_t** methods; /* method list */
+} Dtlib_t;
+
+#if _BLD_cdt
+
+#if defined(__STDC__)
+#define CDTLIB(m) __DEFINE__(Dtmethod_t*,m,&_##m);
+#else
+#define CDTLIB(m) __DEFINE__(Dtmethod_t*,m,&_/**/m);
+#endif
+
+#else
+
+#if defined(__STDC__)
+#define CDTLIB(m) \
+ void* cdt_lib(const char* name, Dtdisc_t* disc, const char* type) \
+ { \
+ int i; \
+ int n; \
+ if (!type) \
+ return &cdt_lib_##m; \
+ n = strlen(cdt_lib_##m.prefix); \
+ if (!strncmp(type, cdt_lib_##m.prefix, n)) \
+ type += n; \
+ for (i = 0; cdt_lib_##m.methods[i]; i++) \
+ if (!strcmp(type, cdt_lib_##m.methods[i]->name + n)) \
+ return cdt_lib_##m.methods[i]; \
+ return 0; \
+ } \
+ unsigned long plugin_version(void) { return CDT_PLUGIN_VERSION; }
+#else
+#define CDTLIB(m) \
+ void* cdt_lib(name, disc, type) const char* name; Dtdisc_t* disc; const char* type; \
+ { \
+ int i; \
+ int n; \
+ if (!type) \
+ return &cdt_lib_/**/m; \
+ n = strlen(cdt_lib_/**/m.prefix); \
+ if (!strncmp(type, cdt_lib_/**/m.prefix, n)) \
+ type += n; \
+ for (i = 0; cdt_lib_/**/m.methods[i]; i++) \
+ if (!strcmp(type, cdt_lib_/**/m.methods[i]->name + n)) \
+ return cdt_lib_/**/m.methods[i]; \
+ return 0; \
+ } \
+ unsigned long plugin_version() { return CDT_PLUGIN_VERSION; }
+#endif
+
+#endif /* _BLD_cdt */
+
+/* these macros lock/unlock dictionaries. DTRETURN substitutes for "return" */
+#define DTSETLOCK(dt) (((dt)->data->type&DT_SHARE) ? asolock(&(dt)->data->lock,1,ASO_SPINLOCK) : 0 )
+#define DTCLRLOCK(dt) (((dt)->data->type&DT_SHARE) ? asolock(&(dt)->data->lock,1,ASO_UNLOCK) : 0 )
+#define DTRETURN(ob,rv) do { (ob) = (rv); goto dt_return; } while(0)
+#define DTERROR(dt, mesg) (!((dt)->disc && (dt)->disc->eventf) ? 0 : \
+ (*(dt)->disc->eventf)((dt),DT_ERROR,(Void_t*)(mesg),(dt)->disc) )
+
+/* announce completion of an operation of type (ty) on some object (ob) in dictionary (dt) */
+#define DTANNOUNCE(dt,ob,ty) ( ((ob) && ((ty)&DT_TOANNOUNCE) && ((dt)->data->type&DT_ANNOUNCE) && \
+ (dt)->disc && (dt)->disc->eventf ) ? \
+ (*(dt)->disc->eventf)((dt), DT_ANNOUNCE|(ty), (ob), (dt)->disc) : 0 )
+
+/* map bits for upward compabitibility */
+#define DTTYPE(dt,ty) ((dt)->typef ? (*(dt)->typef)((dt), (ty)) : (ty) )
+
+/* short-hands for fields in Dtlink_t.
+** note that __hash is used as a hash value
+** or as the position in the parent table.
+*/
+#define _left lh.__left
+#define _hash lh.__hash
+#define _ppos lh.__hash
+
+#define _rght rh.__rght
+#define _ptbl rh.__ptbl
+
+/* tree rotation/linking functions */
+#define rrotate(x,y) ((x)->_left = (y)->_rght, (y)->_rght = (x))
+#define lrotate(x,y) ((x)->_rght = (y)->_left, (y)->_left = (x))
+#define rlink(r,x) ((r) = (r)->_left = (x) )
+#define llink(l,x) ((l) = (l)->_rght = (x) )
+
+#define RROTATE(x,y) (rrotate(x,y), (x) = (y))
+#define LROTATE(x,y) (lrotate(x,y), (x) = (y))
+#define RRSHIFT(x,t) ((t) = (x)->_left->_left, (x)->_left->_left = (t)->_rght, \
+ (t)->_rght = (x), (x) = (t) )
+#define LLSHIFT(x,t) ((t) = (x)->_rght->_rght, (x)->_rght->_rght = (t)->_left, \
+ (t)->_left = (x), (x) = (t) )
+
+_BEGIN_EXTERNS_
+
+#if _BLD_cdt && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern Dtlink_t* _dtmake _ARG_((Dt_t*, Void_t*, int));
+extern void _dtfree _ARG_((Dt_t*, Dtlink_t*, int));
+extern int _dtlock _ARG_((Dt_t*, int));
+
+#undef extern
+
+#if !_PACKAGE_ast
+extern Void_t* malloc _ARG_((size_t));
+extern Void_t* realloc _ARG_((Void_t*, size_t));
+extern void free _ARG_((Void_t*));
+#endif
+_END_EXTERNS_
+
+#endif /* _CDTLIB_H */
diff --git a/src/lib/libast/cdt/dtclose.c b/src/lib/libast/cdt/dtclose.c
new file mode 100644
index 0000000..45bca76
--- /dev/null
+++ b/src/lib/libast/cdt/dtclose.c
@@ -0,0 +1,66 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "dthdr.h"
+
+/* Close a dictionary
+**
+** Written by Kiem-Phong Vo (11/15/2010)
+*/
+#if __STD_C
+int dtclose(Dt_t* dt)
+#else
+int dtclose(dt)
+Dt_t* dt;
+#endif
+{
+ int ev, type;
+ Dt_t pdt;
+ Dtdisc_t *disc = dt->disc;
+
+ if(!dt || dt->nview > 0 ) /* can't close if being viewed */
+ return -1;
+
+ if(disc && disc->eventf) /* announce closing event */
+ ev = (*disc->eventf)(dt, DT_CLOSE, (Void_t*)1, disc);
+ else ev = 0;
+ if(ev < 0) /* cannot close */
+ return -1;
+
+ if(dt->view) /* turn off viewing at this point */
+ dtview(dt,NIL(Dt_t*));
+
+ type = dt->data->type; /* save before memory is freed */
+ memcpy(&pdt, dt, sizeof(Dt_t));
+
+ if(ev == 0 ) /* release all allocated data */
+ { (void)(*(dt->meth->searchf))(dt,NIL(Void_t*),DT_CLEAR);
+ (void)(*dt->meth->eventf)(dt, DT_CLOSE, (Void_t*)0);
+ /**/DEBUG_ASSERT(!dt->data);
+ }
+ if(!(type&DT_INDATA) )
+ (void)free(dt);
+
+ if(disc && disc->eventf) /* announce end of closing activities */
+ (void)(*disc->eventf)(&pdt, DT_ENDCLOSE, (Void_t*)0, disc);
+
+ return 0;
+}
diff --git a/src/lib/libast/cdt/dtcomp.c b/src/lib/libast/cdt/dtcomp.c
new file mode 100644
index 0000000..5308c70
--- /dev/null
+++ b/src/lib/libast/cdt/dtcomp.c
@@ -0,0 +1,60 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * backwards binary compatibility
+ */
+
+#include <cdt.h>
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#undef dtflatten
+extern Dtlink_t* dtflatten(Dt_t* d)
+{
+ return (Dtlink_t*)(*(_DT(d)->searchf))((d),(Void_t*)(0),DT_FLATTEN);
+}
+
+#undef dtextract
+extern Dtlink_t* dtextract(Dt_t* d)
+{
+ return (Dtlink_t*)(*(_DT(d)->searchf))((d),(Void_t*)(0),DT_EXTRACT);
+}
+
+#undef dtrestore
+extern Dtlink_t* dtrestore(Dt_t* d, Void_t* l)
+{
+ return (Dtlink_t*)(*(_DT(d)->searchf))((d),(l),DT_RESTORE);
+}
+
+#undef dtsize
+extern ssize_t dtsize(Dt_t* d)
+{
+ return (ssize_t)(*(_DT(d)->searchf))((d),(Void_t*)(0),DT_STAT);
+}
+
+#undef dtstat
+extern ssize_t dtstat(Dt_t* d)
+{
+ return (ssize_t)(*(_DT(d)->searchf))((d),(Void_t*)(0),DT_STAT);
+}
diff --git a/src/lib/libast/cdt/dtdisc.c b/src/lib/libast/cdt/dtdisc.c
new file mode 100644
index 0000000..166aa7c
--- /dev/null
+++ b/src/lib/libast/cdt/dtdisc.c
@@ -0,0 +1,91 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "dthdr.h"
+
+/* Change discipline.
+** dt : dictionary
+** disc : discipline
+**
+** Written by Kiem-Phong Vo (5/26/96)
+*/
+
+#if __STD_C
+static Void_t* dtmemory(Dt_t* dt, Void_t* addr, size_t size, Dtdisc_t* disc)
+#else
+static Void_t* dtmemory(dt, addr, size, disc)
+Dt_t* dt; /* dictionary */
+Void_t* addr; /* address to be manipulate */
+size_t size; /* size to obtain */
+Dtdisc_t* disc; /* discipline */
+#endif
+{
+ if(addr)
+ { if(size == 0)
+ { free(addr);
+ return NIL(Void_t*);
+ }
+ else return realloc(addr,size);
+ }
+ else return size > 0 ? malloc(size) : NIL(Void_t*);
+}
+
+#if __STD_C
+Dtdisc_t* dtdisc(Dt_t* dt, Dtdisc_t* disc, int type)
+#else
+Dtdisc_t* dtdisc(dt,disc,type)
+Dt_t* dt;
+Dtdisc_t* disc;
+int type;
+#endif
+{
+ Dtsearch_f searchf;
+ Dtdisc_t *old;
+ Dtlink_t *list;
+
+ if(!(old = dt->disc) ) /* initialization call from dtopen() */
+ { dt->disc = disc;
+ if(!(dt->memoryf = disc->memoryf) )
+ dt->memoryf = dtmemory;
+ return disc;
+ }
+
+ if(!disc) /* only want to know current discipline */
+ return old;
+
+ searchf = dt->meth->searchf;
+
+ if(old->eventf && (*old->eventf)(dt,DT_DISC,(Void_t*)disc,old) < 0)
+ return NIL(Dtdisc_t*);
+
+ if((type & (DT_SAMEHASH|DT_SAMECMP)) != (DT_SAMEHASH|DT_SAMECMP) )
+ list = dtextract(dt); /* grab the list of objects if any */
+ else list = NIL(Dtlink_t*);
+
+ dt->disc = disc;
+ if(!(dt->memoryf = disc->memoryf) )
+ dt->memoryf = dtmemory;
+
+ if(list ) /* reinsert extracted objects (with new discipline) */
+ dtrestore(dt, list);
+
+ return old;
+}
diff --git a/src/lib/libast/cdt/dthash.c b/src/lib/libast/cdt/dthash.c
new file mode 100644
index 0000000..984b2a5
--- /dev/null
+++ b/src/lib/libast/cdt/dthash.c
@@ -0,0 +1,431 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "dthdr.h"
+
+/* Hash table with chaining for collisions.
+**
+** Written by Kiem-Phong Vo (05/25/96)
+*/
+
+/* these bits should be outside the scope of DT_METHODS */
+#define H_FIXED 0100000 /* table size is fixed */
+#define H_FLATTEN 0200000 /* table was flattened */
+
+#define HLOAD(n) (n) /* load one-to-one */
+
+/* internal data structure for hash table with chaining */
+typedef struct _dthash_s
+{ Dtdata_t data;
+ int type;
+ Dtlink_t* here; /* fingered object */
+ Dtlink_t** htbl; /* hash table slots */
+ ssize_t tblz; /* size of hash table */
+} Dthash_t;
+
+/* make/resize hash table */
+static int htable(Dt_t* dt)
+{
+ Dtlink_t **htbl, **t, **endt, *l, *next;
+ ssize_t n, k;
+ Dtdisc_t *disc = dt->disc;
+ Dthash_t *hash = (Dthash_t*)dt->data;
+
+ if((n = hash->tblz) > 0 && (hash->type&H_FIXED) )
+ return 0; /* fixed size table */
+
+ if(n == 0 && disc && disc->eventf) /* let user have input */
+ { if((*disc->eventf)(dt, DT_HASHSIZE, &n, disc) > 0 )
+ { if(n < 0) /* fix table size */
+ { hash->type |= H_FIXED;
+ n = -n;
+ }
+ }
+ }
+
+ /* table size should be a power of 2 */
+ n = n < HLOAD(hash->data.size) ? HLOAD(hash->data.size) : n;
+ for(k = (1<<DT_HTABLE); k < n; )
+ k *= 2;
+ if((n = k) <= hash->tblz)
+ return 0;
+
+ /* allocate new table */
+ if(!(htbl = (Dtlink_t**)(*dt->memoryf)(dt, 0, n*sizeof(Dtlink_t*), disc)) )
+ { DTERROR(dt, "Error in allocating an extended hash table");
+ return -1;
+ }
+ memset(htbl, 0, n*sizeof(Dtlink_t*));
+
+ /* move objects into new table */
+ for(endt = (t = hash->htbl) + hash->tblz; t < endt; ++t)
+ { for(l = *t; l; l = next)
+ { next = l->_rght;
+ l->_rght = htbl[k = l->_hash&(n-1)];
+ htbl[k] = l;
+ }
+ }
+
+ if(hash->htbl) /* free old table and set new table */
+ (void)(*dt->memoryf)(dt, hash->htbl, 0, disc);
+ hash->htbl = htbl;
+ hash->tblz = n;
+
+ return 0;
+}
+
+static Void_t* hclear(Dt_t* dt)
+{
+ Dtlink_t **t, **endt, *l, *next;
+ Dthash_t *hash = (Dthash_t*)dt->data;
+
+ hash->here = NIL(Dtlink_t*);
+ hash->data.size = 0;
+
+ for(endt = (t = hash->htbl) + hash->tblz; t < endt; ++t)
+ { for(l = *t; l; l = next)
+ { next = l->_rght;
+ _dtfree(dt, l, DT_DELETE);
+ }
+ *t = NIL(Dtlink_t*);
+ }
+
+ return NIL(Void_t*);
+}
+
+static Void_t* hfirst(Dt_t* dt)
+{
+ Dtlink_t **t, **endt, *l;
+ Dthash_t *hash = (Dthash_t*)dt->data;
+
+ for(endt = (t = hash->htbl) + hash->tblz; t < endt; ++t)
+ { if(!(l = *t) )
+ continue;
+ hash->here = l;
+ return _DTOBJ(dt->disc, l);
+ }
+
+ return NIL(Void_t*);
+}
+
+static Void_t* hnext(Dt_t* dt, Dtlink_t* l)
+{
+ Dtlink_t **t, **endt, *next;
+ Dthash_t *hash = (Dthash_t*)dt->data;
+
+ if((next = l->_rght) )
+ { hash->here = next;
+ return _DTOBJ(dt->disc, next);
+ }
+ else
+ { t = hash->htbl + (l->_hash & (hash->tblz-1)) + 1;
+ endt = hash->htbl + hash->tblz;
+ for(; t < endt; ++t)
+ { if(!(l = *t) )
+ continue;
+ hash->here = l;
+ return _DTOBJ(dt->disc, l);
+ }
+ return NIL(Void_t*);
+ }
+}
+
+static Void_t* hflatten(Dt_t* dt, int type)
+{
+ Dtlink_t **t, **endt, *head, *tail, *l;
+ Dthash_t *hash = (Dthash_t*)dt->data;
+
+ if(type == DT_FLATTEN || type == DT_EXTRACT)
+ { head = tail = NIL(Dtlink_t*);
+ for(endt = (t = hash->htbl) + hash->tblz; t < endt; ++t)
+ { for(l = *t; l; l = l->_rght)
+ { if(tail)
+ tail = (tail->_rght = l);
+ else head = tail = l;
+
+ *t = type == DT_FLATTEN ? tail : NIL(Dtlink_t*);
+ }
+ }
+
+ if(type == DT_FLATTEN)
+ { hash->here = head;
+ hash->type |= H_FLATTEN;
+ }
+ else hash->data.size = 0;
+
+ return (Void_t*)head;
+ }
+ else /* restoring a previous flattened list */
+ { head = hash->here;
+ for(endt = (t = hash->htbl) + hash->tblz; t < endt; ++t)
+ { if(*t == NIL(Dtlink_t*))
+ continue;
+
+ /* find the tail of the list for this slot */
+ for(l = head; l && l != *t; l = l->_rght)
+ ;
+ if(!l) /* something is seriously wrong */
+ return NIL(Void_t*);
+
+ *t = head; /* head of list for this slot */
+ head = l->_rght; /* head of next list */
+ l->_rght = NIL(Dtlink_t*);
+ }
+
+ hash->here = NIL(Dtlink_t*);
+ hash->type &= ~H_FLATTEN;
+
+ return NIL(Void_t*);
+ }
+}
+
+static Void_t* hlist(Dt_t* dt, Dtlink_t* list, int type)
+{
+ Void_t *obj;
+ Dtlink_t *l, *next;
+ Dtdisc_t *disc = dt->disc;
+
+ if(type&DT_FLATTEN)
+ return hflatten(dt, DT_FLATTEN);
+ else if(type&DT_EXTRACT)
+ return hflatten(dt, DT_EXTRACT);
+ else /* if(type&DT_RESTORE) */
+ { dt->data->size = 0;
+ for(l = list; l; l = next)
+ { next = l->_rght;
+ obj = _DTOBJ(disc,l);
+ if((*dt->meth->searchf)(dt, (Void_t*)l, DT_RELINK) == obj)
+ dt->data->size += 1;
+ }
+ return (Void_t*)list;
+ }
+}
+
+static Void_t* hstat(Dt_t* dt, Dtstat_t* st)
+{
+ ssize_t n;
+ Dtlink_t **t, **endt, *l;
+ Dthash_t *hash = (Dthash_t*)dt->data;
+
+ if(st)
+ { memset(st, 0, sizeof(Dtstat_t));
+ st->meth = dt->meth->type;
+ st->size = hash->data.size;
+ st->space = sizeof(Dthash_t) + hash->tblz*sizeof(Dtlink_t*) +
+ (dt->disc->link >= 0 ? 0 : hash->data.size*sizeof(Dthold_t));
+
+ for(endt = (t = hash->htbl) + hash->tblz; t < endt; ++t)
+ { for(n = 0, l = *t; l; l = l->_rght)
+ n += 1;
+ st->mlev = n > st->mlev ? n : st->mlev;
+ if(n < DT_MAXSIZE) /* if chain length is small */
+ { st->msize = n > st->msize ? n : st->msize;
+ st->lsize[n] += n;
+ }
+ }
+ }
+
+ return (Void_t*)hash->data.size;
+}
+
+#if __STD_C
+static Void_t* dthashchain(Dt_t* dt, Void_t* obj, int type)
+#else
+static Void_t* dthashchain(dt,obj,type)
+Dt_t* dt;
+Void_t* obj;
+int type;
+#endif
+{
+ Dtlink_t *lnk, *pp, *ll, *p, *l, **tbl;
+ Void_t *key, *k, *o;
+ uint hsh;
+ Dtdisc_t *disc = dt->disc;
+ Dthash_t *hash = (Dthash_t*)dt->data;
+
+ type = DTTYPE(dt,type); /* map type for upward compatibility */
+ if(!(type&DT_OPERATIONS) )
+ return NIL(Void_t*);
+
+ DTSETLOCK(dt);
+
+ if(!hash->htbl && htable(dt) < 0 ) /* initialize hash table */
+ DTRETURN(obj, NIL(Void_t*));
+
+ if(hash->type&H_FLATTEN) /* restore flattened list */
+ hflatten(dt, 0);
+
+ if(type&(DT_FIRST|DT_LAST|DT_CLEAR|DT_EXTRACT|DT_RESTORE|DT_FLATTEN|DT_STAT) )
+ { if(type&(DT_FIRST|DT_LAST) )
+ DTRETURN(obj, hfirst(dt));
+ else if(type&DT_CLEAR)
+ DTRETURN(obj, hclear(dt));
+ else if(type&DT_STAT)
+ DTRETURN(obj, hstat(dt, (Dtstat_t*)obj));
+ else /*if(type&(DT_EXTRACT|DT_RESTORE|DT_FLATTEN))*/
+ DTRETURN(obj, hlist(dt, (Dtlink_t*)obj, type));
+ }
+
+ lnk = hash->here; /* fingered object */
+ hash->here = NIL(Dtlink_t*);
+
+ if(lnk && obj == _DTOBJ(disc,lnk))
+ { if(type&DT_SEARCH)
+ DTRETURN(obj, obj);
+ else if(type&(DT_NEXT|DT_PREV) )
+ DTRETURN(obj, hnext(dt,lnk));
+ }
+
+ if(type&DT_RELINK)
+ { lnk = (Dtlink_t*)obj;
+ obj = _DTOBJ(disc,lnk);
+ key = _DTKEY(disc,obj);
+ }
+ else
+ { lnk = NIL(Dtlink_t*);
+ if((type&DT_MATCH) )
+ { key = obj;
+ obj = NIL(Void_t*);
+ }
+ else key = _DTKEY(disc,obj);
+ }
+ hsh = _DTHSH(dt,key,disc);
+
+ tbl = hash->htbl + (hsh & (hash->tblz-1));
+ pp = ll = NIL(Dtlink_t*);
+ for(p = NIL(Dtlink_t*), l = *tbl; l; p = l, l = l->_rght)
+ { if(hsh == l->_hash)
+ { o = _DTOBJ(disc,l); k = _DTKEY(disc,o);
+ if(_DTCMP(dt, key, k, disc) != 0 )
+ continue;
+ else if((type&(DT_REMOVE|DT_NEXT|DT_PREV)) && o != obj )
+ { if(type&(DT_NEXT|DT_PREV) )
+ { pp = p; ll = l; }
+ continue;
+ }
+ else break;
+ }
+ }
+ if(l) /* found an object, use it */
+ { pp = p; ll = l; }
+
+ if(ll) /* found object */
+ { if(type&(DT_SEARCH|DT_MATCH|DT_ATLEAST|DT_ATMOST) )
+ { hash->here = ll;
+ DTRETURN(obj, _DTOBJ(disc,ll));
+ }
+ else if(type & (DT_NEXT|DT_PREV) )
+ DTRETURN(obj, hnext(dt, ll));
+ else if(type & (DT_DELETE|DT_DETACH|DT_REMOVE) )
+ { hash->data.size -= 1;
+ if(pp)
+ pp->_rght = ll->_rght;
+ else *tbl = ll->_rght;
+ _dtfree(dt, ll, type);
+ DTRETURN(obj, _DTOBJ(disc,ll));
+ }
+ else
+ { /**/DEBUG_ASSERT(type&(DT_INSERT|DT_ATTACH|DT_APPEND|DT_RELINK));
+ if(!(dt->meth->type&DT_BAG) )
+ { if(type&(DT_INSERT|DT_APPEND|DT_ATTACH) )
+ type |= DT_SEARCH; /* for announcement */
+ else if(lnk && (type&DT_RELINK) )
+ _dtfree(dt, lnk, DT_DELETE);
+ DTRETURN(obj, _DTOBJ(disc,ll));
+ }
+ else goto do_insert;
+ }
+ }
+ else /* no matching object */
+ { if(!(type&(DT_INSERT|DT_APPEND|DT_ATTACH|DT_RELINK)) )
+ DTRETURN(obj, NIL(Void_t*));
+
+ do_insert: /* inserting a new object */
+ if(hash->tblz < HLOAD(hash->data.size) )
+ { htable(dt); /* resize table */
+ tbl = hash->htbl + (hsh & (hash->tblz-1));
+ }
+
+ if(!lnk) /* inserting a new object */
+ { if(!(lnk = _dtmake(dt, obj, type)) )
+ DTRETURN(obj, NIL(Void_t*));
+ hash->data.size += 1;
+ }
+
+ lnk->_hash = hsh; /* memoize the hash value */
+ lnk->_rght = *tbl; *tbl = lnk;
+
+ hash->here = lnk;
+ DTRETURN(obj, _DTOBJ(disc,lnk));
+ }
+
+dt_return:
+ DTANNOUNCE(dt, obj, type);
+ DTCLRLOCK(dt);
+ return obj;
+}
+
+static int hashevent(Dt_t* dt, int event, Void_t* arg)
+{
+ Dtlink_t *list;
+ Dthash_t *hash = (Dthash_t*)dt->data;
+ int rv = -1;
+
+ if(event == DT_OPEN)
+ { if(hash)
+ return 0;
+ if(!(hash = (Dthash_t*)(*dt->memoryf)(dt, 0, sizeof(Dthash_t), dt->disc)) )
+ { DTERROR(dt, "Error in allocating a hash table with chaining");
+ return -1;
+ }
+ memset(hash, 0, sizeof(Dthash_t));
+ dt->data = (Dtdata_t*)hash;
+ return 1;
+ }
+ else if(event == DT_CLOSE)
+ { if(!hash)
+ return 0;
+ if(hash->data.size > 0 )
+ (void)hclear(dt);
+ if(hash->htbl)
+ (void)(*dt->memoryf)(dt, hash->htbl, 0, dt->disc);
+ (void)(*dt->memoryf)(dt, hash, 0, dt->disc);
+ dt->data = NIL(Dtdata_t*);
+ return 0;
+ }
+ else return 0;
+}
+
+static Dtmethod_t _Dtset = { dthashchain, DT_SET, hashevent, "Dtset" };
+static Dtmethod_t _Dtbag = { dthashchain, DT_BAG, hashevent, "Dtbag" };
+__DEFINE__(Dtmethod_t*,Dtset,&_Dtset);
+__DEFINE__(Dtmethod_t*,Dtbag,&_Dtbag);
+
+/* backwards compatibility */
+#undef Dthash
+#if defined(__EXPORT__)
+__EXPORT__
+#endif
+__DEFINE__(Dtmethod_t*,Dthash,&_Dtset);
+
+#ifdef NoF
+NoF(dthashchain)
+#endif
diff --git a/src/lib/libast/cdt/dthdr.h b/src/lib/libast/cdt/dthdr.h
new file mode 100644
index 0000000..d24ae0d
--- /dev/null
+++ b/src/lib/libast/cdt/dthdr.h
@@ -0,0 +1,37 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#ifndef _DTHDR_H
+#define _DTHDR_H 1
+
+#ifndef _BLD_cdt
+#define _BLD_cdt 1
+#endif
+
+/* Internal definitions for libcdt.
+** Written by Kiem-Phong Vo (5/25/96)
+*/
+
+#undef _DTTRACE
+
+#include <cdtlib.h>
+
+#endif /* _DTHDR_H */
diff --git a/src/lib/libast/cdt/dtlist.c b/src/lib/libast/cdt/dtlist.c
new file mode 100644
index 0000000..af0dfd1
--- /dev/null
+++ b/src/lib/libast/cdt/dtlist.c
@@ -0,0 +1,387 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "dthdr.h"
+
+/* List, Deque, Stack, Queue.
+**
+** Written by Kiem-Phong Vo (05/25/96)
+*/
+
+typedef struct _dtlist_s
+{ Dtdata_t data;
+ Dtlink_t* link; /* list of objects */
+ Dtlink_t* here; /* finger to searched objects */
+} Dtlist_t;
+
+#ifdef DEBUG
+int dtlistprint(Dt_t* dt, Dtlink_t* here, char* (*objprintf)(Void_t*) )
+{
+ int k;
+ char *obj, *endb, buf[1024];
+ Dtdisc_t *disc = dt->disc;
+ Dtlist_t *list = (Dtlist_t*)dt->data;
+
+ if(!here && !(here = list->link) )
+ return -1;
+
+ for(; here; here = here->_rght)
+ { endb = buf; /* indentation */
+ *endb++ = '(';
+ obj = (*objprintf)(_DTOBJ(disc, here));
+ k = strlen(obj); memcpy(endb, obj, k); endb += k;
+ *endb++ = ')';
+ *endb++ = '\n';
+ write(2, buf, endb-buf);
+ }
+
+ return 0;
+}
+#endif
+
+/* terminal objects: DT_FIRST|DT_LAST */
+#if __STD_C
+Void_t* lfirstlast(Dt_t* dt, int type)
+#else
+Void_t* lfirstlast(dt, type)
+Dt_t* dt;
+int type;
+#endif
+{
+ Dtlink_t *lnk;
+ Dtdisc_t *disc = dt->disc;
+ Dtlist_t *list = (Dtlist_t*)dt->data;
+
+ if((lnk = list->link) )
+ { if(type&DT_LAST)
+ lnk = lnk->_left;
+ list->here = lnk; /* finger points to this */
+ }
+
+ return lnk ? _DTOBJ(disc,lnk) : NIL(Void_t*);
+}
+
+/* DT_CLEAR */
+#if __STD_C
+Void_t* lclear(Dt_t* dt)
+#else
+Void_t* lclear(dt)
+Dt_t* dt;
+#endif
+{
+ Dtlink_t *lnk, *next;
+ Dtdisc_t *disc = dt->disc;
+ Dtlist_t *list = (Dtlist_t*)dt->data;
+
+ lnk = list->link;
+ list->link = list->here = NIL(Dtlink_t*);
+ list->data.size = 0;
+
+ if(disc->freef || disc->link < 0)
+ { for(; lnk; lnk = next)
+ { next = lnk->_rght;
+ _dtfree(dt, lnk, DT_DELETE);
+ }
+ }
+
+ return NIL(Void_t*);
+}
+
+/* DT_FLATTEN|DT_EXTRACT|DT_RESTORE */
+#if __STD_C
+Void_t* llist(Dt_t* dt, Dtlink_t* lnk, int type)
+#else
+Void_t* llist(dt, lnk, type)
+Dt_t* dt;
+Dtlink_t* lnk;
+int type;
+#endif
+{
+ Dtlist_t *list = (Dtlist_t*)dt->data;
+
+ if(type&(DT_FLATTEN|DT_EXTRACT) )
+ { if(lnk) /* error on calling */
+ return NIL(Void_t*);
+
+ lnk = list->link;
+ if(type&DT_EXTRACT)
+ { list->link = NIL(Dtlink_t*);
+ dt->data->size = 0;
+ }
+ }
+ else /* if(type&DT_RESTORE) */
+ { if(list->link != NIL(Dtlink_t*))
+ return NIL(Void_t*);
+
+ list->link = lnk;
+
+ dt->data->size = 0;
+ for(; lnk; lnk = lnk->_rght)
+ dt->data->size += 1;
+ }
+
+ return (Void_t*)lnk;
+}
+
+#if __STD_C
+static Void_t* liststat(Dt_t* dt, Dtstat_t* st)
+#else
+static Void_t* liststat(dt, st)
+Dt_t* dt;
+Dtstat_t* st;
+#endif
+{
+ ssize_t size;
+ Dtlink_t *lnk;
+ Dtlist_t *list = (Dtlist_t*)dt->data;
+
+ if(st)
+ { memset(st, 0, sizeof(Dtstat_t));
+ st->meth = dt->meth->type;
+ st->size = dt->data->size;
+ st->space = sizeof(Dtlist_t) + (dt->disc->link >= 0 ? 0 : dt->data->size*sizeof(Dthold_t));
+ }
+
+ return (Void_t*)dt->data->size;
+}
+
+#if __STD_C
+static Void_t* dtlist(Dt_t* dt, Void_t* obj, int type)
+#else
+static Void_t* dtlist(dt, obj, type)
+Dt_t* dt;
+Void_t* obj;
+int type;
+#endif
+{
+ Dtlink_t *r, *t, *h;
+ Void_t *key, *o, *k;
+ Dtdisc_t *disc = dt->disc;
+ Dtlist_t *list = (Dtlist_t*)dt->data;
+
+ type = DTTYPE(dt,type); /* map type for upward compatibility */
+ if(!(type&DT_OPERATIONS) )
+ return NIL(Void_t*);
+
+ DTSETLOCK(dt);
+
+ if(type&(DT_FIRST|DT_LAST) )
+ DTRETURN(obj, lfirstlast(dt, type));
+ else if(type&(DT_EXTRACT|DT_RESTORE|DT_FLATTEN) )
+ DTRETURN(obj, llist(dt, (Dtlink_t*)obj, type));
+ else if(type&DT_CLEAR)
+ DTRETURN(obj, lclear(dt));
+ else if(type&DT_STAT )
+ DTRETURN(obj, liststat(dt, (Dtstat_t*)obj));
+
+ h = list->here; /* save finger to last search object */
+ list->here = NIL(Dtlink_t*);
+
+ if(!obj)
+ { if((type&(DT_DELETE|DT_DETACH|DT_REMOVE)) && (dt->meth->type&(DT_STACK|DT_QUEUE)) )
+ if((r = list->link) ) /* special case for destack or dequeue */
+ goto dt_delete;
+ DTRETURN(obj, NIL(Void_t*)); /* error, needing non-void object */
+ }
+
+ if(type&DT_RELINK) /* relink object after some processing */
+ { r = (Dtlink_t*)obj;
+ goto do_insert;
+ }
+ else if(type&(DT_INSERT|DT_APPEND|DT_ATTACH))
+ { if(!(r = _dtmake(dt, obj, type)) )
+ DTRETURN(obj, NIL(Void_t*));
+ dt->data->size += 1;
+
+ do_insert:
+ if(dt->meth->type&DT_DEQUE)
+ { if(type&DT_APPEND)
+ goto dt_queue; /* append at end */
+ else goto dt_stack; /* insert at top */
+ }
+ else if(dt->meth->type&DT_LIST)
+ { if(type&DT_APPEND)
+ { if(!h || !h->_rght)
+ goto dt_queue;
+ r->_rght = h->_rght;
+ r->_rght->_left = r;
+ r->_left = h;
+ r->_left->_rght = r;
+ }
+ else
+ { if(!h || h == list->link )
+ goto dt_stack;
+ r->_left = h->_left;
+ r->_left->_rght = r;
+ r->_rght = h;
+ r->_rght->_left = r;
+ }
+ }
+ else if(dt->meth->type&DT_STACK)
+ { dt_stack:
+ r->_rght = t = list->link;
+ if(t)
+ { r->_left = t->_left;
+ t->_left = r;
+ }
+ else r->_left = r;
+ list->link = r;
+ }
+ else /* if(dt->meth->type&DT_QUEUE) */
+ { dt_queue:
+ if((t = list->link) )
+ { t->_left->_rght = r;
+ r->_left = t->_left;
+ t->_left = r;
+ }
+ else
+ { list->link = r;
+ r->_left = r;
+ }
+ r->_rght = NIL(Dtlink_t*);
+ }
+
+ list->here = r;
+ DTRETURN(obj, _DTOBJ(disc,r));
+ }
+
+ /* define key to match */
+ if(type&DT_MATCH)
+ { key = obj;
+ obj = NIL(Void_t*);
+ }
+ else key = _DTKEY(disc, obj);
+
+ /* try to find a matching object */
+ if(h && _DTOBJ(disc,h) == obj && (type & (DT_SEARCH|DT_NEXT|DT_PREV)) )
+ r = h; /* match at the finger, no search needed */
+ else /* linear search through the list */
+ { h = NIL(Dtlink_t*); /* track first/last obj with same key */
+ for(r = list->link; r; r = r->_rght)
+ { o = _DTOBJ(disc,r); k = _DTKEY(disc,o);
+ if(_DTCMP(dt, key, k, disc) != 0)
+ continue;
+ else if(type & (DT_REMOVE|DT_NEXT|DT_PREV) )
+ { if(o == obj) /* got exact object, done */
+ break;
+ else if(type&DT_NEXT) /* track last object */
+ h = r;
+ else if(type&DT_PREV) /* track first object */
+ h = h ? h : r;
+ else continue;
+ }
+ else if(type & DT_ATLEAST )
+ h = r; /* track last object */
+ else break;
+ }
+ r = h ? h : r;
+ }
+ if(!r)
+ DTRETURN(obj, NIL(Void_t*));
+
+ if(type&(DT_DELETE|DT_DETACH|DT_REMOVE))
+ { dt_delete:
+ if(r->_rght)
+ r->_rght->_left = r->_left;
+ if(r == (t = list->link) )
+ { list->link = r->_rght;
+ if((h = list->link) )
+ h->_left = t->_left;
+ }
+ else
+ { r->_left->_rght = r->_rght;
+ if(r == t->_left)
+ t->_left = r->_left;
+ }
+
+ list->here = r == list->here ? r->_rght : NIL(Dtlink_t*);
+
+ obj = _DTOBJ(disc,r);
+ _dtfree(dt, r, type);
+ dt->data->size -= 1;
+
+ DTRETURN(obj, obj);
+ }
+
+ if(type&DT_NEXT)
+ r = r->_rght;
+ else if(type&DT_PREV)
+ r = r == list->link ? NIL(Dtlink_t*) : r->_left;
+ /* else: if(type&(DT_SEARCH|DT_MATCH|DT_ATLEAST|DT_ATMOST)) */
+
+ list->here = r;
+ if(r)
+ DTRETURN(obj, _DTOBJ(disc,r));
+ else DTRETURN(obj, NIL(Void_t*));
+
+dt_return:
+ DTANNOUNCE(dt,obj,type);
+ DTCLRLOCK(dt);
+ return obj;
+}
+
+#if __STD_C
+static int listevent(Dt_t* dt, int event, Void_t* arg)
+#else
+static int listevent(dt, event, arg)
+Dt_t* dt;
+int event;
+Void_t* arg;
+#endif
+{
+ Dtlist_t *list = (Dtlist_t*)dt->data;
+
+ if(event == DT_OPEN)
+ { if(list) /* already initialized */
+ return 0;
+ if(!(list = (Dtlist_t*)(*dt->memoryf)(dt, 0, sizeof(Dtlist_t), dt->disc)) )
+ { DTERROR(dt, "Error in allocating a list data structure");
+ return -1;
+ }
+ memset(list, 0, sizeof(Dtlist_t));
+ dt->data = (Dtdata_t*)list;
+ return 1;
+ }
+ else if(event == DT_CLOSE)
+ { if(!list) /* already closed */
+ return 0;
+ if(list->link) /* remove all items */
+ (void)lclear(dt);
+ (void)(*dt->memoryf)(dt, (Void_t*)list, 0, dt->disc);
+ dt->data = NIL(Dtdata_t*);
+ return 0;
+ }
+ else return 0;
+}
+
+static Dtmethod_t _Dtlist = { dtlist, DT_LIST, listevent, "Dtlist" };
+static Dtmethod_t _Dtdeque = { dtlist, DT_DEQUE, listevent, "Dtdeque" };
+static Dtmethod_t _Dtstack = { dtlist, DT_STACK, listevent, "Dtstack" };
+static Dtmethod_t _Dtqueue = { dtlist, DT_QUEUE, listevent, "Dtqueue" };
+
+__DEFINE__(Dtmethod_t*,Dtlist,&_Dtlist);
+__DEFINE__(Dtmethod_t*,Dtdeque,&_Dtdeque);
+__DEFINE__(Dtmethod_t*,Dtstack,&_Dtstack);
+__DEFINE__(Dtmethod_t*,Dtqueue,&_Dtqueue);
+
+#ifdef NoF
+NoF(dtlist)
+#endif
diff --git a/src/lib/libast/cdt/dtmethod.c b/src/lib/libast/cdt/dtmethod.c
new file mode 100644
index 0000000..56a1d25
--- /dev/null
+++ b/src/lib/libast/cdt/dtmethod.c
@@ -0,0 +1,107 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "dthdr.h"
+
+/* Change search method.
+**
+** Written by Kiem-Phong Vo (05/25/96)
+*/
+
+#if __STD_C
+Dtmethod_t* dtmethod(Dt_t* dt, Dtmethod_t* meth)
+#else
+Dtmethod_t* dtmethod(dt, meth)
+Dt_t* dt;
+Dtmethod_t* meth;
+#endif
+{
+ Dtlink_t *list;
+ Dtdisc_t *disc = dt->disc;
+ Dtmethod_t *oldmt = dt->meth;
+ Dtdata_t *newdt, *olddt = dt->data;
+
+ if(!meth || meth == oldmt)
+ return oldmt;
+
+ /* ask discipline if switching to new method is ok */
+ if(disc->eventf && (*disc->eventf)(dt,DT_METH,(Void_t*)meth,disc) < 0)
+ return NIL(Dtmethod_t*);
+
+ list = dtextract(dt); /* extract elements out of dictionary */
+
+ /* try to create internal structure for new method */
+ if(dt->searchf == oldmt->searchf) /* ie, not viewpathing */
+ dt->searchf = meth->searchf;
+ dt->meth = meth;
+ dt->data = NIL(Dtdata_t*);
+ if((*dt->meth->eventf)(dt, DT_OPEN, NIL(Void_t*)) < 0 )
+ newdt = NIL(Dtdata_t*);
+ else newdt = dt->data;
+
+ /* see what need to be done to data of the old method */
+ if(dt->searchf == meth->searchf)
+ dt->searchf = oldmt->searchf;
+ dt->meth = oldmt;
+ dt->data = olddt;
+ if(newdt) /* switch was successful, remove old data */
+ { (void)(*dt->meth->eventf)(dt, DT_CLOSE, NIL(Void_t*));
+
+ if(dt->searchf == oldmt->searchf)
+ dt->searchf = meth->searchf;
+ dt->meth = meth;
+ dt->data = newdt;
+ dtrestore(dt, list);
+ return oldmt;
+ }
+ else /* switch failed, restore dictionary to previous states */
+ { dtrestore(dt, list);
+ return NIL(Dtmethod_t*);
+ }
+}
+
+/* customize certain actions in a container data structure */
+int dtcustomize(Dt_t* dt, int type, int action)
+{
+ int done = 0;
+
+ if((type&DT_SHARE) &&
+ (!dt->meth->eventf || (*dt->meth->eventf)(dt, DT_SHARE, (Void_t*)((long)action)) >= 0) )
+ { if(action <= 0 )
+ dt->data->type &= ~DT_SHARE;
+ else dt->data->type |= DT_SHARE;
+ done |= DT_SHARE;
+ }
+
+ if((type&DT_ANNOUNCE) &&
+ (!dt->meth->eventf || (*dt->meth->eventf)(dt, DT_ANNOUNCE, (Void_t*)((long)action)) >= 0) )
+ { if(action <= 0 )
+ dt->data->type &= ~DT_ANNOUNCE;
+ else dt->data->type |= DT_ANNOUNCE;
+ done |= DT_ANNOUNCE;
+ }
+
+ if((type&DT_OPTIMIZE) &&
+ (!dt->meth->eventf || (*dt->meth->eventf)(dt, DT_OPTIMIZE, (Void_t*)((long)action)) >= 0) )
+ done |= DT_OPTIMIZE;
+
+ return done;
+}
diff --git a/src/lib/libast/cdt/dtnew.c b/src/lib/libast/cdt/dtnew.c
new file mode 100644
index 0000000..5e1bb70
--- /dev/null
+++ b/src/lib/libast/cdt/dtnew.c
@@ -0,0 +1,81 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * dtopen() with handle placed in specific vm region
+ */
+
+#include <dt.h>
+
+typedef struct Dc_s
+{
+ Dtdisc_t ndisc;
+ Dtdisc_t* odisc;
+ Vmalloc_t* vm;
+} Dc_t;
+
+static int
+eventf(Dt_t* dt, int op, void* data, Dtdisc_t* disc)
+{
+ Dc_t* dc = (Dc_t*)disc;
+ int r;
+
+ if (dc->odisc->eventf && (r = (*dc->odisc->eventf)(dt, op, data, dc->odisc)))
+ return r;
+ return op == DT_ENDOPEN ? 1 : 0;
+}
+
+static void*
+memoryf(Dt_t* dt, void* addr, size_t size, Dtdisc_t* disc)
+{
+ return vmresize(((Dc_t*)disc)->vm, addr, size, VM_RSMOVE);
+}
+
+/*
+ * open a dictionary using disc->memoryf if set or vm otherwise
+ */
+
+Dt_t*
+_dtnew(Vmalloc_t* vm, Dtdisc_t* disc, Dtmethod_t* meth, unsigned long version)
+{
+ Dt_t* dt;
+ Dc_t dc;
+
+ dc.odisc = disc;
+ dc.ndisc = *disc;
+ dc.ndisc.eventf = eventf;
+ if (!dc.ndisc.memoryf)
+ dc.ndisc.memoryf = memoryf;
+ dc.vm = vm;
+ if (dt = _dtopen(&dc.ndisc, meth, version))
+ dtdisc(dt, disc, DT_SAMECMP|DT_SAMEHASH);
+ return dt;
+}
+
+#undef dtnew
+
+Dt_t*
+dtnew(Vmalloc_t* vm, Dtdisc_t* disc, Dtmethod_t* meth)
+{
+ return _dtnew(vm, disc, meth, 20050420L);
+}
diff --git a/src/lib/libast/cdt/dtopen.c b/src/lib/libast/cdt/dtopen.c
new file mode 100644
index 0000000..6411969
--- /dev/null
+++ b/src/lib/libast/cdt/dtopen.c
@@ -0,0 +1,177 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "dthdr.h"
+static char* Version = "\n@(#)$Id: cdt (AT&T Labs - Research) 2011-11-11 $\0\n";
+
+/* Make a new dictionary
+**
+** Written by Kiem-Phong Vo (5/25/96)
+*/
+
+/* map operation bits from the 2005 version to the current version */
+static int _dttype2005(Dt_t* dt, int type)
+{
+ if (type == DT_DELETE && (dt->meth->type&(DT_OBAG|DT_BAG)))
+ type = DT_REMOVE;
+ return type;
+}
+
+#if __STD_C
+Dt_t* _dtopen(Dtdisc_t* disc, Dtmethod_t* meth, unsigned long version)
+#else
+Dt_t* _dtopen(disc, meth, version)
+Dtdisc_t* disc;
+Dtmethod_t* meth;
+unsigned long version;
+#endif
+{
+ Dtdata_t *data;
+ Dt_t *dt, pdt;
+ int ev, type;
+
+ if(!disc || !meth)
+ return NIL(Dt_t*);
+
+ dt = NIL(Dt_t*);
+ data = NIL(Dtdata_t*);
+ type = meth->type;
+
+ memset(&pdt, 0, sizeof(Dt_t));
+ pdt.searchf = meth->searchf;
+ pdt.meth = meth;
+ dtdisc(&pdt,disc,0); /* note that this sets pdt.memoryf */
+
+ if(disc->eventf)
+ { if((ev = (*disc->eventf)(&pdt,DT_OPEN,(Void_t*)(&data),disc)) < 0)
+ return NIL(Dt_t*); /* something bad happened */
+ else if(ev > 0)
+ { if(data) /* shared data are being restored */
+ { if((data->type & DT_METHODS) != meth->type)
+ { DTERROR(&pdt, "Error in matching methods to restore dictionary");
+ return NIL(Dt_t*);
+ }
+ pdt.data = data;
+ }
+ }
+ else
+ { if(data) /* dt should be allocated with dt->data */
+ type |= DT_INDATA;
+ }
+ }
+
+ if(!pdt.data) /* allocate method-specific data */
+ if((*meth->eventf)(&pdt, DT_OPEN, NIL(Void_t*)) < 0 || !pdt.data )
+ return NIL(Dt_t*);
+ pdt.data->type |= type;
+
+ /* now allocate/initialize the actual dictionary structure */
+ if(pdt.data->type&DT_INDATA)
+ dt = &pdt.data->dict;
+ else if(!(dt = (Dt_t*) malloc(sizeof(Dt_t))) )
+ { (void)(*meth->eventf)(&pdt, DT_CLOSE, NIL(Void_t*));
+ DTERROR(&pdt, "Error in allocating a new dictionary");
+ return NIL(Dt_t*);
+ }
+
+ *dt = pdt;
+
+ dt->user = &dt->data->user; /* space allocated for application usage */
+
+ if(disc->eventf) /* signal opening is done */
+ (void)(*disc->eventf)(dt, DT_ENDOPEN, (Void_t*)0, disc);
+
+ /* set mapping of operation bits between versions as needed */
+ if(version < 20111111L)
+ dt->typef = _dttype2005;
+
+ return dt;
+}
+
+#undef dtopen /* deal with binary upward compatibility for op bits */
+#if __STD_C
+Dt_t* dtopen(Dtdisc_t* disc, Dtmethod_t* meth)
+#else
+Dt_t* dtopen(disc, meth)
+Dtdisc_t* disc;
+Dtmethod_t* meth;
+#endif
+{
+ return _dtopen(disc, meth, 20050420L);
+}
+
+/* below are private functions used across CDT modules */
+Dtlink_t* _dtmake(Dt_t* dt, Void_t* obj, int type)
+{
+ Dthold_t *h;
+ Dtdisc_t *disc = dt->disc;
+
+ /* if obj is a prototype, make a real one */
+ if(!(type&DT_ATTACH) && disc->makef && !(obj = (*disc->makef)(dt, obj, disc)) )
+ return NIL(Dtlink_t*);
+
+ if(disc->link >= 0) /* holder is embedded in obj itself */
+ return _DTLNK(disc, obj);
+
+ /* create a holder to hold obj */
+ if((h = (Dthold_t*)(dt->memoryf)(dt, NIL(Void_t*), sizeof(Dthold_t), disc)) )
+ h->obj = obj;
+ else
+ { DTERROR(dt, "Error in allocating an object holder");
+ if(!(type&DT_ATTACH) && disc->makef && disc->freef)
+ (void)(*disc->freef)(dt, obj, disc); /* free just-made obj */
+ }
+
+ return (Dtlink_t*)h;
+}
+
+void _dtfree(Dt_t* dt, Dtlink_t* l, int type)
+{
+ Dtdisc_t *disc = dt->disc;
+
+ if(!(type&DT_DETACH) && disc->freef) /* free object */
+ (void)(*disc->freef)(dt, _DTOBJ(disc,l), disc);
+
+ if(disc->link < 0) /* free holder */
+ (void)(*dt->memoryf)(dt, (Void_t*)l, 0, disc);
+}
+
+int dtuserlock(Dt_t* dt, unsigned int key, int type)
+{
+ if(type > 0)
+ return asolock(&dt->data->user.lock, key, ASO_LOCK);
+ else if(type < 0)
+ return asolock(&dt->data->user.lock, key, ASO_UNLOCK);
+ else return asolock(&dt->data->user.lock, key, ASO_TRYLOCK);
+}
+
+Void_t* dtuserdata(Dt_t* dt, Void_t* data, unsigned int key)
+{
+ if(key == 0)
+ return dt->data->user.data;
+ else if(dtuserlock(dt, key, 1) < 0 )
+ return NIL(Void_t*);
+ else
+ { dt->data->user.data = data;
+ dtuserlock(dt, key, -1);
+ return data;
+ }
+}
diff --git a/src/lib/libast/cdt/dtstrhash.c b/src/lib/libast/cdt/dtstrhash.c
new file mode 100644
index 0000000..7eaac89
--- /dev/null
+++ b/src/lib/libast/cdt/dtstrhash.c
@@ -0,0 +1,61 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "dthdr.h"
+
+/* Hashing a string into an unsigned integer.
+** The basic method is to continuingly accumulate bytes and multiply
+** with some given prime. The length n of the string is added last.
+** The recurrent equation is like this:
+** h[k] = (h[k-1] + bytes)*prime for 0 <= k < n
+** h[n] = (h[n-1] + n)*prime
+** The prime is chosen to have a good distribution of 1-bits so that
+** the multiplication will distribute the bits in the accumulator well.
+** The below code accumulates 2 bytes at a time for speed.
+**
+** Written by Kiem-Phong Vo (02/28/03)
+*/
+
+#if __STD_C
+uint dtstrhash(uint h, Void_t* args, ssize_t n)
+#else
+uint dtstrhash(h,args,n)
+reg uint h;
+Void_t* args;
+ssize_t n;
+#endif
+{
+ unsigned char *s = (unsigned char*)args;
+
+ if(n <= 0)
+ { for(; *s != 0; s += s[1] ? 2 : 1)
+ h = (h + (s[0]<<8) + s[1])*DT_PRIME;
+ n = s - (unsigned char*)args;
+ }
+ else
+ { unsigned char* ends;
+ for(ends = s+n-1; s < ends; s += 2)
+ h = (h + (s[0]<<8) + s[1])*DT_PRIME;
+ if(s <= ends)
+ h = (h + (s[0]<<8))*DT_PRIME;
+ }
+ return (h+n)*DT_PRIME;
+}
diff --git a/src/lib/libast/cdt/dttree.c b/src/lib/libast/cdt/dttree.c
new file mode 100644
index 0000000..2dd31d3
--- /dev/null
+++ b/src/lib/libast/cdt/dttree.c
@@ -0,0 +1,696 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "dthdr.h"
+
+/* Ordered set/multiset
+** dt: dictionary being searched
+** obj: the object to look for.
+** type: search type.
+**
+** Written by Kiem-Phong Vo (5/25/96)
+*/
+
+typedef struct _dttree_s
+{ Dtdata_t data;
+ Dtlink_t* root; /* tree root */
+} Dttree_t;
+
+#ifdef CDT_DEBUG
+int dttreeprint(Dt_t* dt, Dtlink_t* here, int lev, char* (*objprintf)(Void_t*) )
+{
+ int k, rv;
+ char *obj, *endb, buf[1024];
+ Dtdisc_t *disc = dt->disc;
+ Dttree_t *tree = (Dttree_t*)dt->data;
+
+ if(!here && !(here = tree->root) )
+ return -1;
+
+ endb = buf; /* indentation */
+ for(k = 0; k < lev; ++k)
+ { *endb++ = ' '; *endb++ = ' '; }
+
+ *endb++ = '(';
+ obj = (*objprintf)(_DTOBJ(disc, here));
+ k = strlen(obj); memcpy(endb, obj, k); endb += k;
+ *endb++ = ')';
+ *endb++ = ':';
+ *endb++ = ' ';
+
+ *endb++ = '<';
+ if(here->_left)
+ obj = (*objprintf)(_DTOBJ(disc,here->_left));
+ else obj = "NIL";
+ k = strlen(obj); memcpy(endb, obj, k); endb += k;
+ *endb++ = '>';
+ *endb++ = ' ';
+
+ *endb++ = '<';
+ if(here->_rght)
+ obj = (*objprintf)(_DTOBJ(disc,here->_rght));
+ else obj = "NIL";
+ k = strlen(obj); memcpy(endb, obj, k); endb += k;
+ *endb++ = '>';
+ *endb++ = '\n';
+ write(2, buf, endb-buf);
+
+ if(here->_left)
+ dttreeprint(dt, here->_left, lev+1, objprintf);
+ if(here->_rght)
+ dttreeprint(dt, here->_rght, lev+1, objprintf);
+
+ return 0;
+}
+#endif
+
+/* terminal object: DT_FIRST|DT_LAST */
+#if __STD_C
+Void_t* tfirstlast(Dt_t* dt, int type)
+#else
+Void_t* tfirstlast(dt, type)
+Dt_t* dt;
+int type;
+#endif
+{
+ Dtlink_t *t, *root;
+ Dtdisc_t *disc = dt->disc;
+ Dttree_t *tree = (Dttree_t*)dt->data;
+
+ if(!(root = tree->root) )
+ return NIL(Void_t*);
+
+ if(type&DT_LAST)
+ { while((t = root->_rght) )
+ LROTATE(root,t);
+ }
+ else /* type&DT_FIRST */
+ { while((t = root->_left) )
+ RROTATE(root,t);
+ }
+ tree->root = root;
+
+ return _DTOBJ(disc, root);
+}
+
+/* DT_CLEAR */
+#if __STD_C
+static Void_t* tclear(Dt_t* dt)
+#else
+static Void_t* tclear(dt)
+Dt_t* dt;
+#endif
+{
+ Dtlink_t *root, *t;
+ Dtdisc_t *disc = dt->disc;
+ Dttree_t *tree = (Dttree_t*)dt->data;
+
+ root = tree->root;
+ tree->root = NIL(Dtlink_t*);
+ tree->data.size = 0;
+
+ if(root && (disc->link < 0 || disc->freef) )
+ { do
+ { while((t = root->_left) )
+ RROTATE(root,t);
+ t = root->_rght;
+ _dtfree(dt, root, DT_DELETE);
+ } while((root = t) );
+ }
+
+ return NIL(Void_t*);
+}
+
+#if __STD_C
+static Void_t* tlist(Dt_t* dt, Dtlink_t* list, int type)
+#else
+static Void_t* tlist(dt, list, type)
+Dt_t* dt;
+Dtlink_t* list;
+int type;
+#endif
+{
+ Void_t *obj;
+ Dtlink_t *last, *r, *t;
+ Dttree_t *tree = (Dttree_t*)dt->data;
+ Dtdisc_t *disc = dt->disc;
+
+ if(type&(DT_FLATTEN|DT_EXTRACT) )
+ { if((list = tree->root) )
+ { while((t = list->_left) ) /* make smallest object root */
+ RROTATE(list, t);
+ for(r = (last = list)->_rght; r; r = (last = r)->_rght)
+ { while((t = r->_left) ) /* no left children */
+ RROTATE(r,t);
+ last->_rght = r;
+ }
+ }
+
+ if(type&DT_FLATTEN)
+ tree->root = list;
+ else
+ { tree->root = NIL(Dtlink_t*);
+ dt->data->size = 0;
+ }
+ }
+ else /* if(type&DT_RESTORE) */
+ { dt->data->size = 0;
+ for(r = list; r; r = t)
+ { t = r->_rght;
+ obj = _DTOBJ(disc,r);
+ if((*dt->meth->searchf)(dt, (Void_t*)r, DT_RELINK) == obj )
+ dt->data->size += 1;
+ }
+ }
+
+ return (Void_t*)list;
+}
+
+#if __STD_C /* compute tree depth and number of nodes */
+static ssize_t tsize(Dtlink_t* root, ssize_t lev, Dtstat_t* st)
+#else
+static ssize_t tsize(root, lev, st)
+Dtlink_t* root;
+ssize_t lev;
+Dtstat_t* st;
+#endif
+{
+ ssize_t size, z;
+
+ if(!root) /* nothing to do */
+ return 0;
+
+ if(lev >= DT_MAXRECURSE) /* avoid blowing the stack */
+ return -1;
+
+ if(st)
+ { st->mlev = lev > st->mlev ? lev : st->mlev;
+ if(lev < DT_MAXSIZE)
+ { st->msize = lev > st->msize ? lev : st->msize;
+ st->lsize[lev] += 1; /* count #objects per level */
+ }
+ }
+
+ size = 1;
+
+ if((z = tsize(root->_left, lev+1, st)) < 0)
+ return -1;
+ else size += z;
+
+ if((z = tsize(root->_rght, lev+1, st)) < 0)
+ return -1;
+ else size += z;
+
+ return size;
+}
+
+#if __STD_C
+static Void_t* tstat(Dt_t* dt, Dtstat_t* st)
+#else
+static Void_t* tstat(dt, st)
+Dt_t* dt;
+Dtstat_t* st;
+#endif
+{
+ ssize_t size;
+ Dttree_t *tree = (Dttree_t*)dt->data;
+
+ if(!st)
+ return (Void_t*)dt->data->size;
+ else
+ { memset(st, 0, sizeof(Dtstat_t));
+ size = tsize(tree->root, 0, st);
+ /**/DEBUG_ASSERT((dt->data->type&DT_SHARE) || size == dt->data->size);
+ st->meth = dt->meth->type;
+ st->size = size;
+ st->space = sizeof(Dttree_t) + (dt->disc->link >= 0 ? 0 : size*sizeof(Dthold_t));
+ return (Void_t*)size;
+ }
+}
+
+#if __STD_C /* make a list into a balanced tree */
+static Dtlink_t* tbalance(Dtlink_t* list, ssize_t size)
+#else
+static Dtlink_t* tbalance(list, size)
+Dtlink_t* list;
+ssize_t size;
+#endif
+{
+ ssize_t n;
+ Dtlink_t *l, *mid;
+
+ if(size <= 2)
+ return list;
+
+ for(l = list, n = size/2 - 1; n > 0; n -= 1)
+ l = l->_rght;
+
+ mid = l->_rght; l->_rght = NIL(Dtlink_t*);
+ mid->_left = tbalance(list, (n = size/2) );
+ mid->_rght = tbalance(mid->_rght, size - (n + 1));
+ return mid;
+}
+
+static void toptimize(Dt_t* dt)
+{
+ ssize_t size;
+ Dtlink_t *l, *list;
+ Dttree_t *tree = (Dttree_t*)dt->data;
+
+ if((list = (Dtlink_t*)tlist(dt, NIL(Void_t*), DT_FLATTEN)) )
+ { for(size = 0, l = list; l; l = l->_rght)
+ size += 1;
+ tree->root = tbalance(list, size);
+ }
+}
+
+static Dtlink_t* troot(Dt_t* dt, Dtlink_t* list, Dtlink_t* link, Void_t* obj, int type)
+{
+ Dtlink_t *root, *last, *t, *r, *l;
+ Void_t *key, *o, *k;
+ Dtdisc_t *disc = dt->disc;
+
+ key = _DTKEY(disc, obj); /* key of object */
+
+ if(type&(DT_ATMOST|DT_ATLEAST) ) /* find the left-most or right-most element */
+ { list->_left = link->_rght;
+ list->_rght = link->_left;
+ if(type&DT_ATMOST)
+ { while((l = list->_left) )
+ { while((r = l->_rght) ) /* get the max elt of left subtree */
+ LROTATE(l,r);
+ list->_left = l;
+
+ o = _DTOBJ(disc,l); k = _DTKEY(disc,o);
+ if(_DTCMP(dt, key, k, disc) != 0 )
+ break;
+ else RROTATE(list,l);
+ }
+ }
+ else
+ { while((r = list->_rght) )
+ { while((l = r->_left) ) /* get the min elt of right subtree */
+ RROTATE(r,l);
+ list->_rght = r;
+
+ o = _DTOBJ(disc,r); k = _DTKEY(disc,o);
+ if(_DTCMP(dt, key, k, disc) != 0 )
+ break;
+ else LROTATE(list,r);
+ }
+ }
+ link->_rght = list->_left;
+ link->_left = list->_rght;
+ return list;
+ }
+
+ last = list; list->_left = list->_rght = NIL(Dtlink_t*);
+ root = NIL(Dtlink_t*);
+
+ while(!root && (t = link->_rght) ) /* link->_rght is the left subtree <= obj */
+ { while((r = t->_rght) ) /* make t the maximum element */
+ LROTATE(t,r);
+
+ o = _DTOBJ(disc,t); k = _DTKEY(disc,o);
+ if(_DTCMP(dt, key, k, disc) != 0 )
+ { link->_rght = t; /* no more of this group in subtree */
+ break;
+ }
+ else if((type & (DT_REMOVE|DT_NEXT|DT_PREV)) && o == obj)
+ { link->_rght = t->_left; /* found the exact object */
+ root = t;
+ }
+ else /* add t to equal list in an order-preserving manner */
+ { link->_rght = t->_left;
+ t->_left = t->_rght = NIL(Dtlink_t*);
+ if(type&DT_NEXT )
+ { last->_left = t; last = t; }
+ else { t->_rght = list; list = t; }
+ }
+ }
+
+ while(!root && (t = link->_left) ) /* link->_left is the right subtree >= obj */
+ { while((l = t->_left) ) /* make t the minimum element */
+ RROTATE(t,l);
+
+ o = _DTOBJ(disc,t); k = _DTKEY(disc,o);
+ if(_DTCMP(dt, key, k, disc) != 0 )
+ { link->_left = t; /* no more of this group in subtree */
+ break;
+ }
+ else if((type & (DT_REMOVE|DT_NEXT|DT_PREV)) && o == obj)
+ { link->_left = t->_rght; /* found the exact object */
+ root = t;
+ }
+ else /* add t to equal list in an order-preserving manner */
+ { link->_left = t->_rght;
+ t->_left = t->_rght = NIL(Dtlink_t*);
+ if(type&DT_NEXT )
+ { t->_left = list; list = t; }
+ else { last->_rght = t; last = t; }
+ }
+ }
+
+ if(!root) /* always set a non-trivial root */
+ { root = list;
+ if(type&DT_NEXT)
+ list = list->_left;
+ else list = list->_rght;
+ }
+
+ if(list) /* add the rest of the equal-list to the proper subtree */
+ { if(type&DT_NEXT)
+ { last->_left = link->_rght;
+ link->_rght = list;
+ }
+ else
+ { last->_rght = link->_left;
+ link->_left = list;
+ }
+ }
+
+ return root;
+}
+
+#if __STD_C
+static Void_t* dttree(Dt_t* dt, Void_t* obj, int type)
+#else
+static Void_t* dttree(dt,obj,type)
+Dt_t* dt;
+Void_t* obj;
+int type;
+#endif
+{
+ int cmp;
+ Void_t *o, *k, *key;
+ Dtlink_t *root, *t, *l, *r, *me, link;
+ Dtdisc_t *disc = dt->disc;
+ Dttree_t *tree = (Dttree_t*)dt->data;
+
+ type = DTTYPE(dt, type); /* map type for upward compatibility */
+ if(!(type&DT_OPERATIONS) )
+ return NIL(Void_t*);
+
+ DTSETLOCK(dt);
+
+ if(type&(DT_FIRST|DT_LAST) )
+ DTRETURN(obj, tfirstlast(dt, type));
+ else if(type&(DT_EXTRACT|DT_RESTORE|DT_FLATTEN))
+ DTRETURN(obj, tlist(dt, (Dtlink_t*)obj, type));
+ else if(type&DT_CLEAR)
+ DTRETURN(obj, tclear(dt));
+ else if(type&DT_STAT)
+ { toptimize(dt); /* balance tree to avoid deep recursion */
+ DTRETURN(obj, tstat(dt, (Dtstat_t*)obj));
+ }
+
+ if(!obj) /* from here on, an object prototype is required */
+ DTRETURN(obj, NIL(Void_t*));
+
+ if(type&DT_RELINK) /* relinking objects after some processing */
+ { me = (Dtlink_t*)obj;
+ obj = _DTOBJ(disc,me);
+ key = _DTKEY(disc,obj);
+ }
+ else
+ { me = NIL(Dtlink_t*);
+ if(type&DT_MATCH) /* no prototype object given, just the key */
+ { key = obj;
+ obj = NIL(Void_t*);
+ }
+ else key = _DTKEY(disc,obj); /* get key from prototype object */
+ }
+
+ memset(&link, 0, sizeof(link));
+ l = r = &link; /* link._rght(_left) will be LEFT(RIGHT) tree after splaying */
+ if((root = tree->root) && _DTOBJ(disc,root) != obj) /* splay-search for a matching object */
+ { while(1)
+ { o = _DTOBJ(disc,root); k = _DTKEY(disc,o);
+ if((cmp = _DTCMP(dt,key,k,disc)) == 0)
+ break;
+ else if(cmp < 0)
+ { if((t = root->_left) )
+ { o = _DTOBJ(disc,t); k = _DTKEY(disc,o);
+ if((cmp = _DTCMP(dt,key,k,disc)) < 0)
+ { rrotate(root,t);
+ rlink(r,t);
+ if(!(root = t->_left) )
+ break;
+ }
+ else if(cmp == 0)
+ { rlink(r,root);
+ root = t;
+ break;
+ }
+ else /* if(cmp > 0) */
+ { llink(l,t);
+ rlink(r,root);
+ if(!(root = t->_rght) )
+ break;
+ }
+ }
+ else
+ { rlink(r,root);
+ root = NIL(Dtlink_t*);
+ break;
+ }
+ }
+ else /* if(cmp > 0) */
+ { if((t = root->_rght) )
+ { o = _DTOBJ(disc,t); k = _DTKEY(disc,o);
+ if((cmp = _DTCMP(dt,key,k,disc)) > 0)
+ { lrotate(root,t);
+ llink(l,t);
+ if(!(root = t->_rght) )
+ break;
+ }
+ else if(cmp == 0)
+ { llink(l,root);
+ root = t;
+ break;
+ }
+ else /* if(cmp < 0) */
+ { rlink(r,t);
+ llink(l,root);
+ if(!(root = t->_left) )
+ break;
+ }
+ }
+ else
+ { llink(l,root);
+ root = NIL(Dtlink_t*);
+ break;
+ }
+ }
+ }
+ }
+ l->_rght = root ? root->_left : NIL(Dtlink_t*);
+ r->_left = root ? root->_rght : NIL(Dtlink_t*);
+
+ if(root)
+ { if(dt->meth->type&DT_OBAG ) /* may need to reset root to the right object */
+ { if((type&(DT_ATLEAST|DT_ATMOST)) ||
+ ((type&(DT_NEXT|DT_PREV|DT_REMOVE)) && _DTOBJ(disc,root) != obj) )
+ root = troot(dt, root, &link, obj, type);
+ }
+
+ if(type&(DT_SEARCH|DT_MATCH|DT_ATMOST|DT_ATLEAST))
+ { has_root: /* reconstitute the tree */
+ root->_left = link._rght;
+ root->_rght = link._left;
+ tree->root = root;
+ DTRETURN(obj, _DTOBJ(disc,root));
+ }
+ else if(type&DT_NEXT)
+ { root->_left = link._rght;
+ root->_rght = NIL(Dtlink_t*);
+ link._rght = root;
+ dt_next:
+ if((root = link._left) )
+ { while((t = root->_left) )
+ RROTATE(root,t);
+ link._left = root->_rght;
+ goto has_root;
+ }
+ else goto no_root;
+ }
+ else if(type&DT_PREV)
+ { root->_rght = link._left;
+ root->_left = NIL(Dtlink_t*);
+ link._left = root;
+ dt_prev:
+ if((root = link._rght) )
+ { while((t = root->_rght) )
+ LROTATE(root,t);
+ link._rght = root->_left;
+ goto has_root;
+ }
+ else goto no_root;
+ }
+ else if(type&DT_REMOVE) /* remove a particular element in the tree */
+ { if(_DTOBJ(disc,root) == obj)
+ goto dt_delete;
+ else
+ { root->_left = link._rght;
+ root->_rght = link._left;
+ tree->root = root;
+ DTRETURN(obj, NIL(Void_t*));
+ }
+ }
+ else if(type&(DT_DELETE|DT_DETACH))
+ { dt_delete: /* remove an object from the dictionary */
+ obj = _DTOBJ(disc,root);
+ _dtfree(dt, root, type);
+ dt->data->size -= 1;
+ goto no_root;
+ }
+ else if(type&(DT_INSERT|DT_APPEND|DT_ATTACH))
+ { if(dt->meth->type&DT_OSET)
+ { type |= DT_SEARCH; /* for announcement */
+ goto has_root;
+ }
+ else
+ { root->_left = NIL(Dtlink_t*);
+ root->_rght = link._left;
+ link._left = root;
+ goto dt_insert;
+ }
+ }
+ else if(type&DT_RELINK) /* a duplicate */
+ { if(dt->meth->type&DT_OSET)
+ _dtfree(dt, me, DT_DELETE);
+ else
+ { me->_left = NIL(Dtlink_t*);
+ me->_rght = link._left;
+ link._left = me;
+ }
+ goto has_root;
+ }
+ }
+ else /* no matching object, tree has been split to LEFT&RIGHT subtrees */
+ { if(type&(DT_SEARCH|DT_MATCH))
+ { no_root:
+ if(!(l = link._rght) ) /* no LEFT subtree */
+ tree->root = link._left; /* tree is RIGHT tree */
+ else
+ { while((t = l->_rght) ) /* maximize root of LEFT tree */
+ { if(t->_rght)
+ LLSHIFT(l,t);
+ else LROTATE(l,t);
+ }
+ l->_rght = link._left; /* hook RIGHT tree to LEFT root */
+ tree->root = l; /* LEFT tree is now the entire tree */
+ }
+
+ if(type&(DT_DELETE|DT_DETACH|DT_REMOVE))
+ DTRETURN(obj, obj);
+ else DTRETURN(obj, NIL(Void_t*));
+ }
+ else if(type&(DT_NEXT|DT_ATLEAST) )
+ goto dt_next;
+ else if(type&(DT_PREV|DT_ATMOST) )
+ goto dt_prev;
+ else if(type&(DT_DELETE|DT_DETACH|DT_REMOVE))
+ { obj = NIL(Void_t*);
+ goto no_root;
+ }
+ else if(type&(DT_INSERT|DT_APPEND|DT_ATTACH))
+ { dt_insert:
+ if(!(root = _dtmake(dt, obj, type)) )
+ { obj = NIL(Void_t*);
+ goto no_root;
+ }
+ else
+ { dt->data->size += 1;
+ goto has_root;
+ }
+ }
+ else if(type&DT_RELINK)
+ { root = me;
+ goto has_root;
+ }
+ }
+ DTRETURN(obj, NIL(Void_t*));
+
+dt_return:
+ DTANNOUNCE(dt,obj,type);
+ DTCLRLOCK(dt);
+ return obj;
+}
+
+static int treeevent(Dt_t* dt, int event, Void_t* arg)
+{
+ Dtlink_t *l, *list;
+ ssize_t size;
+ Dttree_t *tree = (Dttree_t*)dt->data;
+
+ if(event == DT_OPEN)
+ { if(tree) /* already initialized */
+ return 0;
+ if(!(tree = (Dttree_t*)(*dt->memoryf)(dt, 0, sizeof(Dttree_t), dt->disc)) )
+ { DTERROR(dt, "Error in allocating a tree data structure");
+ return -1;
+ }
+ memset(tree, 0, sizeof(Dttree_t));
+ dt->data = (Dtdata_t*)tree;
+ return 1;
+ }
+ else if(event == DT_CLOSE)
+ { if(!tree)
+ return 0;
+ if(tree->root)
+ (void)tclear(dt);
+ (void)(*dt->memoryf)(dt, (Void_t*)tree, 0, dt->disc);
+ dt->data = NIL(Dtdata_t*);
+ return 0;
+ }
+ else if(event == DT_OPTIMIZE) /* balance the search tree */
+ { toptimize(dt);
+ return 0;
+ }
+ else return 0;
+}
+
+#if _UWIN
+
+Void_t* dtfinger(Dt_t* dt)
+{
+ return (dt && dt->meth && (dt->meth->type & DT_ORDERED)) ? (Void_t*)((Dttree_t*)dt->data)->root : NIL(Void_t*);
+}
+
+#endif
+
+/* make this method available */
+static Dtmethod_t _Dtoset = { dttree, DT_OSET, treeevent, "Dtoset" };
+static Dtmethod_t _Dtobag = { dttree, DT_OBAG, treeevent, "Dtobag" };
+__DEFINE__(Dtmethod_t*,Dtoset,&_Dtoset);
+__DEFINE__(Dtmethod_t*,Dtobag,&_Dtobag);
+
+/* backwards compatibility */
+#undef Dttree
+#if defined(__EXPORT__)
+__EXPORT__
+#endif
+__DEFINE__(Dtmethod_t*,Dttree,&_Dtoset);
+
+#ifdef NoF
+NoF(dttree)
+#endif
diff --git a/src/lib/libast/cdt/dtview.c b/src/lib/libast/cdt/dtview.c
new file mode 100644
index 0000000..94f4a54
--- /dev/null
+++ b/src/lib/libast/cdt/dtview.c
@@ -0,0 +1,157 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "dthdr.h"
+
+/* Set a view path from dict to view.
+**
+** Written by Kiem-Phong Vo (5/25/96)
+*/
+
+/* these operations must be done without viewpathing */
+#define DT_NOVIEWPATH (DT_INSERT|DT_APPEND|DT_DELETE|\
+ DT_ATTACH|DT_DETACH|DT_RELINK|DT_CLEAR| \
+ DT_FLATTEN|DT_EXTRACT|DT_RESTORE|DT_STAT)
+
+#if __STD_C
+static Void_t* dtvsearch(Dt_t* dt, reg Void_t* obj, reg int type)
+#else
+static Void_t* dtvsearch(dt,obj,type)
+Dt_t* dt;
+reg Void_t* obj;
+reg int type;
+#endif
+{
+ int cmp;
+ Dt_t *d, *p;
+ Void_t *o, *n, *oky, *nky;
+
+ if(type&DT_NOVIEWPATH)
+ return (*(dt->meth->searchf))(dt,obj,type);
+
+ o = NIL(Void_t*);
+
+ /* these ops look for the first appearance of an object of the right type */
+ if((type & (DT_MATCH|DT_SEARCH)) ||
+ ((type & (DT_FIRST|DT_LAST|DT_ATLEAST|DT_ATMOST)) && !(dt->meth->type&DT_ORDERED) ) )
+ { for(d = dt; d; d = d->view)
+ if((o = (*(d->meth->searchf))(d,obj,type)) )
+ break;
+ dt->walk = d;
+ return o;
+ }
+
+ if(dt->meth->type & DT_ORDERED) /* ordered sets/bags */
+ { if(!(type & (DT_FIRST|DT_LAST|DT_NEXT|DT_PREV|DT_ATLEAST|DT_ATMOST)) )
+ return NIL(Void_t*);
+
+ /* find the min/max element that satisfies the op requirement */
+ n = nky = NIL(Void_t*); p = NIL(Dt_t*);
+ for(d = dt; d; d = d->view)
+ { if(!(o = (*d->meth->searchf)(d, obj, type)) )
+ continue;
+ oky = _DTKEY(d->disc,o);
+
+ if(n) /* get the right one among all dictionaries */
+ { cmp = _DTCMP(d,oky,nky,d->disc);
+ if(((type & (DT_NEXT|DT_FIRST|DT_ATLEAST)) && cmp < 0) ||
+ ((type & (DT_PREV|DT_LAST|DT_ATMOST)) && cmp > 0) )
+ goto b_est;
+ }
+ else
+ { b_est: /* current best element to fit op requirement */
+ p = d;
+ n = o;
+ nky = oky;
+ }
+ }
+
+ dt->walk = p;
+ return n;
+ }
+
+ /* unordered collections */
+ if(!(type&(DT_NEXT|DT_PREV)) )
+ return NIL(Void_t*);
+
+ if(!dt->walk )
+ { for(d = dt; d; d = d->view)
+ if((o = (*(d->meth->searchf))(d, obj, DT_SEARCH)) )
+ break;
+ dt->walk = d;
+ if(!(obj = o) )
+ return NIL(Void_t*);
+ }
+
+ for(d = dt->walk, obj = (*d->meth->searchf)(d, obj, type);; )
+ { while(obj) /* keep moving until finding an uncovered object */
+ { for(p = dt; ; p = p->view)
+ { if(p == d) /* adjacent object is uncovered */
+ return obj;
+ if((*(p->meth->searchf))(p, obj, DT_SEARCH) )
+ break;
+ }
+ obj = (*d->meth->searchf)(d, obj, type);
+ }
+
+ if(!(d = dt->walk = d->view) ) /* move on to next dictionary */
+ return NIL(Void_t*);
+ else if(type&DT_NEXT)
+ obj = (*(d->meth->searchf))(d,NIL(Void_t*),DT_FIRST);
+ else obj = (*(d->meth->searchf))(d,NIL(Void_t*),DT_LAST);
+ }
+}
+
+#if __STD_C
+Dt_t* dtview(reg Dt_t* dt, reg Dt_t* view)
+#else
+Dt_t* dtview(dt,view)
+reg Dt_t* dt;
+reg Dt_t* view;
+#endif
+{
+ reg Dt_t* d;
+
+ if(view && view->meth != dt->meth) /* must use the same method */
+ return NIL(Dt_t*);
+
+ /* make sure there won't be a cycle */
+ for(d = view; d; d = d->view)
+ if(d == dt)
+ return NIL(Dt_t*);
+
+ /* no more viewing lower dictionary */
+ if((d = dt->view) )
+ d->nview -= 1;
+ dt->view = dt->walk = NIL(Dt_t*);
+
+ if(!view)
+ { dt->searchf = dt->meth->searchf;
+ return d;
+ }
+
+ /* ok */
+ dt->view = view;
+ dt->searchf = dtvsearch;
+ view->nview += 1;
+
+ return view;
+}
diff --git a/src/lib/libast/cdt/dtwalk.c b/src/lib/libast/cdt/dtwalk.c
new file mode 100644
index 0000000..05c706c
--- /dev/null
+++ b/src/lib/libast/cdt/dtwalk.c
@@ -0,0 +1,53 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "dthdr.h"
+
+/* Walk a dictionary and all dictionaries viewed through it.
+** userf: user function
+**
+** Written by Kiem-Phong Vo (5/25/96)
+*/
+
+#if __STD_C
+int dtwalk(Dt_t* dt, int (*userf)(Dt_t*, Void_t*, Void_t*), Void_t* data)
+#else
+int dtwalk(dt,userf,data)
+Dt_t* dt;
+int(* userf)();
+Void_t* data;
+#endif
+{
+ Void_t *obj, *next;
+ Dt_t *walk;
+ int rv;
+
+ for(obj = dtfirst(dt); obj; )
+ { if(!(walk = dt->walk) )
+ walk = dt;
+ next = dtnext(dt,obj);
+ if((rv = (*userf)(walk, obj, data )) < 0)
+ return rv;
+ obj = next;
+ }
+
+ return 0;
+}