Index: /trunk/psLib/src/sys/psError.c
===================================================================
--- /trunk/psLib/src/sys/psError.c	(revision 1684)
+++ /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);
+}
+
Index: /trunk/psLib/src/sys/psError.h
===================================================================
--- /trunk/psLib/src/sys/psError.h	(revision 1684)
+++ /trunk/psLib/src/sys/psError.h	(revision 1685)
@@ -12,6 +12,6 @@
  *  @author Eric Van Alst, MHPCC
  *
- *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-09-02 22:23:20 $
+ *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-09-03 20:39:50 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -22,4 +22,5 @@
 
 #include<stdio.h>
+#include<stdbool.h>
 
 #include "psErrorCodes.h"
@@ -29,18 +30,70 @@
  */
 
+/** Error message object */
 typedef struct
 {
-    char *name;                        ///< category of code that caused the error
+    char* name;                        ///< category of code that caused the error
     psErrorCode code;                  ///< class of error
-    char *msg;                         ///< the message associated with the error
+    char* msg;                         ///< the message associated with the error
 }
 psErr;
 
-const psErr *psErrorGet(int which);
-const psErr *psErrorLast(void);
+/** Get a error from the error stack
+ *
+ *  Previous errors on the stack are returned by psErrorGet (a value of 0 
+ *  passed to psErrorGet is equivalent to a call to psErrorLast).
+ *
+ *  if no error is at the which position, a non-NULL psErr is returned with 
+ *  code PS_ERR_NONE.
+ *
+ *  @return    Error message object at 'which'
+ */
+const psErr* psErrorGet(
+    int which                          ///< position in the error stack. 0 is last error on stack.
+);
+
+/** Get last error put on the error stack
+ *
+ *  The last error reported is available from psErrorLast; if no errors are 
+ *  current, a non-NULL psErr is returned with code PS_ERR_NONE.
+ *
+ *  @return psErr*     Reference to last error message on error stack
+ */
+const psErr* psErrorLast(void);
+
+/** Clears the error stack.
+ *
+ *  The error stack may be completely cleared with psErrorClear.
+ *
+ */
 void psErrorClear(void);
 
-void psErrorStackPrint(FILE *fd, const char *fmt, ...);
-void psErrorStackPrintV(FILE *fd, const char *fmt, va_list va);
+/** Prints error stack to specified open file descriptor
+ *
+ *  The entire error stack may be printed to an open file descriptor by 
+ *  calling psErrorStackPrint; if and only if there are current errors, the 
+ *  printf-style string fmt is first printed to the file descriptor fd. In 
+ *  this printout, error codes are replaced by their string equivalents.
+ *
+ */
+void psErrorStackPrint(
+    FILE* fd,                          ///< destination file descriptor
+    const char* fmt,                   ///< printf-style format of header line
+    ...                                ///< any parameters required in fmt
+);
+
+/** Prints error stack to specified open file descriptor
+ *
+ *  The entire error stack may be printed to an open file descriptor by 
+ *  calling psErrorStackPrintV; if and only if there are current errors, the 
+ *  vprintf-style string fmt is first printed to the file descriptor fd. In 
+ *  this printout, error codes are replaced by their string equivalents.
+ *
+ */
+void psErrorStackPrintV(
+    FILE* fd,                          ///< destination file descriptor
+    const char* fmt,                   ///< printf-style format of header line
+    va_list va                         ///< any parameters required in fmt
+);
 
 /** Reports an error message to the logging facility
@@ -57,4 +110,31 @@
 );
 
+/** Reports an error message to the logging facility
+ *
+ *  This function will invoke the psLogMsg function with a level of
+ *  PS_LOG_ERROR and pass the parameters name and fmt to generate a proper
+ *  log message.
+ *
+ */
+void psErrorMsg(
+    const char *name,                  ///< Name of error in the form aaa.bbb.ccc
+    psErrorCode code,                  ///< Error class code
+    bool new,                          ///< true if error originates at this location
+    const char* fmt,                   ///< printf style formatting statement defining error message
+    ...
+);
+
+/** Create a new psErr struct
+ *
+ *  Creates a new psErr struct, making a copy of the parameters.
+ *
+ *  @return psErr*     new psErr object
+ */
+psErr* psErrAlloc(
+    const char* name,                  ///< Name of error in the form aaa.bbb.ccc
+    psErrorCode code,                  ///< Error class code
+    const char* msg                    ///< Error message
+);
+
 /* @} */// End of SysUtils Functions
 
