aboutsummaryrefslogtreecommitdiff
path: root/src/backend/lib
diff options
context:
space:
mode:
authorMarc G. Fournier <scrappy@hub.org>1996-07-09 06:22:35 +0000
committerMarc G. Fournier <scrappy@hub.org>1996-07-09 06:22:35 +0000
commitd31084e9d1118b25fd16580d9d8c2924b5740dff (patch)
tree3179e66307d54df9c7b966543550e601eb55e668 /src/backend/lib
downloadpostgresql-PG95-1_01.tar.gz
postgresql-PG95-1_01.zip
Postgres95 1.01 Distribution - Virgin SourcesPG95-1_01
Diffstat (limited to 'src/backend/lib')
-rw-r--r--src/backend/lib/Makefile.inc20
-rw-r--r--src/backend/lib/bit.c45
-rw-r--r--src/backend/lib/dllist.c204
-rw-r--r--src/backend/lib/dllist.h72
-rw-r--r--src/backend/lib/fstack.c153
-rw-r--r--src/backend/lib/fstack.h113
-rw-r--r--src/backend/lib/hasht.c47
-rw-r--r--src/backend/lib/hasht.h23
-rw-r--r--src/backend/lib/lispsort.c56
-rw-r--r--src/backend/lib/lispsort.h18
-rw-r--r--src/backend/lib/qsort.c281
-rw-r--r--src/backend/lib/qsort.h24
-rw-r--r--src/backend/lib/stringinfo.c116
-rw-r--r--src/backend/lib/stringinfo.h47
14 files changed, 1219 insertions, 0 deletions
diff --git a/src/backend/lib/Makefile.inc b/src/backend/lib/Makefile.inc
new file mode 100644
index 00000000000..c3a46d546ce
--- /dev/null
+++ b/src/backend/lib/Makefile.inc
@@ -0,0 +1,20 @@
+#-------------------------------------------------------------------------
+#
+# Makefile.inc--
+# Makefile for the lib module (miscellaneous stuff)
+#
+# Copyright (c) 1994, Regents of the University of California
+#
+#
+# IDENTIFICATION
+# $Header: /cvsroot/pgsql/src/backend/lib/Attic/Makefile.inc,v 1.1.1.1 1996/07/09 06:21:28 scrappy Exp $
+#
+#-------------------------------------------------------------------------
+
+VPATH:=$(VPATH):$(CURDIR)/lib
+
+
+SRCS_LIB= bit.c fstack.c hasht.c lispsort.c qsort.c stringinfo.c dllist.c
+
+HEADERS+= fstack.h hasht.h lispsort.h qsort.h stringinfo.h dllist.h
+
diff --git a/src/backend/lib/bit.c b/src/backend/lib/bit.c
new file mode 100644
index 00000000000..9aa12b48502
--- /dev/null
+++ b/src/backend/lib/bit.c
@@ -0,0 +1,45 @@
+/*-------------------------------------------------------------------------
+ *
+ * bit.c--
+ * Standard bit array code.
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * $Header: /cvsroot/pgsql/src/backend/lib/Attic/bit.c,v 1.1.1.1 1996/07/09 06:21:28 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/*
+ * utils/memutils.h contains declarations of the functions in this file
+ */
+#include "utils/memutils.h"
+
+void
+BitArraySetBit(BitArray bitArray, BitIndex bitIndex)
+{
+ bitArray[bitIndex/BitsPerByte]
+ |= (1 << (BitsPerByte - (bitIndex % BitsPerByte) - 1));
+ return;
+}
+
+void
+BitArrayClearBit(BitArray bitArray, BitIndex bitIndex)
+{
+ bitArray[bitIndex/BitsPerByte]
+ &= ~(1 << (BitsPerByte - (bitIndex % BitsPerByte) - 1));
+ return;
+}
+
+bool
+BitArrayBitIsSet(BitArray bitArray, BitIndex bitIndex)
+{
+ return( (bool) (((bitArray[bitIndex / BitsPerByte] &
+ (1 << (BitsPerByte - (bitIndex % BitsPerByte)
+ - 1)
+ )
+ ) != 0 ) ? 1 : 0) );
+}
+
diff --git a/src/backend/lib/dllist.c b/src/backend/lib/dllist.c
new file mode 100644
index 00000000000..92526632c9f
--- /dev/null
+++ b/src/backend/lib/dllist.c
@@ -0,0 +1,204 @@
+/*-------------------------------------------------------------------------
+ *
+ * dllist.c--
+ * this is a simple doubly linked list implementation
+ * replaces the old simplelists stuff
+ * the elements of the lists are void*
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * $Header: /cvsroot/pgsql/src/backend/lib/dllist.c,v 1.1.1.1 1996/07/09 06:21:28 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+#include "lib/dllist.h"
+
+Dllist*
+DLNewList()
+{
+ Dllist* l;
+
+ l = malloc(sizeof(Dllist));
+ l->dll_head = 0;
+ l->dll_tail = 0;
+
+ return l;
+}
+
+ /* free up a list and all the nodes in it*/
+void
+DLFreeList(Dllist* l)
+{
+ Dlelem* curr;
+
+ while ( (curr = DLRemHead(l)) != 0)
+ free(curr);
+
+ free(l);
+}
+
+Dlelem*
+DLNewElem(void* val)
+{
+ Dlelem* e;
+ e = malloc(sizeof(Dlelem));
+ e->dle_next = 0;
+ e->dle_prev = 0;
+ e->dle_val = val;
+ e->dle_list = 0;
+ return e;
+}
+
+void
+DLFreeElem(Dlelem* e)
+{
+ free(e);
+}
+
+Dlelem*
+DLGetHead(Dllist* l)
+{
+ return (l ? l->dll_head : 0);
+}
+
+/* get the value stored in the first element */
+void*
+DLGetHeadVal(Dllist* l)
+{
+ Dlelem* e = DLGetHead(l);
+
+ return (e ? e->dle_val : 0);
+}
+
+Dlelem*
+DLGetTail(Dllist* l)
+{
+ return (l ? l->dll_tail : 0);
+}
+
+/* get the value stored in the first element */
+void*
+DLGetTailVal(Dllist* l)
+{
+ Dlelem* e = DLGetTail(l);
+
+ return (e ? e->dle_val : 0);
+}
+
+
+Dlelem*
+DLGetPred(Dlelem* e) /* get predecessor */
+{
+ return (e ? e->dle_prev : 0);
+}
+
+Dlelem*
+DLGetSucc(Dlelem* e) /* get successor */
+{
+ return (e ? e->dle_next : 0);
+}
+
+void
+DLRemove(Dlelem* e)
+{
+ Dllist* l;
+
+ if (e->dle_prev)
+ e->dle_prev->dle_next = e->dle_next;
+ if (e->dle_next)
+ e->dle_next->dle_prev = e->dle_prev;
+
+ /* check to see if we're removing the head or tail */
+ l = e->dle_list;
+ if (e == l->dll_head)
+ DLRemHead(l);
+ if (e == l->dll_tail)
+ DLRemTail(l);
+
+}
+
+void
+DLAddHead(Dllist* l, Dlelem* e)
+{
+ e->dle_list = l;
+
+ if (l->dll_head) {
+ l->dll_head->dle_prev = e;
+ e->dle_next = l->dll_head;
+ }
+ e->dle_prev = 0;
+ l->dll_head = e;
+
+ if (l->dll_tail == 0) /* if this is first element added */
+ l->dll_tail = l->dll_head;
+}
+
+void
+DLAddTail(Dllist* l, Dlelem* e)
+{
+ e->dle_list = l;
+
+ if (l->dll_tail) {
+ l->dll_tail->dle_next = e;
+ e->dle_prev = l->dll_tail;
+ }
+ e->dle_next = 0;
+ l->dll_tail = e;
+
+ if (l->dll_head == 0) /* if this is first element added */
+ l->dll_head = l->dll_tail;
+}
+
+Dlelem*
+DLRemHead(Dllist* l)
+{
+ /* remove and return the head */
+ Dlelem* result;
+
+ if (l->dll_head == 0)
+ return 0;
+
+ result = l->dll_head;
+ if (l->dll_head->dle_next) {
+ l->dll_head->dle_next->dle_prev = 0;
+ }
+
+ l->dll_head = l->dll_head->dle_next;
+
+ result->dle_next = 0;
+ result->dle_list = 0;
+
+ if (result == l->dll_tail) /* if the head is also the tail */
+ l->dll_tail = 0;
+
+ return result;
+}
+
+Dlelem*
+DLRemTail(Dllist* l)
+{
+ /* remove and return the tail */
+ Dlelem* result;
+
+ if (l->dll_tail == 0 )
+ return 0;
+
+ result = l->dll_tail;
+ if (l->dll_tail->dle_prev) {
+ l->dll_tail->dle_prev->dle_next = 0;
+ }
+ l->dll_tail = l->dll_tail->dle_prev;
+
+ result->dle_prev = 0;
+ result->dle_list = 0;
+
+ if (result == l->dll_head) /* if the tail is also the head */
+ l->dll_head = 0;
+
+ return result;
+}
+
diff --git a/src/backend/lib/dllist.h b/src/backend/lib/dllist.h
new file mode 100644
index 00000000000..cd9ac42a12f
--- /dev/null
+++ b/src/backend/lib/dllist.h
@@ -0,0 +1,72 @@
+/*-------------------------------------------------------------------------
+ *
+ * dllist.h--
+ * simple doubly linked list primitives
+ * the elements of the list are void* so the lists can contain
+ * anything
+ * Dlelem can only be in one list at a time
+ *
+ *
+ * Here's a small example of how to use Dllist's :
+ *
+ * Dllist *lst;
+ * Dlelem *elt;
+ * void *in_stuff; -- stuff to stick in the list
+ * void *out_stuff
+ *
+ * lst = DLNewList(); -- make a new dllist
+ * DLAddHead(lst, DLNewElem(in_stuff)); -- add a new element to the list
+ * with in_stuff as the value
+ * ...
+ * elt = DLGetHead(lst); -- retrieve the head element
+ * out_stuff = (void*)DLE_VAL(elt); -- get the stuff out
+ * DLRemove(elt); -- removes the element from its list
+ * DLFreeElem(elt); -- free the element since we don't
+ * use it anymore
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: dllist.h,v 1.1.1.1 1996/07/09 06:21:28 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef DLLIST_H
+#define DLLIST_H
+
+#include "c.h"
+
+struct Dllist;
+struct Dlelem;
+
+typedef struct Dlelem {
+ struct Dlelem *dle_next; /* next element */
+ struct Dlelem *dle_prev; /* previous element */
+ void *dle_val; /* value of the element */
+ struct Dllist *dle_list; /* what list this element is in */
+} Dlelem;
+
+typedef struct Dllist {
+ Dlelem *dll_head;
+ Dlelem *dll_tail;
+} Dllist;
+
+extern Dllist* DLNewList(); /* initialize a new list */
+extern void DLFreeList(Dllist*); /* free up a list and all the nodes in it*/
+extern Dlelem* DLNewElem(void* val);
+extern void DLFreeElem(Dlelem*);
+extern Dlelem* DLGetHead(Dllist*);
+extern Dlelem* DLGetTail(Dllist*);
+extern void* DLGetHeadVal(Dllist*);
+extern void* DLGetTailVal(Dllist*);
+extern Dlelem* DLGetPred(Dlelem*); /* get predecessor */
+extern Dlelem* DLGetSucc(Dlelem*); /* get successor */
+extern void DLRemove(Dlelem*); /* removes node from list*/
+extern void DLAddHead(Dllist* list, Dlelem* node);
+extern void DLAddTail(Dllist* list, Dlelem* node);
+extern Dlelem* DLRemHead(Dllist* list); /* remove and return the head */
+extern Dlelem* DLRemTail(Dllist* list); /* remove and return the tail */
+
+#define DLE_VAL(x) (x->dle_val)
+
+#endif /* DLLIST_H */
diff --git a/src/backend/lib/fstack.c b/src/backend/lib/fstack.c
new file mode 100644
index 00000000000..541767183d8
--- /dev/null
+++ b/src/backend/lib/fstack.c
@@ -0,0 +1,153 @@
+/*-------------------------------------------------------------------------
+ *
+ * fstack.c--
+ * Fixed format stack definitions.
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * $Header: /cvsroot/pgsql/src/backend/lib/Attic/fstack.c,v 1.1.1.1 1996/07/09 06:21:28 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "c.h"
+#include "lib/fstack.h"
+
+/*
+ * Internal function definitions
+ */
+
+/*
+ * FixedItemIsValid --
+ * True iff item is valid.
+ */
+#define FixedItemIsValid(item) PointerIsValid(item)
+
+/*
+ * FixedStackGetItemBase --
+ * Returns base of enclosing structure.
+ */
+#define FixedStackGetItemBase(stack, item) \
+ ((Pointer)((char *)(item) - (stack)->offset))
+
+/*
+ * FixedStackGetItem --
+ * Returns item of given pointer to enclosing structure.
+ */
+#define FixedStackGetItem(stack, pointer) \
+ ((FixedItem)((char *)(pointer) + (stack)->offset))
+
+/*
+ * External functions
+ */
+
+/*
+ * FixedStackIsValid --
+ * True iff stack is valid.
+ */
+static bool
+FixedStackIsValid(FixedStack stack)
+{
+ return ((bool)PointerIsValid(stack));
+}
+
+
+void
+FixedStackInit(FixedStack stack, Offset offset)
+{
+ AssertArg(PointerIsValid(stack));
+
+ stack->top = NULL;
+ stack->offset = offset;
+}
+
+Pointer
+FixedStackPop(FixedStack stack)
+{
+ Pointer pointer;
+
+ AssertArg(FixedStackIsValid(stack));
+
+ if (!PointerIsValid(stack->top)) {
+ return (NULL);
+ }
+
+ pointer = FixedStackGetItemBase(stack, stack->top);
+ stack->top = stack->top->next;
+
+ return (pointer);
+}
+
+void
+FixedStackPush(FixedStack stack, Pointer pointer)
+{
+ FixedItem item = FixedStackGetItem(stack, pointer);
+
+ AssertArg(FixedStackIsValid(stack));
+ AssertArg(PointerIsValid(pointer));
+
+ item->next = stack->top;
+ stack->top = item;
+}
+
+
+/*
+ * FixedStackContains --
+ * True iff ordered stack contains given element.
+ *
+ * Note:
+ * This is inefficient. It is intended for debugging use only.
+ *
+ * Exceptions:
+ * BadArg if stack is invalid.
+ * BadArg if pointer is invalid.
+ */
+static bool
+FixedStackContains(FixedStack stack, Pointer pointer)
+{
+ FixedItem next;
+ FixedItem item;
+
+ AssertArg(FixedStackIsValid(stack));
+ AssertArg(PointerIsValid(pointer));
+
+ item = FixedStackGetItem(stack, pointer);
+
+ for (next = stack->top; FixedItemIsValid(next); next = next->next) {
+ if (next == item) {
+ return (true);
+ }
+ }
+ return (false);
+}
+
+Pointer
+FixedStackGetTop(FixedStack stack)
+{
+ AssertArg(FixedStackIsValid(stack));
+
+ if (!PointerIsValid(stack->top)) {
+ return (NULL);
+ }
+
+ return (FixedStackGetItemBase(stack, stack->top));
+}
+
+Pointer
+FixedStackGetNext(FixedStack stack, Pointer pointer)
+{
+ FixedItem item;
+
+ /* AssertArg(FixedStackIsValid(stack)); */
+ /* AssertArg(PointerIsValid(pointer)); */
+ AssertArg(FixedStackContains(stack, pointer));
+
+ item = FixedStackGetItem(stack, pointer)->next;
+
+ if (!PointerIsValid(item)) {
+ return (NULL);
+ }
+
+ return(FixedStackGetItemBase(stack, item));
+}
diff --git a/src/backend/lib/fstack.h b/src/backend/lib/fstack.h
new file mode 100644
index 00000000000..b0b1df00d83
--- /dev/null
+++ b/src/backend/lib/fstack.h
@@ -0,0 +1,113 @@
+/*-------------------------------------------------------------------------
+ *
+ * fstack.h--
+ * Fixed format stack definitions.
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: fstack.h,v 1.1.1.1 1996/07/09 06:21:29 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+/*
+ * Note:
+ * Fixed format stacks assist in the construction of FIFO stacks of
+ * fixed format structures. Structures which are to be stackable
+ * should contain a FixedItemData component. A stack is initilized
+ * with the offset of the FixedItemData component of the structure
+ * it will hold. By doing so, push and pop operations are simplified
+ * for the callers. All references to stackable items are pointers
+ * to the base of the structure instead of pointers to the
+ * FixedItemData component.
+ *
+ */
+#ifndef FSTACK_H
+#define FSTACK_H
+
+#include "c.h"
+
+/*
+ * FixedItem --
+ * Fixed format stackable item chain component.
+ *
+ * Note:
+ * Structures must contain one FixedItemData component per stack in
+ * which it will be an item.
+ */
+typedef struct FixedItemData FixedItemData;
+typedef FixedItemData *FixedItem;
+
+struct FixedItemData {
+ FixedItem next; /* next item or NULL */
+};
+
+/*
+ * FixedStack --
+ * Fixed format stack.
+ */
+typedef struct FixedStackData {
+ FixedItem top; /* Top item on the stack or NULL */
+ Offset offset; /* Offset from struct base to item */
+ /* this could be signed short int! */
+} FixedStackData;
+
+typedef FixedStackData *FixedStack;
+
+/*
+ * FixedStackInit --
+ * Iniitializes stack for structures with given fixed component offset.
+ *
+ * Exceptions:
+ * BadArg if stack is invalid pointer.
+ */
+extern void FixedStackInit(FixedStack stack, Offset offset);
+
+/*
+ * FixedStackPop --
+ * Returns pointer to top structure on stack or NULL if empty stack.
+ *
+ * Exceptions:
+ * BadArg if stack is invalid.
+ */
+Pointer FixedStackPop(FixedStack stack);
+
+/*
+ * FixedStackPush --
+ * Places structure associated with pointer onto top of stack.
+ *
+ * Exceptions:
+ * BadArg if stack is invalid.
+ * BadArg if pointer is invalid.
+ */
+extern void FixedStackPush(FixedStack stack, Pointer pointer);
+
+/*
+ * FixedStackGetTop --
+ * Returns pointer to top structure of a stack. This item is not poped.
+ *
+ * Note:
+ * This is not part of the normal stack interface. It is intended for
+ * debugging use only.
+ *
+ * Exceptions:
+ * BadArg if stack is invalid.
+ */
+extern Pointer FixedStackGetTop(FixedStack stack);
+
+/*
+ * FixedStackGetNext --
+ * Returns pointer to next structure after pointer of a stack.
+ *
+ * Note:
+ * This is not part of the normal stack interface. It is intended for
+ * debugging use only.
+ *
+ * Exceptions:
+ * BadArg if stack is invalid.
+ * BadArg if pointer is invalid.
+ * BadArg if stack does not contain pointer.
+ */
+extern Pointer FixedStackGetNext(FixedStack stack, Pointer pointer);
+
+#endif /* FSTACK_H */
diff --git a/src/backend/lib/hasht.c b/src/backend/lib/hasht.c
new file mode 100644
index 00000000000..5487bed44bc
--- /dev/null
+++ b/src/backend/lib/hasht.c
@@ -0,0 +1,47 @@
+/*-------------------------------------------------------------------------
+ *
+ * hasht.c--
+ * hash table related functions that are not directly supported
+ * by the hashing packages under utils/hash.
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * $Header: /cvsroot/pgsql/src/backend/lib/Attic/hasht.c,v 1.1.1.1 1996/07/09 06:21:29 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "c.h"
+#include "utils/memutils.h"
+#include "utils/elog.h"
+#include "utils/hsearch.h"
+#include "lib/hasht.h"
+
+/* -----------------------------------
+ * HashTableWalk
+ *
+ * call function on every element in hashtable
+ * one extra argument, arg may be supplied
+ * -----------------------------------
+ */
+void
+HashTableWalk(HTAB *hashtable, HashtFunc function, int arg)
+{
+ long *hashent;
+ long *data;
+ int keysize;
+
+ keysize = hashtable->hctl->keysize;
+ (void)hash_seq((HTAB *)NULL);
+ while ((hashent = hash_seq(hashtable)) != (long *) TRUE) {
+ if (hashent == NULL)
+ elog(FATAL, "error in HashTableWalk.");
+ /*
+ * XXX the corresponding hash table insertion does NOT
+ * LONGALIGN -- make sure the keysize is ok
+ */
+ data = (long *) LONGALIGN((char*) hashent + keysize);
+ (*function)(data, arg);
+ }
+}
diff --git a/src/backend/lib/hasht.h b/src/backend/lib/hasht.h
new file mode 100644
index 00000000000..543c8c95d84
--- /dev/null
+++ b/src/backend/lib/hasht.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * hasht.h--
+ * hash table related functions that are not directly supported
+ * under utils/hash.
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: hasht.h,v 1.1.1.1 1996/07/09 06:21:29 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef HASHT_H
+#define HASHT_H
+
+#include "utils/hsearch.h"
+
+typedef void (*HashtFunc)();
+
+extern void HashTableWalk(HTAB *hashtable, HashtFunc function, int arg);
+
+#endif /* HASHT_H */
diff --git a/src/backend/lib/lispsort.c b/src/backend/lib/lispsort.c
new file mode 100644
index 00000000000..0cf49bf0c0b
--- /dev/null
+++ b/src/backend/lib/lispsort.c
@@ -0,0 +1,56 @@
+/*-------------------------------------------------------------------------
+ *
+ * lispsort.c--
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * $Header: /cvsroot/pgsql/src/backend/lib/Attic/lispsort.c,v 1.1.1.1 1996/07/09 06:21:29 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+#include "nodes/pg_list.h"
+#include "nodes/primnodes.h"
+#include "nodes/plannodes.h"
+#include "nodes/relation.h"
+#include "lib/lispsort.h"
+#include "utils/palloc.h"
+#include "lib/qsort.h"
+
+/*
+** lisp_qsort: Takes a lisp list as input, copies it into an array of lisp
+** nodes which it sorts via qsort() with the comparison function
+** as passed into lisp_qsort(), and returns a new list with
+** the nodes sorted. The old list is *not* freed or modified (?)
+*/
+List *lisp_qsort(List *the_list, /* the list to be sorted */
+ int (*compare)()) /* function to compare two nodes */
+{
+ int i;
+ size_t num;
+ List **nodearray;
+ List *tmp, *output;
+
+ /* find size of list */
+ num = length(the_list);
+ if (num < 2)
+ return(copyObject(the_list));
+
+ /* copy elements of the list into an array */
+ nodearray = (List **) palloc(num * sizeof(List *));
+
+ for (tmp = the_list, i = 0; tmp != NIL; tmp = lnext(tmp), i++)
+ nodearray[i] = copyObject(lfirst(tmp));
+
+ /* sort the array */
+ pg_qsort(nodearray, num, sizeof(List *), compare);
+
+ /* lcons together the array elements */
+ output = NIL;
+ for (i = num - 1; i >= 0; i--)
+ output = lcons(nodearray[i], output);
+
+ return(output);
+}
diff --git a/src/backend/lib/lispsort.h b/src/backend/lib/lispsort.h
new file mode 100644
index 00000000000..e49ee543622
--- /dev/null
+++ b/src/backend/lib/lispsort.h
@@ -0,0 +1,18 @@
+/*-------------------------------------------------------------------------
+ *
+ * lispsort.h--
+ *
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: lispsort.h,v 1.1.1.1 1996/07/09 06:21:29 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LISPSORT_H
+#define LISPSORT_H
+
+extern List *lisp_qsort(List *the_list, int (*compare)());
+
+#endif /* LISPSORT_H */
diff --git a/src/backend/lib/qsort.c b/src/backend/lib/qsort.c
new file mode 100644
index 00000000000..5af64bf8006
--- /dev/null
+++ b/src/backend/lib/qsort.c
@@ -0,0 +1,281 @@
+/*-------------------------------------------------------------------------
+ *
+ * qsort.c--
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * $Header: /cvsroot/pgsql/src/backend/lib/Attic/qsort.c,v 1.1.1.1 1996/07/09 06:21:29 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+/*-
+ * Copyright (c) 1980, 1983, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)qsort.c 5.9 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
+
+#include "postgres.h"
+#include "lib/qsort.h"
+
+/*
+ * MTHRESH is the smallest partition for which we compare for a median
+ * value instead of using the middle value.
+ */
+#define MTHRESH 6
+
+/*
+ * THRESH is the minimum number of entries in a partition for continued
+ * partitioning.
+ */
+#define THRESH 4
+
+static void insertion_sort(char* bot, int nmemb, int size, int (*compar)());
+static void quick_sort(char* bot, int nmemb, int size, int (*compar)());
+
+void pg_qsort(void *bot,
+ size_t nmemb,
+ size_t size,
+ int (*compar)(void *, void *))
+{
+
+ if (nmemb <= 1)
+ return;
+
+ if (nmemb >= THRESH)
+ quick_sort(bot, nmemb, size, compar);
+ else
+ insertion_sort(bot, nmemb, size, compar);
+}
+
+/*
+ * Swap two areas of size number of bytes. Although qsort(3) permits random
+ * blocks of memory to be sorted, sorting pointers is almost certainly the
+ * common case (and, were it not, could easily be made so). Regardless, it
+ * isn't worth optimizing; the SWAP's get sped up by the cache, and pointer
+ * arithmetic gets lost in the time required for comparison function calls.
+ */
+#define SWAP(a, b) { \
+ cnt = size; \
+ do { \
+ ch = *a; \
+ *a++ = *b; \
+ *b++ = ch; \
+ } while (--cnt); \
+}
+
+/*
+ * Knuth, Vol. 3, page 116, Algorithm Q, step b, argues that a single pass
+ * of straight insertion sort after partitioning is complete is better than
+ * sorting each small partition as it is created. This isn't correct in this
+ * implementation because comparisons require at least one (and often two)
+ * function calls and are likely to be the dominating expense of the sort.
+ * Doing a final insertion sort does more comparisons than are necessary
+ * because it compares the "edges" and medians of the partitions which are
+ * known to be already sorted.
+ *
+ * This is also the reasoning behind selecting a small THRESH value (see
+ * Knuth, page 122, equation 26), since the quicksort algorithm does less
+ * comparisons than the insertion sort.
+ */
+#define SORT(bot, n) { \
+ if (n > 1) \
+ if (n == 2) { \
+ t1 = bot + size; \
+ if (compar(t1, bot) < 0) \
+ SWAP(t1, bot); \
+ } else \
+ insertion_sort(bot, n, size, compar); \
+}
+
+static void
+quick_sort(char* bot, int nmemb, int size, int (*compar)())
+{
+ register int cnt;
+ register u_char ch;
+ register char *top, *mid, *t1, *t2;
+ register int n1, n2;
+ char *bsv;
+
+ /* bot and nmemb must already be set. */
+partition:
+
+ /* find mid and top elements */
+ mid = bot + size * (nmemb >> 1);
+ top = bot + (nmemb - 1) * size;
+
+ /*
+ * Find the median of the first, last and middle element (see Knuth,
+ * Vol. 3, page 123, Eq. 28). This test order gets the equalities
+ * right.
+ */
+ if (nmemb >= MTHRESH) {
+ n1 = compar(bot, mid);
+ n2 = compar(mid, top);
+ if (n1 < 0 && n2 > 0)
+ t1 = compar(bot, top) < 0 ? top : bot;
+ else if (n1 > 0 && n2 < 0)
+ t1 = compar(bot, top) > 0 ? top : bot;
+ else
+ t1 = mid;
+
+ /* if mid element not selected, swap selection there */
+ if (t1 != mid) {
+ SWAP(t1, mid);
+ mid -= size;
+ }
+ }
+
+ /* Standard quicksort, Knuth, Vol. 3, page 116, Algorithm Q. */
+#define didswap n1
+#define newbot t1
+#define replace t2
+ didswap = 0;
+ for (bsv = bot;;) {
+ for (; bot < mid && compar(bot, mid) <= 0; bot += size);
+ while (top > mid) {
+ if (compar(mid, top) <= 0) {
+ top -= size;
+ continue;
+ }
+ newbot = bot + size; /* value of bot after swap */
+ if (bot == mid) /* top <-> mid, mid == top */
+ replace = mid = top;
+ else { /* bot <-> top */
+ replace = top;
+ top -= size;
+ }
+ goto swap;
+ }
+ if (bot == mid)
+ break;
+
+ /* bot <-> mid, mid == bot */
+ replace = mid;
+ newbot = mid = bot; /* value of bot after swap */
+ top -= size;
+
+swap: SWAP(bot, replace);
+ bot = newbot;
+ didswap = 1;
+ }
+
+ /*
+ * Quicksort behaves badly in the presence of data which is already
+ * sorted (see Knuth, Vol. 3, page 119) going from O N lg N to O N^2.
+ * To avoid this worst case behavior, if a re-partitioning occurs
+ * without swapping any elements, it is not further partitioned and
+ * is insert sorted. This wins big with almost sorted data sets and
+ * only loses if the data set is very strangely partitioned. A fix
+ * for those data sets would be to return prematurely if the insertion
+ * sort routine is forced to make an excessive number of swaps, and
+ * continue the partitioning.
+ */
+ if (!didswap) {
+ insertion_sort(bsv, nmemb, size, compar);
+ return;
+ }
+
+ /*
+ * Re-partition or sort as necessary. Note that the mid element
+ * itself is correctly positioned and can be ignored.
+ */
+#define nlower n1
+#define nupper n2
+ bot = bsv;
+ nlower = (mid - bot) / size; /* size of lower partition */
+ mid += size;
+ nupper = nmemb - nlower - 1; /* size of upper partition */
+
+ /*
+ * If must call recursively, do it on the smaller partition; this
+ * bounds the stack to lg N entries.
+ */
+ if (nlower > nupper) {
+ if (nupper >= THRESH)
+ quick_sort(mid, nupper, size, compar);
+ else {
+ SORT(mid, nupper);
+ if (nlower < THRESH) {
+ SORT(bot, nlower);
+ return;
+ }
+ }
+ nmemb = nlower;
+ } else {
+ if (nlower >= THRESH)
+ quick_sort(bot, nlower, size, compar);
+ else {
+ SORT(bot, nlower);
+ if (nupper < THRESH) {
+ SORT(mid, nupper);
+ return;
+ }
+ }
+ bot = mid;
+ nmemb = nupper;
+ }
+ goto partition;
+}
+
+static void
+insertion_sort(char* bot, int nmemb, int size, int (*compar)())
+{
+ register int cnt;
+ register u_char ch;
+ register char *s1, *s2, *t1, *t2, *top;
+
+ /*
+ * A simple insertion sort (see Knuth, Vol. 3, page 81, Algorithm
+ * S). Insertion sort has the same worst case as most simple sorts
+ * (O N^2). It gets used here because it is (O N) in the case of
+ * sorted data.
+ */
+ top = bot + nmemb * size;
+ for (t1 = bot + size; t1 < top;) {
+ for (t2 = t1; (t2 -= size) >= bot && compar(t1, t2) < 0;);
+ if (t1 != (t2 += size)) {
+ /* Bubble bytes up through each element. */
+ for (cnt = size; cnt--; ++t1) {
+ ch = *t1;
+ for (s1 = s2 = t1; (s2 -= size) >= t2; s1 = s2)
+ *s1 = *s2;
+ *s1 = ch;
+ }
+ } else
+ t1 += size;
+ }
+}
diff --git a/src/backend/lib/qsort.h b/src/backend/lib/qsort.h
new file mode 100644
index 00000000000..d81d4e2e070
--- /dev/null
+++ b/src/backend/lib/qsort.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * qsort.h--
+ *
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: qsort.h,v 1.1.1.1 1996/07/09 06:21:29 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef QSORT_H
+#define QSORT_H
+
+#include <sys/types.h>
+
+extern void pg_qsort(void *bot,
+ size_t nmemb,
+ size_t size,
+ int (*compar)(void *, void *));
+
+#endif /* QSORT_H */
+
diff --git a/src/backend/lib/stringinfo.c b/src/backend/lib/stringinfo.c
new file mode 100644
index 00000000000..7167ffcf65c
--- /dev/null
+++ b/src/backend/lib/stringinfo.c
@@ -0,0 +1,116 @@
+/*-------------------------------------------------------------------------
+ *
+ * stringinfo.c--
+ * These are routines that can be used to write informations to a string,
+ * without having to worry about string lengths, space allocation etc.
+ * Ideally the interface should look like the file i/o interface,
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * $Header: /cvsroot/pgsql/src/backend/lib/stringinfo.c,v 1.1.1.1 1996/07/09 06:21:29 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <string.h>
+#include "postgres.h"
+#include "nodes/pg_list.h"
+#include "lib/stringinfo.h"
+#include "utils/elog.h"
+#include "utils/palloc.h"
+
+/*---------------------------------------------------------------------
+ * makeStringInfo
+ *
+ * Create a StringInfoData & return a pointer to it.
+ *
+ *---------------------------------------------------------------------
+ */
+StringInfo
+makeStringInfo()
+{
+ StringInfo res;
+ long size;
+
+ res = (StringInfo) palloc(sizeof(StringInfoData));
+ if (res == NULL) {
+ elog(WARN, "makeStringInfo: Out of memory!");
+ }
+
+ size = 100;
+ res->data = palloc(size);
+ if (res->data == NULL) {
+ elog(WARN,
+ "makeStringInfo: Out of memory! (%ld bytes requested)", size);
+ }
+ res->maxlen = size;
+ res->len = 0;
+ /*
+ * NOTE: we must initialize `res->data' to the empty string because
+ * we use 'strcat' in 'appendStringInfo', which of course it always
+ * expects a null terminated string.
+ */
+ res->data[0] = '\0';
+
+ return(res);
+}
+
+/*---------------------------------------------------------------------
+ * appendStringInfo
+ *
+ * append to the current 'StringInfo' a new string.
+ * If there is not enough space in the current 'data', then reallocate
+ * some more...
+ *
+ * NOTE: if we reallocate space, we pfree the old one!
+ *---------------------------------------------------------------------
+ */
+void
+appendStringInfo(StringInfo str, char *buffer)
+{
+ int buflen, newlen;
+ char *s;
+
+ Assert((str!=NULL));
+
+ /*
+ * do we have enough space to append the new string?
+ * (don't forget to count the null string terminating char!)
+ * If no, then reallocate some more.
+ */
+ buflen = strlen(buffer);
+ if (buflen + str->len >= str->maxlen-1) {
+ /*
+ * how much more space to allocate ?
+ * Let's say double the current space...
+ * However we must check if this is enough!
+ */
+ newlen = 2 * str->len;
+ while (buflen + str->len >= newlen-1) {
+ newlen = 2 * newlen;
+ }
+ /*
+ * allocate enough space.
+ */
+ s = palloc(newlen);
+ if (s==NULL) {
+ elog(WARN,
+ "appendStringInfo: Out of memory (%d bytes requested)",
+ newlen);
+ }
+ memmove(s, str->data, str->len+1);
+ pfree(str->data);
+ str->maxlen = newlen;
+ str->data = s;
+ }
+
+ /*
+ * OK, we have enough space now, append 'buffer' at the
+ * end of the string & update the string length.
+ * NOTE: this is a text string (i.e. printable characters)
+ * so 'strcat' will do the job (no need to use 'bcopy' et all...)
+ */
+ (void) strcat(str->data, buffer);
+ str->len += buflen;
+}
diff --git a/src/backend/lib/stringinfo.h b/src/backend/lib/stringinfo.h
new file mode 100644
index 00000000000..717f2ad5985
--- /dev/null
+++ b/src/backend/lib/stringinfo.h
@@ -0,0 +1,47 @@
+/*-------------------------------------------------------------------------
+ *
+ * stringinfo.h--
+ * Declarations/definitons for "string" functions.
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: stringinfo.h,v 1.1.1.1 1996/07/09 06:21:29 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef STRINGINFO_H
+#define STRINGINFO_H
+
+/*#include "c.h" */ /* for 'String' */
+
+/*-------------------------
+ * StringInfoData holds information about a string.
+ * 'data' is the string.
+ * 'len' is the current string length (as returned by 'strlen')
+ * 'maxlen' is the size in bytes of 'data', i.e. the maximum string
+ * size (includeing the terminating '\0' char) that we can
+ * currently store in 'data' without having to reallocate
+ * more space.
+ */
+typedef struct StringInfoData {
+ char *data;
+ int maxlen;
+ int len;
+} StringInfoData;
+
+typedef StringInfoData *StringInfo;
+
+/*------------------------
+ * makeStringInfo
+ * create a 'StringInfoData' & return a pointer to it.
+ */
+extern StringInfo makeStringInfo(void);
+
+/*------------------------
+ * appendStringInfo
+ * similar to 'strcat' but reallocates more space if necessary...
+ */
+extern void appendStringInfo(StringInfo str, char *buffer);
+
+#endif /* STRINGINFO_H */