Index: trunk/psLib/src/sys/psError.c
===================================================================
--- trunk/psLib/src/sys/psError.c	(revision 1407)
+++ trunk/psLib/src/sys/psError.c	(revision 1685)
@@ -11,64 +11,58 @@
  *  @author Eric Van Alst, MHPCC
  *   
- *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-08-07 00:06:06 $
+ *  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-09-03 20:39:50 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
  */
 
-/******************************************************************************/
+#include <stdarg.h>
+#include <pthread.h>
+#include <string.h>
 
-/*  INCLUDE FILES                                                             */
-
-/******************************************************************************/
-#include <stdarg.h>
 #include "psLogMsg.h"
 #include "psError.h"
+#include "psMemory.h"
 
-/******************************************************************************/
+#define MAX_ERROR_STACK_SIZE 64
+static psErr* errorStack[MAX_ERROR_STACK_SIZE];
+static unsigned int errorStackSize = 0;
+pthread_mutex_t lockErrorStack = PTHREAD_MUTEX_INITIALIZER;
 
-/*  DEFINE STATEMENTS                                                         */
 
-/******************************************************************************/
+static void pushErrorStack(psErr* err);
 
-// None
+static void pushErrorStack(psErr* err)
+{
 
-/******************************************************************************/
+    pthread_mutex_lock(&lockErrorStack);
 
-/*  TYPE DEFINITIONS                                                          */
+    if (errorStackSize < MAX_ERROR_STACK_SIZE) {
+        errorStack[errorStackSize] = psMemIncrRefCounter(err);
+        errorStackSize++;
+    }
 
-/******************************************************************************/
+    pthread_mutex_unlock(&lockErrorStack);
+}
 
-// None
+static void errFree(psErr* err)
+{
+    if (err != NULL) {
+        psFree(err->msg);
+        psFree(err->name);
+    }
+}
 
-/*****************************************************************************/
+psErr* psErrAlloc(const char* name, psErrorCode code, const char* msg)
+{
+    psErr* err = psAlloc(sizeof(psErr));
+    err->msg = strcpy(psAlloc(strlen(msg) + 1), msg);
+    err->name = strcpy(psAlloc(strlen(name) + 1), name);
+    err->code = code;
 
-/*  GLOBAL VARIABLES                                                         */
+    p_psMemSetDeallocator(err,(psFreeFcn)errFree);
 
-/*****************************************************************************/
-
-// None
-
-/*****************************************************************************/
-
-/*  FILE STATIC VARIABLES                                                    */
-
-/*****************************************************************************/
-
-// None
-
-/*****************************************************************************/
-
-/*  FUNCTION IMPLEMENTATIONS - LOCAL                                         */
-
-/*****************************************************************************/
-
-// None
-
-/*****************************************************************************/
-
-/* FUNCTION IMPLEMENTATIONS - PUBLIC                                         */
-
-/*****************************************************************************/
+    return err;
+}
 
 void psError(const char *name, const char *fmt, ...)
@@ -85,2 +79,94 @@
     va_end(argPtr);
 }
+
+void psErrorClear()
+{
+    pthread_mutex_lock(&lockErrorStack);
+    for (int lcv=0;lcv<errorStackSize;lcv++) {
+        psFree(errorStack[lcv]);
+    }
+    errorStackSize = 0;
+    pthread_mutex_unlock(&lockErrorStack);
+}
+
+void psErrorMsg(const char *name, psErrorCode code, bool new, const char* fmt, ...)
+{
+    char errMsg[1024];
+    psErr* err;
+
+    va_list argPtr;             // variable list arguement pointer
+
+    // Get the variable list parameters to pass to logging function
+    va_start(argPtr, fmt);
+
+    // Call logging function with PS_LOG_ERROR level
+    psLogMsgV(name, PS_LOG_ERROR, fmt, argPtr);
+
+    if (new) {
+        psErrorClear();
+    }
+
+    vsnprintf(errMsg,1024,fmt,argPtr);
+    err = psErrAlloc(name,code,errMsg);
+    pushErrorStack(err);
+
+    // Clean up stack after variable argument has been used
+    va_end(argPtr);
+
+    psFree(err);
+}
+
+const psErr* psErrorGet(int which)
+{
+    psErr* result;
+
+    pthread_mutex_lock(&lockErrorStack);
+
+    which = errorStackSize-1-which;     // the which input is from the end of errorStack
+    if (which < 0 || which >= errorStackSize) {
+        result = psErrAlloc("",PS_ERR_NONE,"");    // no error at the given location
+    } else {
+        result = psMemIncrRefCounter(errorStack[which]); // a new reference passed back
+    }
+
+    pthread_mutex_unlock(&lockErrorStack);
+
+    return result;
+}
+
+const psErr* psErrorLast(void)
+{
+    return psErrorGet(0);
+}
+
+void psErrorStackPrint(FILE *fd, const char *fmt, ...)
+{
+    va_list argPtr;             // variable list arguement pointer
+
+    // Get the variable list parameters to pass to logging function
+    va_start(argPtr, fmt);
+
+    psErrorStackPrintV(fd,fmt,argPtr);
+
+    va_end(argPtr);
+}
+
+void psErrorStackPrintV(FILE *fd, const char *fmt, va_list va)
+{
+
+    pthread_mutex_lock(&lockErrorStack);
+
+    if (errorStackSize > 0) {
+        vfprintf(fd,fmt,va);
+
+        for (int lcv=0;lcv<errorStackSize;lcv++) {
+            fprintf(fd," -> %s: %s\n     %s\n",
+                    errorStack[lcv]->name,
+                    psErrorCodeString(errorStack[lcv]->code),
+                    errorStack[lcv]->msg);
+        }
+    }
+
+    pthread_mutex_unlock(&lockErrorStack);
+}
+