Index: /trunk/psLib/src/sysUtils/psError.c
===================================================================
--- /trunk/psLib/src/sysUtils/psError.c	(revision 1684)
+++ /trunk/psLib/src/sysUtils/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);
+}
+
Index: /trunk/psLib/src/sysUtils/psError.h
===================================================================
--- /trunk/psLib/src/sysUtils/psError.h	(revision 1684)
+++ /trunk/psLib/src/sysUtils/psError.h	(revision 1685)
@@ -12,6 +12,6 @@
  *  @author Eric Van Alst, MHPCC
  *
- *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-09-02 22:23:20 $
+ *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-09-03 20:39:50 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -22,4 +22,5 @@
 
 #include<stdio.h>
+#include<stdbool.h>
 
 #include "psErrorCodes.h"
@@ -29,18 +30,70 @@
  */
 
+/** Error message object */
 typedef struct
 {
-    char *name;                        ///< category of code that caused the error
+    char* name;                        ///< category of code that caused the error
     psErrorCode code;                  ///< class of error
-    char *msg;                         ///< the message associated with the error
+    char* msg;                         ///< the message associated with the error
 }
 psErr;
 
-const psErr *psErrorGet(int which);
-const psErr *psErrorLast(void);
+/** Get a error from the error stack
+ *
+ *  Previous errors on the stack are returned by psErrorGet (a value of 0 
+ *  passed to psErrorGet is equivalent to a call to psErrorLast).
+ *
+ *  if no error is at the which position, a non-NULL psErr is returned with 
+ *  code PS_ERR_NONE.
+ *
+ *  @return    Error message object at 'which'
+ */
+const psErr* psErrorGet(
+    int which                          ///< position in the error stack. 0 is last error on stack.
+);
+
+/** Get last error put on the error stack
+ *
+ *  The last error reported is available from psErrorLast; if no errors are 
+ *  current, a non-NULL psErr is returned with code PS_ERR_NONE.
+ *
+ *  @return psErr*     Reference to last error message on error stack
+ */
+const psErr* psErrorLast(void);
+
+/** Clears the error stack.
+ *
+ *  The error stack may be completely cleared with psErrorClear.
+ *
+ */
 void psErrorClear(void);
 
-void psErrorStackPrint(FILE *fd, const char *fmt, ...);
-void psErrorStackPrintV(FILE *fd, const char *fmt, va_list va);
+/** Prints error stack to specified open file descriptor
+ *
+ *  The entire error stack may be printed to an open file descriptor by 
+ *  calling psErrorStackPrint; if and only if there are current errors, the 
+ *  printf-style string fmt is first printed to the file descriptor fd. In 
+ *  this printout, error codes are replaced by their string equivalents.
+ *
+ */
+void psErrorStackPrint(
+    FILE* fd,                          ///< destination file descriptor
+    const char* fmt,                   ///< printf-style format of header line
+    ...                                ///< any parameters required in fmt
+);
+
+/** Prints error stack to specified open file descriptor
+ *
+ *  The entire error stack may be printed to an open file descriptor by 
+ *  calling psErrorStackPrintV; if and only if there are current errors, the 
+ *  vprintf-style string fmt is first printed to the file descriptor fd. In 
+ *  this printout, error codes are replaced by their string equivalents.
+ *
+ */
+void psErrorStackPrintV(
+    FILE* fd,                          ///< destination file descriptor
+    const char* fmt,                   ///< printf-style format of header line
+    va_list va                         ///< any parameters required in fmt
+);
 
 /** Reports an error message to the logging facility
@@ -57,4 +110,31 @@
 );
 
+/** Reports an error message to the logging facility
+ *
+ *  This function will invoke the psLogMsg function with a level of
+ *  PS_LOG_ERROR and pass the parameters name and fmt to generate a proper
+ *  log message.
+ *
+ */
+void psErrorMsg(
+    const char *name,                  ///< Name of error in the form aaa.bbb.ccc
+    psErrorCode code,                  ///< Error class code
+    bool new,                          ///< true if error originates at this location
+    const char* fmt,                   ///< printf style formatting statement defining error message
+    ...
+);
+
+/** Create a new psErr struct
+ *
+ *  Creates a new psErr struct, making a copy of the parameters.
+ *
+ *  @return psErr*     new psErr object
+ */
+psErr* psErrAlloc(
+    const char* name,                  ///< Name of error in the form aaa.bbb.ccc
+    psErrorCode code,                  ///< Error class code
+    const char* msg                    ///< Error message
+);
+
 /* @} */// End of SysUtils Functions
 
