diff nss/lib/base/error.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nss/lib/base/error.c	Mon Jul 28 10:47:06 2014 +0200
@@ -0,0 +1,269 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * error.c
+ *
+ * This file contains the code implementing the per-thread error 
+ * stacks upon which most NSS routines report their errors.
+ */
+
+#ifndef BASE_H
+#include "base.h"
+#endif /* BASE_H */
+#include <limits.h> /* for UINT_MAX */
+#include <string.h> /* for memmove */
+
+#define NSS_MAX_ERROR_STACK_COUNT 16 /* error codes */
+
+/*
+ * The stack itself has a header, and a sequence of integers.
+ * The header records the amount of space (as measured in stack
+ * slots) already allocated for the stack, and the count of the
+ * number of records currently being used.
+ */
+
+struct stack_header_str {
+  PRUint16 space;
+  PRUint16 count;
+};
+
+struct error_stack_str {
+  struct stack_header_str header;
+  PRInt32 stack[1];
+};
+typedef struct error_stack_str error_stack;
+
+/*
+ * error_stack_index
+ *
+ * Thread-private data must be indexed.  This is that index.
+ * See PR_NewThreadPrivateIndex for more information.
+ *
+ * Thread-private data indexes are in the range [0, 127].
+ */
+
+#define INVALID_TPD_INDEX UINT_MAX
+static PRUintn error_stack_index = INVALID_TPD_INDEX;
+
+/*
+ * call_once
+ *
+ * The thread-private index must be obtained (once!) at runtime.
+ * This block is used for that one-time call.
+ */
+
+static PRCallOnceType error_call_once;
+
+/*
+ * error_once_function
+ *
+ * This is the once-called callback.
+ */
+static PRStatus
+error_once_function ( void)
+{
+  return PR_NewThreadPrivateIndex(&error_stack_index, PR_Free);
+}
+
+/*
+ * error_get_my_stack
+ *
+ * This routine returns the calling thread's error stack, creating
+ * it if necessary.  It may return NULL upon error, which implicitly
+ * means that it ran out of memory.
+ */
+
+static error_stack *
+error_get_my_stack ( void)
+{
+  PRStatus st;
+  error_stack *rv;
+  PRUintn new_size;
+  PRUint32 new_bytes;
+  error_stack *new_stack;
+
+  if( INVALID_TPD_INDEX == error_stack_index ) {
+    st = PR_CallOnce(&error_call_once, error_once_function);
+    if( PR_SUCCESS != st ) {
+      return (error_stack *)NULL;
+    }
+  }
+
+  rv = (error_stack *)PR_GetThreadPrivate(error_stack_index);
+  if( (error_stack *)NULL == rv ) {
+    /* Doesn't exist; create one */
+    new_size = 16;
+  } else if( rv->header.count == rv->header.space  &&
+             rv->header.count  < NSS_MAX_ERROR_STACK_COUNT ) {
+    /* Too small, expand it */
+    new_size = PR_MIN( rv->header.space * 2, NSS_MAX_ERROR_STACK_COUNT);
+  } else {
+    /* Okay, return it */
+    return rv;
+  }
+
+  new_bytes = (new_size * sizeof(PRInt32)) + sizeof(error_stack);
+  /* Use NSPR's calloc/realloc, not NSS's, to avoid loops! */
+  new_stack = PR_Calloc(1, new_bytes);
+  
+  if( (error_stack *)NULL != new_stack ) {
+    if( (error_stack *)NULL != rv ) {
+	(void)nsslibc_memcpy(new_stack,rv,rv->header.space);
+    }
+    new_stack->header.space = new_size;
+  }
+
+  /* Set the value, whether or not the allocation worked */
+  PR_SetThreadPrivate(error_stack_index, new_stack);
+  return new_stack;
+}
+
+/*
+ * The error stack
+ *
+ * The public methods relating to the error stack are:
+ *
+ *  NSS_GetError
+ *  NSS_GetErrorStack
+ *
+ * The nonpublic methods relating to the error stack are:
+ *
+ *  nss_SetError
+ *  nss_ClearErrorStack
+ *
+ */
+
+/*
+ * NSS_GetError
+ *
+ * This routine returns the highest-level (most general) error set
+ * by the most recent NSS library routine called by the same thread
+ * calling this routine.
+ *
+ * This routine cannot fail.  However, it may return zero, which
+ * indicates that the previous NSS library call did not set an error.
+ *
+ * Return value:
+ *  0 if no error has been set
+ *  A nonzero error number
+ */
+
+NSS_IMPLEMENT PRInt32
+NSS_GetError ( void)
+{
+  error_stack *es = error_get_my_stack();
+
+  if( (error_stack *)NULL == es ) {
+    return NSS_ERROR_NO_MEMORY; /* Good guess! */
+  }
+
+  if( 0 == es->header.count ) {
+    return 0;
+  }
+
+  return es->stack[ es->header.count-1 ];
+}
+
+/*
+ * NSS_GetErrorStack
+ *
+ * This routine returns a pointer to an array of integers, containing
+ * the entire sequence or "stack" of errors set by the most recent NSS
+ * library routine called by the same thread calling this routine.
+ * NOTE: the caller DOES NOT OWN the memory pointed to by the return
+ * value.  The pointer will remain valid until the calling thread
+ * calls another NSS routine.  The lowest-level (most specific) error 
+ * is first in the array, and the highest-level is last.  The array is
+ * zero-terminated.  This routine may return NULL upon error; this
+ * indicates a low-memory situation.
+ *
+ * Return value:
+ *  NULL upon error, which is an implied NSS_ERROR_NO_MEMORY
+ *  A NON-caller-owned pointer to an array of integers
+ */
+
+NSS_IMPLEMENT PRInt32 *
+NSS_GetErrorStack ( void)
+{
+  error_stack *es = error_get_my_stack();
+
+  if( (error_stack *)NULL == es ) {
+    return (PRInt32 *)NULL;
+  }
+
+  /* Make sure it's terminated */
+  es->stack[ es->header.count ] = 0;
+
+  return es->stack;
+}
+
+/*
+ * nss_SetError
+ *
+ * This routine places a new error code on the top of the calling 
+ * thread's error stack.  Calling this routine wiht an error code
+ * of zero will clear the error stack.
+ */
+
+NSS_IMPLEMENT void
+nss_SetError ( PRUint32 error)
+{
+  error_stack *es;
+
+  if( 0 == error ) {
+    nss_ClearErrorStack();
+    return;
+  }
+
+  es = error_get_my_stack();
+  if( (error_stack *)NULL == es ) {
+    /* Oh, well. */
+    return;
+  }
+
+  if (es->header.count < es->header.space) {
+    es->stack[ es->header.count++ ] = error;
+  } else {
+    memmove(es->stack, es->stack + 1, 
+		(es->header.space - 1) * (sizeof es->stack[0]));
+    es->stack[ es->header.space - 1 ] = error;
+  }
+  return;
+}
+
+/*
+ * nss_ClearErrorStack
+ *
+ * This routine clears the calling thread's error stack.
+ */
+
+NSS_IMPLEMENT void
+nss_ClearErrorStack ( void)
+{
+  error_stack *es = error_get_my_stack();
+  if( (error_stack *)NULL == es ) {
+    /* Oh, well. */
+    return;
+  }
+
+  es->header.count = 0;
+  es->stack[0] = 0;
+  return;
+}
+
+/*
+ * nss_DestroyErrorStack
+ *
+ * This routine frees the calling thread's error stack.
+ */
+
+NSS_IMPLEMENT void
+nss_DestroyErrorStack ( void)
+{
+  if( INVALID_TPD_INDEX != error_stack_index ) {
+    PR_SetThreadPrivate(error_stack_index, NULL);
+  }
+  return;
+}
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)