Index: /trunk/archive/pslib/src/Utils/tst_array.c
===================================================================
--- /trunk/archive/pslib/src/Utils/tst_array.c	(revision 258)
+++ /trunk/archive/pslib/src/Utils/tst_array.c	(revision 258)
@@ -0,0 +1,52 @@
+#include "psUtils.h"
+
+typedef struct {
+    int x, y;
+} psXY;
+
+psXY *psXYAlloc(void)
+{
+    return psAlloc(sizeof(psXY));
+}
+
+void psXYFree(psXY *xy)
+{
+    psFree(xy);
+}
+
+PS_DECLARE_ARRAY_TYPE(psXY);
+PS_CREATE_ARRAY_TYPE(psXY);
+
+PS_DECLARE_ARRAY_PTR_TYPE(psXY);
+PS_CREATE_ARRAY_PTR_TYPE(psXY);
+
+int main(void)
+{
+    psXYArray *t = psXYArrayAlloc(10, 15);
+    psXYPtrArray *pt = psXYPtrArrayAlloc(10, 10);
+
+    for (int i = 0; i < t->n; i++) {
+	t->arr[i].x = i;
+	pt->arr[i]->y = 10*i;
+    }
+
+    t = psXYArrayRealloc(t, 5);
+    t = psXYArrayRealloc(t, 8);
+
+    for (int i = 0; i < t->n; i++) {
+	printf("%d %d  ", t->arr[i].x, pt->arr[i]->y);
+    }
+    printf("\n");
+    
+    psXYArrayFree(t);
+
+    psXY *xy = psMemDecrRefCounter(pt->arr[0]);
+    pt->arr[0] = NULL;
+    psXYFree(xy);    
+    
+    psXYPtrArrayFree(pt);
+
+    psMemCheckLeaks(0, NULL, stderr);
+
+    return 0;
+}
Index: /trunk/archive/pslib/src/Utils/tst_dlist.c
===================================================================
--- /trunk/archive/pslib/src/Utils/tst_dlist.c	(revision 258)
+++ /trunk/archive/pslib/src/Utils/tst_dlist.c	(revision 258)
@@ -0,0 +1,80 @@
+//#include <stdlib.h>
+#include <stdio.h>
+#include "psUtils.h"
+
+
+typedef struct { int i; } X;
+static X *xAlloc(int i) { X *x = psAlloc(sizeof(X)); x->i = i; return x; }
+static void xFree(X *x) { psFree(x); }
+
+int main(void)
+{
+    psDlist *list = psDlistAlloc(NULL);	// list of metadata
+
+    psDlistAppend(list, xAlloc(1));
+    psDlistAppend(list, xAlloc(2));
+    psDlistAppend(list, xAlloc(3));
+    /*
+     * Print that data
+     */
+    for (psDlistElem *ptr = list->head; ptr != NULL; ptr = ptr->next) {
+	printf("%d ", ((X *)(ptr->data))->i);
+    }
+    printf("\n");
+    /*
+     * Print it again
+     */
+    (void)psDlistGet(list, PS_DLIST_TAIL); // initialise iterator
+    X *x = NULL;
+    while ((x = psDlistGet(list, PS_DLIST_PREV)) != NULL) {
+	printf("%d ", x->i);
+    }
+    printf("\n");
+#if 1
+    /*
+     * Convert to an array
+     */
+    psVoidPtrArray *arr = psDlistToArray(list);
+    list = NULL;			// it's been freed
+
+    for (int i = 0; i < arr->n; i++) {
+	printf("%d ", ((X *)(arr->arr[i]))->i);
+    }
+    printf("\n");
+#if 1
+    /*
+     * Convert back to a list
+     */
+    list = psArrayToDlist(arr);
+    arr = NULL;				// it's been freed
+
+    (void)psDlistGet(list, PS_DLIST_TAIL); // initialise iterator
+    while ((x = psDlistGet(list, PS_DLIST_PREV)) != NULL) {
+	printf("%d ", x->i);
+    }
+    printf("\n");
+#endif
+    psVoidPtrArrayFree(arr, (void (*)(void *))xFree);
+#endif
+
+#if 1
+    list = psArrayToDlist(psDlistToArray(list));
+
+    (void)psDlistGet(list, PS_DLIST_TAIL); // initialise iterator
+    while ((x = psDlistGet(list, PS_DLIST_PREV)) != NULL) {
+	printf("%d ", x->i);
+    }
+    printf("\n");
+#endif
+    /*
+     * Clean up
+     */
+    psDlistFree(list, (void (*)(void *))xFree);
+    /*
+     * Check for memory leaks
+     */
+    fprintf(stderr,"Checking for memory leaks:\n");
+    psMemCheckLeaks(0, NULL, stderr);
+    
+    return 0;
+}
Index: /trunk/archive/pslib/src/Utils/tst_hash.c
===================================================================
--- /trunk/archive/pslib/src/Utils/tst_hash.c	(revision 258)
+++ /trunk/archive/pslib/src/Utils/tst_hash.c	(revision 258)
@@ -0,0 +1,56 @@
+/*
+ * An interface to hash tables for Pan-STARRS
+ *
+ * Collisions are handled by simple linked lists
+ */
+#include <stdio.h>
+#include "psUtils.h"
+
+typedef struct { char *name; } ID;
+static ID *IdAlloc(const char *name)
+{
+    ID *id = psAlloc(sizeof(ID));
+    id->name = psStringCopy(name);
+
+    return id;
+}
+
+static void IdFree(ID *id)
+{
+    if (psMemGetRefCounter(id) > 1) {
+	psMemDecrRefCounter(id);
+	return;
+    }
+
+    psFree(id->name);
+    psFree(id);
+}
+
+int main(void)
+{
+    psSetTraceLevel("utils.hash", 3);
+    long memId0 = psMemGetId();
+
+    psHash *hash = psHashAlloc(16);
+
+    psHashInsert(hash, "Lynda", IdAlloc("Lee"), (void (*)(void *))IdFree);
+    psHashInsert(hash, "Lynda", IdAlloc("Lee"), (void (*)(void *))IdFree);
+    psHashInsert(hash, "Robert", IdAlloc("Lupton"), (void (*)(void *))IdFree);
+    psHashInsert(hash, "Robert", IdAlloc("the Good"), (void (*)(void *))IdFree);
+
+    char *names[] = {"Robert", "Lynda", "Rowan", NULL};
+    for (char **name = names; *name != NULL; name++) {
+	ID *id = psHashLookup(hash, *name);
+	printf("%s's surname is:\t%s\n", *name,
+	       ((id == NULL) ? "(unknown)" : id->name));
+    }
+
+    psHashFree(hash, (void (*)(void *))IdFree);
+    /*
+     * Check for memory leaks
+     */
+    fprintf(stderr,"Checking for memory leaks:\n");
+    psMemCheckLeaks(memId0, NULL, stderr);
+
+    return 0;
+}
Index: /trunk/archive/pslib/src/Utils/tst_logmsg.c
===================================================================
--- /trunk/archive/pslib/src/Utils/tst_logmsg.c	(revision 258)
+++ /trunk/archive/pslib/src/Utils/tst_logmsg.c	(revision 258)
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include "psUtils.h"
+
+int main(void)
+{
+    psSetTraceLevel("utils.logMsg", 1);
+    
+    psSetLogDestination(PS_LOG_TO_STDERR);
+    psSetLogLevel(PS_LOG_INFO);
+    psSetLogFormat("NM");
+    
+    psLogMsg("init", PS_LOG_INFO, "Hello World\n");
+    fprintf(stderr,"    Expect an abort():\n");
+    psAbort("fini", "I'm in Hawai`i");
+
+    return 0;
+}
Index: /trunk/archive/pslib/src/Utils/tst_memory.c
===================================================================
--- /trunk/archive/pslib/src/Utils/tst_memory.c	(revision 258)
+++ /trunk/archive/pslib/src/Utils/tst_memory.c	(revision 258)
@@ -0,0 +1,163 @@
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include "psUtils.h"
+
+/*****************************************************************************/
+/*
+ * My callbacks
+ */
+static int my_MemAllocateCB(const psMemBlock *ptr)
+{
+    static int incr = 0;		// "p_psMemAllocateID += incr"
+
+    assert (ptr != NULL);		// prevent compiler warnings
+    
+    fprintf(stderr, "Allocating block %ld (%s:%d)\n",
+	    ptr->id, ptr->file, ptr->lineno);
+    
+    incr = 2;				// See every other allocation
+
+    return incr;
+}
+
+static void *my_MemExhaustedCB(size_t size)
+{
+    psError(__func__, "Bye bye sweet world\n");
+    
+    return NULL;
+}
+
+static psMemProblemCallback default_MemProblemCB = NULL;
+
+static void my_MemProblemCB(const psMemBlock *ptr,
+			    const char *file, int lineno)
+{
+    fprintf(stderr, "I foresee trouble:\n");
+
+    default_MemProblemCB(ptr, file, lineno);
+}
+    
+/*****************************************************************************/
+
+int main(void)
+{
+    /*
+     * Survive any aborts that are generated
+     * This doesn't seem to work on mac os/x 10.2.8
+     */
+    if (signal(SIGABRT, SIG_IGN) == SIG_ERR) {
+	perror("Installing a SIGABRT handler");
+    }
+    /*
+     * Install my callbacks
+     */
+    (void)psMemAllocateSetCB(my_MemAllocateCB);
+    default_MemProblemCB = psMemProblemSetCB(my_MemProblemCB);
+    (void)psMemExhaustedSetCB(my_MemExhaustedCB);
+    /*
+     * Request callback on first allocation
+     */
+    (void)psMemSetAllocateID(1);
+    /*
+     * Start allocating
+     */
+    char *str = psAlloc(10);
+    double *x = psAlloc(1);
+    int *i = psAlloc(1);
+    *i = 1;
+    *x = 1.234;
+
+    psFree(i);
+    
+    str = psRealloc(str, 20);
+    psFree(str);
+#if 1
+    /*
+     * An illegal double-free
+     */
+    psFree(str);
+#endif
+
+#if 1
+    /*
+     * Free memory not allocated with psAlloc
+     */
+    psFree(psAlloc(1000) + 500);
+#endif
+
+#if 0
+    /*
+     * Ask for more memory than we can get
+     */
+    psAlloc((size_t)-1 - sizeof(psMemBlock));
+#endif
+
+#if 0
+    /*
+     * Increment refCounter on non-malloced pointer
+     */
+    psMemGetRefCounter(malloc(1));
+#endif
+
+#if 0
+    /*
+     * Mess with the refCounter
+     */
+    (void)psMemIncrRefCounter(x);
+    (void)psMemIncrRefCounter(x);
+    (void)psMemDecrRefCounter(x);	// now == 2
+#endif
+
+#if 0
+    /*
+     * A memory leak
+     */
+    {
+	char *str2 = psAlloc(20);
+	
+	sprintf(str2, "XXX");
+    }
+#else
+    psFree(x);
+#endif
+
+#if 1
+    /*
+     * Corrupt some memory
+     */
+    char *c = psAlloc(1);
+    c[-4] = 0;
+#endif
+
+    /*************************************************************************/
+    /*
+     * Check for memory corruption
+     */
+    if(psMemCheckCorruption(1)) {
+	psError(__func__, "Detected corrupted memory\n\n");
+    }
+    /*
+     * Check for memory leaks
+     */
+    psMemBlock **leaks = NULL;
+    int nleak = psMemCheckLeaks(0, &leaks, NULL);
+
+    if (nleak > 0) {
+	fprintf(stderr, "Memory is leaking (%d blocks):\n", nleak);
+	fprintf(stderr, "   %20s:line ID\n", "file");
+	for (int i = 0; i < nleak; i++) {
+	    fprintf(stderr, "   %20s:%-4d %ld\n",
+		    leaks[i]->file, leaks[i]->lineno, leaks[i]->id);
+	}
+	psFree(leaks);
+    }
+
+    if ((nleak = psMemCheckLeaks(0, NULL, NULL)) > 0) {
+	fprintf(stderr, "Memory is still leaking (%d blocks):\n", nleak);
+	psMemCheckLeaks(0, NULL, stderr);
+    }
+
+    return 0;
+}
Index: /trunk/archive/pslib/src/Utils/tst_trace.c
===================================================================
--- /trunk/archive/pslib/src/Utils/tst_trace.c	(revision 258)
+++ /trunk/archive/pslib/src/Utils/tst_trace.c	(revision 258)
@@ -0,0 +1,64 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <assert.h>
+#include "psUtils.h"
+
+static int my_MemAllocateCB(const psMemBlock *ptr)
+{
+    static int n = 1;			// "p_psMemAllocateID += n"
+
+    assert (ptr != NULL);		// prevent compiler warnings
+    
+    if(psMemCheckCorruption(0)) {
+	psError(__func__, "Detected corrupted memory\n\n");
+    }
+    
+    return n;				// see every nth allocation
+}
+
+int main(void)
+{
+    psSetLogFormat("NM");		// suppress some of the psLogMsg verbosity
+
+    (void)psMemAllocateSetCB(my_MemAllocateCB);
+    //(void)psMemFreeSetCB(my_MemAllocateCB);
+    psMemSetAllocateID(1);
+    psMemSetFreeID(14);
+    
+#if 0
+    psSetTraceLevel("", 10);
+#else
+    psSetTraceLevel("utils.dlist.add.head", 9);
+    psSetTraceLevel("utils.dlist.add", 3);
+    psSetTraceLevel("utils.dlist.remove", 4);
+    psSetTraceLevel("coadd", 2);
+    psSetTraceLevel("coadd.CR.remove.morphology", 5);
+    psSetTraceLevel("utils.hash", 2);
+    psSetTraceLevel("utils.dlist.add", 9);
+    psSetTraceLevel("utils", 1);
+#endif
+    
+    psPrintTraceLevels();
+    printf("\n");
+
+    psTrace("utils.dlist.remove", 2, "Removing psDList key \"%s\"\n", "my_key");
+    psTrace("utils", 2, "Initialising utilities library\n");
+    psTrace("", 2, "This is turned on by trace component \"\"");
+    psTrace("utils.dlist", 2, "Initialising psDList\n");
+    psTrace("utils.dlist.remove", 4, "Removing list key \"%s\" (value: \"%d\")\n", "my_key", 12345);
+    psTrace("utils.hash.remove", 4, "Removing hash key \"%s\" (value: \"%d\")\n", "my_key", 12345);
+    psTrace("utils.dlist.add", 1, "Adding list key \"%s\"\n", "your_key");
+    psTrace("utils.dlist.find", 2, "Looking up list key \"%s\"\n", "some_key");
+    psTrace("coadd.CR.remove", 4, "Removing CRs\n");
+    psTrace("coadd.CR.remove.morphology", 4, "CRs are not fuzzy\n");
+
+    psTraceReset();
+    fprintf(stderr,"\n");
+    fprintf(stderr,"Checking for memory leaks:\n");
+    psMemCheckLeaks(0, NULL, stderr);
+    
+
+    return 0;
+}
