summaryrefslogtreecommitdiffstats
path: root/nsprpub/lib
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--nsprpub/lib/Makefile.in24
-rw-r--r--nsprpub/lib/ds/Makefile.in147
-rw-r--r--nsprpub/lib/ds/plarena.c348
-rw-r--r--nsprpub/lib/ds/plarena.h338
-rw-r--r--nsprpub/lib/ds/plarenas.h12
-rw-r--r--nsprpub/lib/ds/plds.def60
-rw-r--r--nsprpub/lib/ds/plds.rc69
-rw-r--r--nsprpub/lib/ds/plhash.c495
-rw-r--r--nsprpub/lib/ds/plhash.h126
-rw-r--r--nsprpub/lib/ds/plvrsion.c100
-rw-r--r--nsprpub/lib/libc/Makefile.in24
-rw-r--r--nsprpub/lib/libc/README20
-rw-r--r--nsprpub/lib/libc/include/Makefile.in24
-rw-r--r--nsprpub/lib/libc/include/README7
-rw-r--r--nsprpub/lib/libc/include/plbase64.h76
-rw-r--r--nsprpub/lib/libc/include/plerror.h34
-rw-r--r--nsprpub/lib/libc/include/plgetopt.h125
-rw-r--r--nsprpub/lib/libc/include/plstr.h437
-rw-r--r--nsprpub/lib/libc/src/Makefile.in148
-rw-r--r--nsprpub/lib/libc/src/README20
-rw-r--r--nsprpub/lib/libc/src/base64.c416
-rw-r--r--nsprpub/lib/libc/src/plc.def72
-rw-r--r--nsprpub/lib/libc/src/plc.rc70
-rw-r--r--nsprpub/lib/libc/src/plerror.c44
-rw-r--r--nsprpub/lib/libc/src/plgetopt.c251
-rw-r--r--nsprpub/lib/libc/src/plvrsion.c100
-rw-r--r--nsprpub/lib/libc/src/strcase.c206
-rw-r--r--nsprpub/lib/libc/src/strcat.c54
-rw-r--r--nsprpub/lib/libc/src/strchr.c70
-rw-r--r--nsprpub/lib/libc/src/strcmp.c33
-rw-r--r--nsprpub/lib/libc/src/strcpy.c65
-rw-r--r--nsprpub/lib/libc/src/strdup.c59
-rw-r--r--nsprpub/lib/libc/src/strlen.c47
-rw-r--r--nsprpub/lib/libc/src/strpbrk.c79
-rw-r--r--nsprpub/lib/libc/src/strstr.c110
-rw-r--r--nsprpub/lib/libc/src/strtok.c59
-rw-r--r--nsprpub/lib/prstreams/Makefile.in142
-rw-r--r--nsprpub/lib/prstreams/plvrsion.c100
-rw-r--r--nsprpub/lib/prstreams/prstrms.cpp517
-rw-r--r--nsprpub/lib/prstreams/prstrms.h154
-rw-r--r--nsprpub/lib/prstreams/prstrms.rc69
-rw-r--r--nsprpub/lib/prstreams/tests/testprstrm/Makefile.in160
-rw-r--r--nsprpub/lib/prstreams/tests/testprstrm/testprstrm.cpp172
-rw-r--r--nsprpub/lib/tests/Makefile.in170
-rw-r--r--nsprpub/lib/tests/arena.c371
-rw-r--r--nsprpub/lib/tests/base64t.c3390
-rw-r--r--nsprpub/lib/tests/getopt.c45
-rw-r--r--nsprpub/lib/tests/string.c3128
48 files changed, 12787 insertions, 0 deletions
diff --git a/nsprpub/lib/Makefile.in b/nsprpub/lib/Makefile.in
new file mode 100644
index 0000000000..64dd43da6d
--- /dev/null
+++ b/nsprpub/lib/Makefile.in
@@ -0,0 +1,24 @@
+#
+# 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/.
+
+#! gmake
+
+MOD_DEPTH = ..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+export NSPR20=1
+
+include $(topsrcdir)/config/config.mk
+
+DIRS = ds libc
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(TARGETS)
+
diff --git a/nsprpub/lib/ds/Makefile.in b/nsprpub/lib/ds/Makefile.in
new file mode 100644
index 0000000000..38a9e3dd15
--- /dev/null
+++ b/nsprpub/lib/ds/Makefile.in
@@ -0,0 +1,147 @@
+#
+# 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/.
+
+#! gmake
+
+MOD_DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include
+
+CSRCS = \
+ plarena.c \
+ plhash.c \
+ plvrsion.c \
+ $(NULL)
+
+HEADERS = \
+ plarenas.h \
+ plarena.h \
+ plhash.h \
+ $(NULL)
+
+HEADERS := $(addprefix $(srcdir)/, $(HEADERS))
+
+ifeq ($(OS_ARCH), WINNT)
+RES=$(OBJDIR)/plds.res
+RESNAME=plds.rc
+endif # WINNT
+
+ifeq ($(OS_ARCH), AIX)
+ifeq ($(CLASSIC_NSPR),1)
+OS_LIBS = -lc
+else
+OS_LIBS = -lc_r
+endif
+endif
+
+ifeq ($(OS_ARCH),SunOS)
+OS_LIBS = -lc
+MAPFILE = $(OBJDIR)/pldsmap.sun
+GARBAGE += $(MAPFILE)
+ifdef NS_USE_GCC
+ifdef GCC_USE_GNU_LD
+MKSHLIB += -Wl,--version-script,$(MAPFILE)
+else
+MKSHLIB += -Wl,-M,$(MAPFILE)
+endif
+else
+MKSHLIB += -M $(MAPFILE)
+endif
+# The -R '$ORIGIN' linker option instructs this library to search for its
+# dependencies in the same directory where it resides.
+MKSHLIB += -R '$$ORIGIN'
+endif
+
+ifeq ($(OS_ARCH),OS2)
+MAPFILE = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).def
+GARBAGE += $(MAPFILE)
+MKSHLIB += $(MAPFILE)
+endif
+
+EXTRA_LIBS = $(LIBNSPR)
+
+# On SCOOS, we can't link with extra libraries when
+# we build a shared library. If we do so, the linker doesn't
+# complain, but we would run into weird problems at run-time.
+# Therefore on these platforms, we link just the .o files.
+ifeq ($(OS_ARCH),SCOOS)
+EXTRA_LIBS =
+endif
+
+ifdef RESOLVE_LINK_SYMBOLS
+EXTRA_LIBS += $(OS_LIBS)
+endif
+
+LIBRARY_NAME = plds
+LIBRARY_VERSION = $(MOD_MAJOR_VERSION)
+
+RELEASE_HEADERS = $(HEADERS)
+RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR)
+RELEASE_LIBS = $(TARGETS)
+
+include $(topsrcdir)/config/rules.mk
+
+#
+# Version information generation (begin)
+#
+ECHO = echo
+TINC = $(OBJDIR)/_pl_bld.h
+PROD = $(notdir $(SHARED_LIBRARY))
+NOW = $(MOD_DEPTH)/config/$(OBJDIR)/now
+SH_DATE = $(shell date "+%Y-%m-%d %T")
+SH_NOW = $(shell $(NOW))
+
+ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
+ SUF = i64
+else
+ SUF = LL
+endif
+
+GARBAGE += $(TINC)
+
+$(TINC):
+ @$(MAKE_OBJDIR)
+ @$(ECHO) '#define _BUILD_STRING "$(SH_DATE)"' > $(TINC)
+ @if test ! -z "$(SH_NOW)"; then \
+ $(ECHO) '#define _BUILD_TIME $(SH_NOW)$(SUF)' >> $(TINC); \
+ else \
+ true; \
+ fi
+ @$(ECHO) '#define _PRODUCTION "$(PROD)"' >> $(TINC)
+
+
+$(OBJDIR)/plvrsion.$(OBJ_SUFFIX): plvrsion.c $(TINC)
+ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
+ $(CC) -Fo$@ -c $(CFLAGS) -I$(OBJDIR) $<
+else
+ $(CC) -o $@ -c $(CFLAGS) -I$(OBJDIR) $<
+endif
+#
+# Version information generation (end)
+#
+
+#
+# The Client build wants the shared libraries in $(dist_bindir),
+# so we also install them there.
+#
+
+export:: $(TARGETS)
+ $(INSTALL) -m 444 $(HEADERS) $(dist_includedir)
+ $(INSTALL) -m 444 $(TARGETS) $(dist_libdir)
+ifdef SHARED_LIBRARY
+ifeq ($(OS_ARCH),HP-UX)
+ $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_libdir)
+ $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_bindir)
+else
+ $(INSTALL) -m 444 $(SHARED_LIBRARY) $(dist_bindir)
+endif
+endif
diff --git a/nsprpub/lib/ds/plarena.c b/nsprpub/lib/ds/plarena.c
new file mode 100644
index 0000000000..3c6df2b7f7
--- /dev/null
+++ b/nsprpub/lib/ds/plarena.c
@@ -0,0 +1,348 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+/*
+ * Lifetime-based fast allocation, inspired by much prior art, including
+ * "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
+ * David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
+ */
+#include <stdlib.h>
+#include <string.h>
+#include "plarena.h"
+#include "prmem.h"
+#include "prbit.h"
+#include "prlog.h"
+#include "prlock.h"
+#include "prinit.h"
+
+#ifdef PL_ARENAMETER
+static PLArenaStats *arena_stats_list;
+
+#define COUNT(pool,what) (pool)->stats.what++
+#else
+#define COUNT(pool,what) /* nothing */
+#endif
+
+#define PL_ARENA_DEFAULT_ALIGN sizeof(double)
+
+PR_IMPLEMENT(void) PL_InitArenaPool(
+ PLArenaPool *pool, const char *name, PRUint32 size, PRUint32 align)
+{
+ /*
+ * Look-up table of PR_BITMASK(PR_CeilingLog2(align)) values for
+ * align = 1 to 32.
+ */
+ static const PRUint8 pmasks[33] = {
+ 0, /* not used */
+ 0, 1, 3, 3, 7, 7, 7, 7,15,15,15,15,15,15,15,15, /* 1 ... 16 */
+ 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31 /* 17 ... 32 */
+ };
+
+ if (align == 0) {
+ align = PL_ARENA_DEFAULT_ALIGN;
+ }
+
+ if (align < sizeof(pmasks)/sizeof(pmasks[0])) {
+ pool->mask = pmasks[align];
+ }
+ else {
+ pool->mask = PR_BITMASK(PR_CeilingLog2(align));
+ }
+
+ pool->first.next = NULL;
+ /* Set all three addresses in pool->first to the same dummy value.
+ * These addresses are only compared with each other, but never
+ * dereferenced. */
+ pool->first.base = pool->first.avail = pool->first.limit =
+ (PRUword)PL_ARENA_ALIGN(pool, &pool->first + 1);
+ pool->current = &pool->first;
+ /*
+ * Compute the net size so that each arena's gross size is |size|.
+ * sizeof(PLArena) + pool->mask is the header and alignment slop
+ * that PL_ArenaAllocate adds to the net size.
+ */
+ if (size > sizeof(PLArena) + pool->mask) {
+ pool->arenasize = size - (sizeof(PLArena) + pool->mask);
+ }
+ else {
+ pool->arenasize = size;
+ }
+#ifdef PL_ARENAMETER
+ memset(&pool->stats, 0, sizeof pool->stats);
+ pool->stats.name = strdup(name);
+ pool->stats.next = arena_stats_list;
+ arena_stats_list = &pool->stats;
+#endif
+}
+
+
+/*
+** PL_ArenaAllocate() -- allocate space from an arena pool
+**
+** Description: PL_ArenaAllocate() allocates space from an arena
+** pool.
+**
+** First, try to satisfy the request from arenas starting at
+** pool->current. Then try to allocate a new arena from the heap.
+**
+** Returns: pointer to allocated space or NULL
+**
+** Notes: The original implementation had some difficult to
+** solve bugs; the code was difficult to read. Sometimes it's
+** just easier to rewrite it. I did that. larryh.
+**
+** See also: bugzilla: 45343.
+**
+*/
+
+PR_IMPLEMENT(void *) PL_ArenaAllocate(PLArenaPool *pool, PRUint32 nb)
+{
+ PLArena *a;
+ char *rp; /* returned pointer */
+ PRUint32 nbOld;
+
+ PR_ASSERT((nb & pool->mask) == 0);
+
+ nbOld = nb;
+ nb = (PRUword)PL_ARENA_ALIGN(pool, nb); /* force alignment */
+ if (nb < nbOld) {
+ return NULL;
+ }
+
+ /* attempt to allocate from arenas at pool->current */
+ {
+ a = pool->current;
+ do {
+ if ( nb <= a->limit - a->avail ) {
+ pool->current = a;
+ rp = (char *)a->avail;
+ a->avail += nb;
+ return rp;
+ }
+ } while( NULL != (a = a->next) );
+ }
+
+ /* attempt to allocate from the heap */
+ {
+ PRUint32 sz = PR_MAX(pool->arenasize, nb);
+ if (PR_UINT32_MAX - sz < sizeof *a + pool->mask) {
+ a = NULL;
+ } else {
+ sz += sizeof *a + pool->mask; /* header and alignment slop */
+ a = (PLArena*)PR_MALLOC(sz);
+ }
+ if ( NULL != a ) {
+ a->limit = (PRUword)a + sz;
+ a->base = a->avail = (PRUword)PL_ARENA_ALIGN(pool, a + 1);
+ PL_MAKE_MEM_NOACCESS((void*)a->avail, a->limit - a->avail);
+ rp = (char *)a->avail;
+ a->avail += nb;
+ PR_ASSERT(a->avail <= a->limit);
+ /* the newly allocated arena is linked after pool->current
+ * and becomes pool->current */
+ a->next = pool->current->next;
+ pool->current->next = a;
+ pool->current = a;
+ if ( NULL == pool->first.next ) {
+ pool->first.next = a;
+ }
+ PL_COUNT_ARENA(pool,++);
+ COUNT(pool, nmallocs);
+ return(rp);
+ }
+ }
+
+ /* we got to here, and there's no memory to allocate */
+ return(NULL);
+} /* --- end PL_ArenaAllocate() --- */
+
+PR_IMPLEMENT(void *) PL_ArenaGrow(
+ PLArenaPool *pool, void *p, PRUint32 size, PRUint32 incr)
+{
+ void *newp;
+
+ if (PR_UINT32_MAX - size < incr) {
+ return NULL;
+ }
+ PL_ARENA_ALLOCATE(newp, pool, size + incr);
+ if (newp) {
+ memcpy(newp, p, size);
+ }
+ return newp;
+}
+
+PR_IMPLEMENT(void) PL_ClearArenaPool(PLArenaPool *pool, PRInt32 pattern)
+{
+ PLArena *a;
+
+ for (a = pool->first.next; a; a = a->next) {
+ PR_ASSERT(a->base <= a->avail && a->avail <= a->limit);
+ a->avail = a->base;
+ PL_CLEAR_UNUSED_PATTERN(a, pattern);
+ PL_MAKE_MEM_NOACCESS((void*)a->avail, a->limit - a->avail);
+ }
+}
+
+/*
+ * Free tail arenas linked after head, which may not be the true list head.
+ * Reset pool->current to point to head in case it pointed at a tail arena.
+ */
+static void FreeArenaList(PLArenaPool *pool, PLArena *head)
+{
+ PLArena *a = head->next;
+ if (!a) {
+ return;
+ }
+
+ head->next = NULL;
+
+ do {
+ PLArena *tmp = a;
+ a = a->next;
+ PL_CLEAR_ARENA(tmp);
+ PL_COUNT_ARENA(pool,--);
+ PR_DELETE(tmp);
+ } while (a);
+
+ pool->current = head;
+}
+
+PR_IMPLEMENT(void) PL_ArenaRelease(PLArenaPool *pool, char *mark)
+{
+ PLArena *a;
+
+ for (a = &pool->first; a; a = a->next) {
+ if (PR_UPTRDIFF(mark, a->base) <= PR_UPTRDIFF(a->avail, a->base)) {
+ a->avail = (PRUword)PL_ARENA_ALIGN(pool, mark);
+ FreeArenaList(pool, a);
+ return;
+ }
+ }
+}
+
+PR_IMPLEMENT(void) PL_FreeArenaPool(PLArenaPool *pool)
+{
+ FreeArenaList(pool, &pool->first);
+ COUNT(pool, ndeallocs);
+}
+
+PR_IMPLEMENT(void) PL_FinishArenaPool(PLArenaPool *pool)
+{
+ FreeArenaList(pool, &pool->first);
+#ifdef PL_ARENAMETER
+ {
+ PLArenaStats *stats, **statsp;
+
+ if (pool->stats.name) {
+ PR_DELETE(pool->stats.name);
+ }
+ for (statsp = &arena_stats_list; (stats = *statsp) != 0;
+ statsp = &stats->next) {
+ if (stats == &pool->stats) {
+ *statsp = stats->next;
+ return;
+ }
+ }
+ }
+#endif
+}
+
+PR_IMPLEMENT(void) PL_CompactArenaPool(PLArenaPool *ap)
+{
+}
+
+PR_IMPLEMENT(void) PL_ArenaFinish(void)
+{
+}
+
+PR_IMPLEMENT(size_t) PL_SizeOfArenaPoolExcludingPool(
+ const PLArenaPool *pool, PLMallocSizeFn mallocSizeOf)
+{
+ /*
+ * The first PLArena is within |pool|, so don't measure it. Subsequent
+ * PLArenas are separate and must be measured.
+ */
+ size_t size = 0;
+ const PLArena *arena = pool->first.next;
+ while (arena) {
+ size += mallocSizeOf(arena);
+ arena = arena->next;
+ }
+ return size;
+}
+
+#ifdef PL_ARENAMETER
+PR_IMPLEMENT(void) PL_ArenaCountAllocation(PLArenaPool *pool, PRUint32 nb)
+{
+ pool->stats.nallocs++;
+ pool->stats.nbytes += nb;
+ if (nb > pool->stats.maxalloc) {
+ pool->stats.maxalloc = nb;
+ }
+ pool->stats.variance += nb * nb;
+}
+
+PR_IMPLEMENT(void) PL_ArenaCountInplaceGrowth(
+ PLArenaPool *pool, PRUint32 size, PRUint32 incr)
+{
+ pool->stats.ninplace++;
+}
+
+PR_IMPLEMENT(void) PL_ArenaCountGrowth(
+ PLArenaPool *pool, PRUint32 size, PRUint32 incr)
+{
+ pool->stats.ngrows++;
+ pool->stats.nbytes += incr;
+ pool->stats.variance -= size * size;
+ size += incr;
+ if (size > pool->stats.maxalloc) {
+ pool->stats.maxalloc = size;
+ }
+ pool->stats.variance += size * size;
+}
+
+PR_IMPLEMENT(void) PL_ArenaCountRelease(PLArenaPool *pool, char *mark)
+{
+ pool->stats.nreleases++;
+}
+
+PR_IMPLEMENT(void) PL_ArenaCountRetract(PLArenaPool *pool, char *mark)
+{
+ pool->stats.nfastrels++;
+}
+
+#include <math.h>
+#include <stdio.h>
+
+PR_IMPLEMENT(void) PL_DumpArenaStats(FILE *fp)
+{
+ PLArenaStats *stats;
+ double mean, variance;
+
+ for (stats = arena_stats_list; stats; stats = stats->next) {
+ if (stats->nallocs != 0) {
+ mean = (double)stats->nbytes / stats->nallocs;
+ variance = fabs(stats->variance / stats->nallocs - mean * mean);
+ } else {
+ mean = variance = 0;
+ }
+
+ fprintf(fp, "\n%s allocation statistics:\n", stats->name);
+ fprintf(fp, " number of arenas: %u\n", stats->narenas);
+ fprintf(fp, " number of allocations: %u\n", stats->nallocs);
+ fprintf(fp, " number of free arena reclaims: %u\n", stats->nreclaims);
+ fprintf(fp, " number of malloc calls: %u\n", stats->nmallocs);
+ fprintf(fp, " number of deallocations: %u\n", stats->ndeallocs);
+ fprintf(fp, " number of allocation growths: %u\n", stats->ngrows);
+ fprintf(fp, " number of in-place growths: %u\n", stats->ninplace);
+ fprintf(fp, "number of released allocations: %u\n", stats->nreleases);
+ fprintf(fp, " number of fast releases: %u\n", stats->nfastrels);
+ fprintf(fp, " total bytes allocated: %u\n", stats->nbytes);
+ fprintf(fp, " mean allocation size: %g\n", mean);
+ fprintf(fp, " standard deviation: %g\n", sqrt(variance));
+ fprintf(fp, " maximum allocation size: %u\n", stats->maxalloc);
+ }
+}
+#endif /* PL_ARENAMETER */
diff --git a/nsprpub/lib/ds/plarena.h b/nsprpub/lib/ds/plarena.h
new file mode 100644
index 0000000000..0ca00c0ac1
--- /dev/null
+++ b/nsprpub/lib/ds/plarena.h
@@ -0,0 +1,338 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef plarena_h___
+#define plarena_h___
+/*
+ * Lifetime-based fast allocation, inspired by much prior art, including
+ * "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
+ * David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
+ *
+ * Also supports LIFO allocation (PL_ARENA_MARK/PL_ARENA_RELEASE).
+ */
+#include "prtypes.h"
+
+PR_BEGIN_EXTERN_C
+
+typedef struct PLArena PLArena;
+
+struct PLArena {
+ PLArena *next; /* next arena for this lifetime */
+ PRUword base; /* aligned base address, follows this header */
+ PRUword limit; /* one beyond last byte in arena */
+ PRUword avail; /* points to next available byte */
+};
+
+#ifdef PL_ARENAMETER
+typedef struct PLArenaStats PLArenaStats;
+
+struct PLArenaStats {
+ PLArenaStats *next; /* next in arenaStats list */
+ char *name; /* name for debugging */
+ PRUint32 narenas; /* number of arenas in pool */
+ PRUint32 nallocs; /* number of PL_ARENA_ALLOCATE() calls */
+ PRUint32 nreclaims; /* number of reclaims from freeArenas */
+ PRUint32 nmallocs; /* number of malloc() calls */
+ PRUint32 ndeallocs; /* number of lifetime deallocations */
+ PRUint32 ngrows; /* number of PL_ARENA_GROW() calls */
+ PRUint32 ninplace; /* number of in-place growths */
+ PRUint32 nreleases; /* number of PL_ARENA_RELEASE() calls */
+ PRUint32 nfastrels; /* number of "fast path" releases */
+ PRUint32 nbytes; /* total bytes allocated */
+ PRUint32 maxalloc; /* maximum allocation size in bytes */
+ PRFloat64 variance; /* size variance accumulator */
+};
+#endif
+
+typedef struct PLArenaPool PLArenaPool;
+
+struct PLArenaPool {
+ PLArena first; /* first arena in pool list */
+ PLArena *current; /* arena from which to allocate space */
+ PRUint32 arenasize; /* net exact size of a new arena */
+ PRUword mask; /* alignment mask (power-of-2 - 1) */
+#ifdef PL_ARENAMETER
+ PLArenaStats stats;
+#endif
+};
+
+/*
+ * WARNING: The PL_MAKE_MEM_ macros are for internal use by NSPR. Do NOT use
+ * them in your code.
+ *
+ * NOTE: Valgrind support to be added.
+ *
+ * The PL_MAKE_MEM_ macros are modeled after the MOZ_MAKE_MEM_ macros in
+ * Mozilla's mfbt/MemoryChecking.h. Only AddressSanitizer is supported now.
+ *
+ * Provides a common interface to the ASan (AddressSanitizer) and Valgrind
+ * functions used to mark memory in certain ways. In detail, the following
+ * three macros are provided:
+ *
+ * PL_MAKE_MEM_NOACCESS - Mark memory as unsafe to access (e.g. freed)
+ * PL_MAKE_MEM_UNDEFINED - Mark memory as accessible, with content undefined
+ * PL_MAKE_MEM_DEFINED - Mark memory as accessible, with content defined
+ *
+ * With Valgrind in use, these directly map to the three respective Valgrind
+ * macros. With ASan in use, the NOACCESS macro maps to poisoning the memory,
+ * while the UNDEFINED/DEFINED macros unpoison memory.
+ *
+ * With no memory checker available, all macros expand to the empty statement.
+ */
+
+/* WARNING: PL_SANITIZE_ADDRESS is for internal use by this header. Do NOT
+ * define or test this macro in your code.
+ */
+#if defined(__has_feature)
+#if __has_feature(address_sanitizer)
+#define PL_SANITIZE_ADDRESS 1
+#endif
+#elif defined(__SANITIZE_ADDRESS__)
+#define PL_SANITIZE_ADDRESS 1
+#endif
+
+#if defined(PL_SANITIZE_ADDRESS)
+
+#if defined(_MSC_VER)
+/* We can't use dllimport due to DLL linkage mismatch with
+ * sanitizer/asan_interface.h.
+ */
+#define PL_ASAN_VISIBILITY(type_) type_
+#else
+#define PL_ASAN_VISIBILITY(type_) PR_IMPORT(type_)
+#endif
+
+/* These definitions are usually provided through the
+ * sanitizer/asan_interface.h header installed by ASan.
+ * See https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning
+ */
+
+PL_ASAN_VISIBILITY(void) __asan_poison_memory_region(
+ void const volatile *addr, size_t size);
+PL_ASAN_VISIBILITY(void) __asan_unpoison_memory_region(
+ void const volatile *addr, size_t size);
+
+#define PL_MAKE_MEM_NOACCESS(addr, size) \
+ __asan_poison_memory_region((addr), (size))
+
+#define PL_MAKE_MEM_UNDEFINED(addr, size) \
+ __asan_unpoison_memory_region((addr), (size))
+
+#define PL_MAKE_MEM_DEFINED(addr, size) \
+ __asan_unpoison_memory_region((addr), (size))
+
+#else
+
+#define PL_MAKE_MEM_NOACCESS(addr, size)
+#define PL_MAKE_MEM_UNDEFINED(addr, size)
+#define PL_MAKE_MEM_DEFINED(addr, size)
+
+#endif
+
+/*
+ * If the including .c file uses only one power-of-2 alignment, it may define
+ * PL_ARENA_CONST_ALIGN_MASK to the alignment mask and save a few instructions
+ * per ALLOCATE and GROW.
+ */
+#ifdef PL_ARENA_CONST_ALIGN_MASK
+#define PL_ARENA_ALIGN(pool, n) (((PRUword)(n) + PL_ARENA_CONST_ALIGN_MASK) \
+ & ~PL_ARENA_CONST_ALIGN_MASK)
+
+#define PL_INIT_ARENA_POOL(pool, name, size) \
+ PL_InitArenaPool(pool, name, size, PL_ARENA_CONST_ALIGN_MASK + 1)
+#else
+#define PL_ARENA_ALIGN(pool, n) (((PRUword)(n) + (pool)->mask) & ~(pool)->mask)
+#endif
+
+#define PL_ARENA_ALLOCATE(p, pool, nb) \
+ PR_BEGIN_MACRO \
+ PLArena *_a = (pool)->current; \
+ PRUint32 _nb = PL_ARENA_ALIGN(pool, (PRUint32)nb); \
+ PRUword _p = _a->avail; \
+ if (_nb < (PRUint32)nb) { \
+ _p = 0; \
+ } else if (_nb > (_a->limit - _a->avail)) { \
+ _p = (PRUword)PL_ArenaAllocate(pool, _nb); \
+ } else { \
+ _a->avail += _nb; \
+ } \
+ p = (void *)_p; \
+ if (p) { \
+ PL_MAKE_MEM_UNDEFINED(p, (PRUint32)nb); \
+ PL_ArenaCountAllocation(pool, (PRUint32)nb); \
+ } \
+ PR_END_MACRO
+
+#define PL_ARENA_GROW(p, pool, size, incr) \
+ PR_BEGIN_MACRO \
+ PLArena *_a = (pool)->current; \
+ PRUint32 _incr = PL_ARENA_ALIGN(pool, (PRUint32)incr); \
+ if (_incr < (PRUint32)incr) { \
+ p = NULL; \
+ } else if (_a->avail == (PRUword)(p) + PL_ARENA_ALIGN(pool, size) && \
+ _incr <= (_a->limit - _a->avail)) { \
+ PL_MAKE_MEM_UNDEFINED((unsigned char *)(p) + size, (PRUint32)incr); \
+ _a->avail += _incr; \
+ PL_ArenaCountInplaceGrowth(pool, size, (PRUint32)incr); \
+ } else { \
+ p = PL_ArenaGrow(pool, p, size, (PRUint32)incr); \
+ } \
+ if (p) {\
+ PL_ArenaCountGrowth(pool, size, (PRUint32)incr); \
+ } \
+ PR_END_MACRO
+
+#define PL_ARENA_MARK(pool) ((void *) (pool)->current->avail)
+#define PR_UPTRDIFF(p,q) ((PRUword)(p) - (PRUword)(q))
+
+#define PL_CLEAR_UNUSED_PATTERN(a, pattern) \
+ PR_BEGIN_MACRO \
+ PR_ASSERT((a)->avail <= (a)->limit); \
+ PL_MAKE_MEM_UNDEFINED((void*)(a)->avail, (a)->limit - (a)->avail); \
+ memset((void*)(a)->avail, (pattern), (a)->limit - (a)->avail); \
+ PR_END_MACRO
+#ifdef DEBUG
+#define PL_FREE_PATTERN 0xDA
+#define PL_CLEAR_UNUSED(a) PL_CLEAR_UNUSED_PATTERN((a), PL_FREE_PATTERN)
+#define PL_CLEAR_ARENA(a) \
+ PR_BEGIN_MACRO \
+ PL_MAKE_MEM_UNDEFINED((void*)(a), (a)->limit - (PRUword)(a)); \
+ memset((void*)(a), PL_FREE_PATTERN, (a)->limit - (PRUword)(a)); \
+ PR_END_MACRO
+#else
+#define PL_CLEAR_UNUSED(a)
+#define PL_CLEAR_ARENA(a)
+#endif
+
+#define PL_ARENA_RELEASE(pool, mark) \
+ PR_BEGIN_MACRO \
+ char *_m = (char *)(mark); \
+ PLArena *_a = (pool)->current; \
+ if (PR_UPTRDIFF(_m, _a->base) <= PR_UPTRDIFF(_a->avail, _a->base)) { \
+ _a->avail = (PRUword)PL_ARENA_ALIGN(pool, _m); \
+ PL_CLEAR_UNUSED(_a); \
+ PL_MAKE_MEM_NOACCESS((void*)_a->avail, _a->limit - _a->avail); \
+ PL_ArenaCountRetract(pool, _m); \
+ } else { \
+ PL_ArenaRelease(pool, _m); \
+ } \
+ PL_ArenaCountRelease(pool, _m); \
+ PR_END_MACRO
+
+#ifdef PL_ARENAMETER
+#define PL_COUNT_ARENA(pool,op) ((pool)->stats.narenas op)
+#else
+#define PL_COUNT_ARENA(pool,op)
+#endif
+
+#define PL_ARENA_DESTROY(pool, a, pnext) \
+ PR_BEGIN_MACRO \
+ PL_COUNT_ARENA(pool,--); \
+ if ((pool)->current == (a)) (pool)->current = &(pool)->first; \
+ *(pnext) = (a)->next; \
+ PL_CLEAR_ARENA(a); \
+ free(a); \
+ (a) = 0; \
+ PR_END_MACRO
+
+/*
+** Initialize an arena pool with the given name for debugging and metering,
+** with a minimum gross size per arena of size bytes. The net size per arena
+** is smaller than the gross size by a header of four pointers plus any
+** necessary padding for alignment.
+**
+** Note: choose a gross size that's a power of two to avoid the heap allocator
+** rounding the size up.
+**/
+PR_EXTERN(void) PL_InitArenaPool(
+ PLArenaPool *pool, const char *name, PRUint32 size, PRUint32 align);
+
+/*
+** Finish using arenas, freeing all memory associated with them.
+** NOTE: this function is now a no-op. If you want to free a single
+** PLArenaPoolUse use PL_FreeArenaPool() or PL_FinishArenaPool().
+**/
+PR_EXTERN(void) PL_ArenaFinish(void);
+
+/*
+** Free the arenas in pool. The user may continue to allocate from pool
+** after calling this function. There is no need to call PL_InitArenaPool()
+** again unless PL_FinishArenaPool(pool) has been called.
+**/
+PR_EXTERN(void) PL_FreeArenaPool(PLArenaPool *pool);
+
+/*
+** Free the arenas in pool and finish using it altogether.
+**/
+PR_EXTERN(void) PL_FinishArenaPool(PLArenaPool *pool);
+
+/*
+** Compact all of the arenas in a pool so that no space is wasted.
+** NOT IMPLEMENTED. Do not use.
+**/
+PR_EXTERN(void) PL_CompactArenaPool(PLArenaPool *pool);
+
+/*
+** Friend functions used by the PL_ARENA_*() macros.
+**
+** WARNING: do not call these functions directly. Always use the
+** PL_ARENA_*() macros.
+**/
+PR_EXTERN(void *) PL_ArenaAllocate(PLArenaPool *pool, PRUint32 nb);
+
+PR_EXTERN(void *) PL_ArenaGrow(
+ PLArenaPool *pool, void *p, PRUint32 size, PRUint32 incr);
+
+PR_EXTERN(void) PL_ArenaRelease(PLArenaPool *pool, char *mark);
+
+/*
+** memset contents of all arenas in pool to pattern
+*/
+PR_EXTERN(void) PL_ClearArenaPool(PLArenaPool *pool, PRInt32 pattern);
+
+/*
+** A function like malloc_size() or malloc_usable_size() that measures the
+** size of a heap block.
+*/
+typedef size_t (*PLMallocSizeFn)(const void *ptr);
+
+/*
+** Measure all memory used by a PLArenaPool, excluding the PLArenaPool
+** structure.
+*/
+PR_EXTERN(size_t) PL_SizeOfArenaPoolExcludingPool(
+ const PLArenaPool *pool, PLMallocSizeFn mallocSizeOf);
+
+#ifdef PL_ARENAMETER
+
+#include <stdio.h>
+
+PR_EXTERN(void) PL_ArenaCountAllocation(PLArenaPool *pool, PRUint32 nb);
+
+PR_EXTERN(void) PL_ArenaCountInplaceGrowth(
+ PLArenaPool *pool, PRUint32 size, PRUint32 incr);
+
+PR_EXTERN(void) PL_ArenaCountGrowth(
+ PLArenaPool *pool, PRUint32 size, PRUint32 incr);
+
+PR_EXTERN(void) PL_ArenaCountRelease(PLArenaPool *pool, char *mark);
+
+PR_EXTERN(void) PL_ArenaCountRetract(PLArenaPool *pool, char *mark);
+
+PR_EXTERN(void) PL_DumpArenaStats(FILE *fp);
+
+#else /* !PL_ARENAMETER */
+
+#define PL_ArenaCountAllocation(ap, nb) /* nothing */
+#define PL_ArenaCountInplaceGrowth(ap, size, incr) /* nothing */
+#define PL_ArenaCountGrowth(ap, size, incr) /* nothing */
+#define PL_ArenaCountRelease(ap, mark) /* nothing */
+#define PL_ArenaCountRetract(ap, mark) /* nothing */
+
+#endif /* !PL_ARENAMETER */
+
+PR_END_EXTERN_C
+
+#endif /* plarena_h___ */
diff --git a/nsprpub/lib/ds/plarenas.h b/nsprpub/lib/ds/plarenas.h
new file mode 100644
index 0000000000..4a0f5a8d5b
--- /dev/null
+++ b/nsprpub/lib/ds/plarenas.h
@@ -0,0 +1,12 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+/*
+** PLArena-related declarations used to be split between plarenas.h and
+** plarena.h. That split wasn't useful, so now all the declarations are in
+** plarena.h. However, this file still exists so that any old code that
+** includes it will still work.
+**/
+#include "plarena.h"
diff --git a/nsprpub/lib/ds/plds.def b/nsprpub/lib/ds/plds.def
new file mode 100644
index 0000000000..cc54a4de2e
--- /dev/null
+++ b/nsprpub/lib/ds/plds.def
@@ -0,0 +1,60 @@
+;+#
+;+# 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/.
+;+#
+;+# OK, this file is meant to support SUN, LINUX, AIX, OS/2 and WINDOWS
+;+# 1. For all unix platforms, the string ";-" means "remove this line"
+;+# 2. For all unix platforms, the string " DATA " will be removed from any
+;+# line on which it occurs.
+;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
+;+# On AIX, lines containing ";+" will be removed.
+;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed.
+;+# 5. For all unix platforms, after the above processing has taken place,
+;+# all characters after the first ";" on the line will be removed.
+;+# And for AIX, the first ";" will also be removed.
+;+# This file is passed directly to windows. Since ';' is a comment, all UNIX
+;+# directives are hidden behind ";", ";+", and ";-"
+;+NSPR_4.0 {
+;+ global:
+LIBRARY plds4 ;-
+EXPORTS ;-
+PL_ArenaAllocate;
+PL_ArenaFinish;
+PL_ArenaGrow;
+PL_ArenaRelease;
+PL_CompactArenaPool;
+PL_CompareStrings;
+PL_CompareValues;
+PL_FinishArenaPool;
+PL_FreeArenaPool;
+PL_HashString;
+PL_HashTableAdd;
+PL_HashTableDestroy;
+PL_HashTableDump;
+PL_HashTableEnumerateEntries;
+PL_HashTableLookup;
+PL_HashTableRawAdd;
+PL_HashTableRawLookup;
+PL_HashTableRawRemove;
+PL_HashTableRemove;
+PL_InitArenaPool;
+PL_NewHashTable;
+libVersionPoint;
+;+ local: *;
+;+};
+;+
+;+NSPR_4.1 {
+;+ global:
+PL_HashTableLookupConst;
+PL_HashTableRawLookupConst;
+;+} NSPR_4.0;
+;+
+;+NSPR_4.8.5 {
+;+ global:
+PL_ClearArenaPool;
+;+} NSPR_4.1;
+;+NSPR_4.9.6 {
+;+ global:
+PL_SizeOfArenaPoolExcludingPool;
+;+} NSPR_4.8.5;
diff --git a/nsprpub/lib/ds/plds.rc b/nsprpub/lib/ds/plds.rc
new file mode 100644
index 0000000000..d8017e732e
--- /dev/null
+++ b/nsprpub/lib/ds/plds.rc
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "prinit.h"
+#include <winver.h>
+
+#define MY_LIBNAME "plds"
+#define MY_FILEDESCRIPTION "PLDS Library"
+
+#define STRINGIZE(x) #x
+#define STRINGIZE2(x) STRINGIZE(x)
+#define PR_VMAJOR_STR STRINGIZE2(PR_VMAJOR)
+
+#ifdef _DEBUG
+#define MY_DEBUG_STR " (debug)"
+#define MY_FILEFLAGS_1 VS_FF_DEBUG
+#else
+#define MY_DEBUG_STR ""
+#define MY_FILEFLAGS_1 0x0L
+#endif
+#if PR_BETA
+#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE
+#else
+#define MY_FILEFLAGS_2 MY_FILEFLAGS_1
+#endif
+
+#ifdef WINNT
+#define MY_FILEOS VOS_NT_WINDOWS32
+#define MY_INTERNAL_NAME "lib" MY_LIBNAME PR_VMAJOR_STR
+#else
+#define MY_FILEOS VOS__WINDOWS32
+#define MY_INTERNAL_NAME MY_LIBNAME PR_VMAJOR_STR
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version-information resource
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0
+ PRODUCTVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGS MY_FILEFLAGS_2
+ FILEOS MY_FILEOS
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L // not used
+
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0" // Lang=US English, CharSet=Unicode
+ BEGIN
+ VALUE "CompanyName", "Mozilla Foundation\0"
+ VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0"
+ VALUE "FileVersion", PR_VERSION "\0"
+ VALUE "InternalName", MY_INTERNAL_NAME "\0"
+ VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0"
+ VALUE "ProductName", "Netscape Portable Runtime\0"
+ VALUE "ProductVersion", PR_VERSION "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/nsprpub/lib/ds/plhash.c b/nsprpub/lib/ds/plhash.c
new file mode 100644
index 0000000000..95497f06fe
--- /dev/null
+++ b/nsprpub/lib/ds/plhash.c
@@ -0,0 +1,495 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+/*
+ * PL hash table package.
+ */
+#include "plhash.h"
+#include "prbit.h"
+#include "prlog.h"
+#include "prmem.h"
+#include "prtypes.h"
+#include <stdlib.h>
+#include <string.h>
+
+/* Compute the number of buckets in ht */
+#define NBUCKETS(ht) (1 << (PL_HASH_BITS - (ht)->shift))
+
+/* The smallest table has 16 buckets */
+#define MINBUCKETSLOG2 4
+#define MINBUCKETS (1 << MINBUCKETSLOG2)
+
+/* Compute the maximum entries given n buckets that we will tolerate, ~90% */
+#define OVERLOADED(n) ((n) - ((n) >> 3))
+
+/* Compute the number of entries below which we shrink the table by half */
+#define UNDERLOADED(n) (((n) > MINBUCKETS) ? ((n) >> 2) : 0)
+
+/*
+** Stubs for default hash allocator ops.
+*/
+static void * PR_CALLBACK
+DefaultAllocTable(void *pool, PRSize size)
+{
+ return PR_MALLOC(size);
+}
+
+static void PR_CALLBACK
+DefaultFreeTable(void *pool, void *item)
+{
+ PR_Free(item);
+}
+
+static PLHashEntry * PR_CALLBACK
+DefaultAllocEntry(void *pool, const void *key)
+{
+ return PR_NEW(PLHashEntry);
+}
+
+static void PR_CALLBACK
+DefaultFreeEntry(void *pool, PLHashEntry *he, PRUintn flag)
+{
+ if (flag == HT_FREE_ENTRY) {
+ PR_Free(he);
+ }
+}
+
+static PLHashAllocOps defaultHashAllocOps = {
+ DefaultAllocTable, DefaultFreeTable,
+ DefaultAllocEntry, DefaultFreeEntry
+};
+
+PR_IMPLEMENT(PLHashTable *)
+PL_NewHashTable(PRUint32 n, PLHashFunction keyHash,
+ PLHashComparator keyCompare, PLHashComparator valueCompare,
+ const PLHashAllocOps *allocOps, void *allocPriv)
+{
+ PLHashTable *ht;
+ PRSize nb;
+
+ if (n <= MINBUCKETS) {
+ n = MINBUCKETSLOG2;
+ } else {
+ n = PR_CeilingLog2(n);
+ if ((PRInt32)n < 0) {
+ return 0;
+ }
+ }
+
+ if (!allocOps) {
+ allocOps = &defaultHashAllocOps;
+ }
+
+ ht = (PLHashTable*)((*allocOps->allocTable)(allocPriv, sizeof *ht));
+ if (!ht) {
+ return 0;
+ }
+ memset(ht, 0, sizeof *ht);
+ ht->shift = PL_HASH_BITS - n;
+ n = 1 << n;
+ nb = n * sizeof(PLHashEntry *);
+ ht->buckets = (PLHashEntry**)((*allocOps->allocTable)(allocPriv, nb));
+ if (!ht->buckets) {
+ (*allocOps->freeTable)(allocPriv, ht);
+ return 0;
+ }
+ memset(ht->buckets, 0, nb);
+
+ ht->keyHash = keyHash;
+ ht->keyCompare = keyCompare;
+ ht->valueCompare = valueCompare;
+ ht->allocOps = allocOps;
+ ht->allocPriv = allocPriv;
+ return ht;
+}
+
+PR_IMPLEMENT(void)
+PL_HashTableDestroy(PLHashTable *ht)
+{
+ PRUint32 i, n;
+ PLHashEntry *he, *next;
+ const PLHashAllocOps *allocOps = ht->allocOps;
+ void *allocPriv = ht->allocPriv;
+
+ n = NBUCKETS(ht);
+ for (i = 0; i < n; i++) {
+ for (he = ht->buckets[i]; he; he = next) {
+ next = he->next;
+ (*allocOps->freeEntry)(allocPriv, he, HT_FREE_ENTRY);
+ }
+ }
+#ifdef DEBUG
+ memset(ht->buckets, 0xDB, n * sizeof ht->buckets[0]);
+#endif
+ (*allocOps->freeTable)(allocPriv, ht->buckets);
+#ifdef DEBUG
+ memset(ht, 0xDB, sizeof *ht);
+#endif
+ (*allocOps->freeTable)(allocPriv, ht);
+}
+
+/*
+** Multiplicative hash, from Knuth 6.4.
+*/
+#define GOLDEN_RATIO 0x9E3779B9U /* 2/(1+sqrt(5))*(2^32) */
+
+PR_IMPLEMENT(PLHashEntry **)
+PL_HashTableRawLookup(PLHashTable *ht, PLHashNumber keyHash, const void *key)
+{
+ PLHashEntry *he, **hep, **hep0;
+ PLHashNumber h;
+
+#ifdef HASHMETER
+ ht->nlookups++;
+#endif
+ h = keyHash * GOLDEN_RATIO;
+ h >>= ht->shift;
+ hep = hep0 = &ht->buckets[h];
+ while ((he = *hep) != 0) {
+ if (he->keyHash == keyHash && (*ht->keyCompare)(key, he->key)) {
+ /* Move to front of chain if not already there */
+ if (hep != hep0) {
+ *hep = he->next;
+ he->next = *hep0;
+ *hep0 = he;
+ }
+ return hep0;
+ }
+ hep = &he->next;
+#ifdef HASHMETER
+ ht->nsteps++;
+#endif
+ }
+ return hep;
+}
+
+/*
+** Same as PL_HashTableRawLookup but doesn't reorder the hash entries.
+*/
+PR_IMPLEMENT(PLHashEntry **)
+PL_HashTableRawLookupConst(PLHashTable *ht, PLHashNumber keyHash,
+ const void *key)
+{
+ PLHashEntry *he, **hep;
+ PLHashNumber h;
+
+#ifdef HASHMETER
+ ht->nlookups++;
+#endif
+ h = keyHash * GOLDEN_RATIO;
+ h >>= ht->shift;
+ hep = &ht->buckets[h];
+ while ((he = *hep) != 0) {
+ if (he->keyHash == keyHash && (*ht->keyCompare)(key, he->key)) {
+ break;
+ }
+ hep = &he->next;
+#ifdef HASHMETER
+ ht->nsteps++;
+#endif
+ }
+ return hep;
+}
+
+PR_IMPLEMENT(PLHashEntry *)
+PL_HashTableRawAdd(PLHashTable *ht, PLHashEntry **hep,
+ PLHashNumber keyHash, const void *key, void *value)
+{
+ PRUint32 i, n;
+ PLHashEntry *he, *next, **oldbuckets;
+ PRSize nb;
+
+ /* Grow the table if it is overloaded */
+ n = NBUCKETS(ht);
+ if (ht->nentries >= OVERLOADED(n)) {
+ oldbuckets = ht->buckets;
+ nb = 2 * n * sizeof(PLHashEntry *);
+ ht->buckets = (PLHashEntry**)
+ ((*ht->allocOps->allocTable)(ht->allocPriv, nb));
+ if (!ht->buckets) {
+ ht->buckets = oldbuckets;
+ return 0;
+ }
+ memset(ht->buckets, 0, nb);
+#ifdef HASHMETER
+ ht->ngrows++;
+#endif
+ ht->shift--;
+
+ for (i = 0; i < n; i++) {
+ for (he = oldbuckets[i]; he; he = next) {
+ next = he->next;
+ hep = PL_HashTableRawLookup(ht, he->keyHash, he->key);
+ PR_ASSERT(*hep == 0);
+ he->next = 0;
+ *hep = he;
+ }
+ }
+#ifdef DEBUG
+ memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]);
+#endif
+ (*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets);
+ hep = PL_HashTableRawLookup(ht, keyHash, key);
+ }
+
+ /* Make a new key value entry */
+ he = (*ht->allocOps->allocEntry)(ht->allocPriv, key);
+ if (!he) {
+ return 0;
+ }
+ he->keyHash = keyHash;
+ he->key = key;
+ he->value = value;
+ he->next = *hep;
+ *hep = he;
+ ht->nentries++;
+ return he;
+}
+
+PR_IMPLEMENT(PLHashEntry *)
+PL_HashTableAdd(PLHashTable *ht, const void *key, void *value)
+{
+ PLHashNumber keyHash;
+ PLHashEntry *he, **hep;
+
+ keyHash = (*ht->keyHash)(key);
+ hep = PL_HashTableRawLookup(ht, keyHash, key);
+ if ((he = *hep) != 0) {
+ /* Hit; see if values match */
+ if ((*ht->valueCompare)(he->value, value)) {
+ /* key,value pair is already present in table */
+ return he;
+ }
+ if (he->value) {
+ (*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_VALUE);
+ }
+ he->value = value;
+ return he;
+ }
+ return PL_HashTableRawAdd(ht, hep, keyHash, key, value);
+}
+
+PR_IMPLEMENT(void)
+PL_HashTableRawRemove(PLHashTable *ht, PLHashEntry **hep, PLHashEntry *he)
+{
+ PRUint32 i, n;
+ PLHashEntry *next, **oldbuckets;
+ PRSize nb;
+
+ *hep = he->next;
+ (*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_ENTRY);
+
+ /* Shrink table if it's underloaded */
+ n = NBUCKETS(ht);
+ if (--ht->nentries < UNDERLOADED(n)) {
+ oldbuckets = ht->buckets;
+ nb = n * sizeof(PLHashEntry*) / 2;
+ ht->buckets = (PLHashEntry**)(
+ (*ht->allocOps->allocTable)(ht->allocPriv, nb));
+ if (!ht->buckets) {
+ ht->buckets = oldbuckets;
+ return;
+ }
+ memset(ht->buckets, 0, nb);
+#ifdef HASHMETER
+ ht->nshrinks++;
+#endif
+ ht->shift++;
+
+ for (i = 0; i < n; i++) {
+ for (he = oldbuckets[i]; he; he = next) {
+ next = he->next;
+ hep = PL_HashTableRawLookup(ht, he->keyHash, he->key);
+ PR_ASSERT(*hep == 0);
+ he->next = 0;
+ *hep = he;
+ }
+ }
+#ifdef DEBUG
+ memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]);
+#endif
+ (*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets);
+ }
+}
+
+PR_IMPLEMENT(PRBool)
+PL_HashTableRemove(PLHashTable *ht, const void *key)
+{
+ PLHashNumber keyHash;
+ PLHashEntry *he, **hep;
+
+ keyHash = (*ht->keyHash)(key);
+ hep = PL_HashTableRawLookup(ht, keyHash, key);
+ if ((he = *hep) == 0) {
+ return PR_FALSE;
+ }
+
+ /* Hit; remove element */
+ PL_HashTableRawRemove(ht, hep, he);
+ return PR_TRUE;
+}
+
+PR_IMPLEMENT(void *)
+PL_HashTableLookup(PLHashTable *ht, const void *key)
+{
+ PLHashNumber keyHash;
+ PLHashEntry *he, **hep;
+
+ keyHash = (*ht->keyHash)(key);
+ hep = PL_HashTableRawLookup(ht, keyHash, key);
+ if ((he = *hep) != 0) {
+ return he->value;
+ }
+ return 0;
+}
+
+/*
+** Same as PL_HashTableLookup but doesn't reorder the hash entries.
+*/
+PR_IMPLEMENT(void *)
+PL_HashTableLookupConst(PLHashTable *ht, const void *key)
+{
+ PLHashNumber keyHash;
+ PLHashEntry *he, **hep;
+
+ keyHash = (*ht->keyHash)(key);
+ hep = PL_HashTableRawLookupConst(ht, keyHash, key);
+ if ((he = *hep) != 0) {
+ return he->value;
+ }
+ return 0;
+}
+
+/*
+** Iterate over the entries in the hash table calling func for each
+** entry found. Stop if "f" says to (return value & PR_ENUMERATE_STOP).
+** Return a count of the number of elements scanned.
+*/
+PR_IMPLEMENT(int)
+PL_HashTableEnumerateEntries(PLHashTable *ht, PLHashEnumerator f, void *arg)
+{
+ PLHashEntry *he, **hep;
+ PRUint32 i, nbuckets;
+ int rv, n = 0;
+ PLHashEntry *todo = 0;
+
+ nbuckets = NBUCKETS(ht);
+ for (i = 0; i < nbuckets; i++) {
+ hep = &ht->buckets[i];
+ while ((he = *hep) != 0) {
+ rv = (*f)(he, n, arg);
+ n++;
+ if (rv & (HT_ENUMERATE_REMOVE | HT_ENUMERATE_UNHASH)) {
+ *hep = he->next;
+ if (rv & HT_ENUMERATE_REMOVE) {
+ he->next = todo;
+ todo = he;
+ }
+ } else {
+ hep = &he->next;
+ }
+ if (rv & HT_ENUMERATE_STOP) {
+ goto out;
+ }
+ }
+ }
+
+out:
+ hep = &todo;
+ while ((he = *hep) != 0) {
+ PL_HashTableRawRemove(ht, hep, he);
+ }
+ return n;
+}
+
+#ifdef HASHMETER
+#include <math.h>
+#include <stdio.h>
+
+PR_IMPLEMENT(void)
+PL_HashTableDumpMeter(PLHashTable *ht, PLHashEnumerator dump, FILE *fp)
+{
+ double mean, variance;
+ PRUint32 nchains, nbuckets;
+ PRUint32 i, n, maxChain, maxChainLen;
+ PLHashEntry *he;
+
+ variance = 0;
+ nchains = 0;
+ maxChainLen = 0;
+ nbuckets = NBUCKETS(ht);
+ for (i = 0; i < nbuckets; i++) {
+ he = ht->buckets[i];
+ if (!he) {
+ continue;
+ }
+ nchains++;
+ for (n = 0; he; he = he->next) {
+ n++;
+ }
+ variance += n * n;
+ if (n > maxChainLen) {
+ maxChainLen = n;
+ maxChain = i;
+ }
+ }
+ mean = (double)ht->nentries / nchains;
+ variance = fabs(variance / nchains - mean * mean);
+
+ fprintf(fp, "\nHash table statistics:\n");
+ fprintf(fp, " number of lookups: %u\n", ht->nlookups);
+ fprintf(fp, " number of entries: %u\n", ht->nentries);
+ fprintf(fp, " number of grows: %u\n", ht->ngrows);
+ fprintf(fp, " number of shrinks: %u\n", ht->nshrinks);
+ fprintf(fp, " mean steps per hash: %g\n", (double)ht->nsteps
+ / ht->nlookups);
+ fprintf(fp, "mean hash chain length: %g\n", mean);
+ fprintf(fp, " standard deviation: %g\n", sqrt(variance));
+ fprintf(fp, " max hash chain length: %u\n", maxChainLen);
+ fprintf(fp, " max hash chain: [%u]\n", maxChain);
+
+ for (he = ht->buckets[maxChain], i = 0; he; he = he->next, i++)
+ if ((*dump)(he, i, fp) != HT_ENUMERATE_NEXT) {
+ break;
+ }
+}
+#endif /* HASHMETER */
+
+PR_IMPLEMENT(int)
+PL_HashTableDump(PLHashTable *ht, PLHashEnumerator dump, FILE *fp)
+{
+ int count;
+
+ count = PL_HashTableEnumerateEntries(ht, dump, fp);
+#ifdef HASHMETER
+ PL_HashTableDumpMeter(ht, dump, fp);
+#endif
+ return count;
+}
+
+PR_IMPLEMENT(PLHashNumber)
+PL_HashString(const void *key)
+{
+ PLHashNumber h;
+ const PRUint8 *s;
+
+ h = 0;
+ for (s = (const PRUint8*)key; *s; s++) {
+ h = PR_ROTATE_LEFT32(h, 4) ^ *s;
+ }
+ return h;
+}
+
+PR_IMPLEMENT(int)
+PL_CompareStrings(const void *v1, const void *v2)
+{
+ return strcmp((const char*)v1, (const char*)v2) == 0;
+}
+
+PR_IMPLEMENT(int)
+PL_CompareValues(const void *v1, const void *v2)
+{
+ return v1 == v2;
+}
diff --git a/nsprpub/lib/ds/plhash.h b/nsprpub/lib/ds/plhash.h
new file mode 100644
index 0000000000..2c221aed77
--- /dev/null
+++ b/nsprpub/lib/ds/plhash.h
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef plhash_h___
+#define plhash_h___
+/*
+ * API to portable hash table code.
+ */
+#include <stdio.h>
+#include "prtypes.h"
+
+PR_BEGIN_EXTERN_C
+
+typedef struct PLHashEntry PLHashEntry;
+typedef struct PLHashTable PLHashTable;
+typedef PRUint32 PLHashNumber;
+#define PL_HASH_BITS 32 /* Number of bits in PLHashNumber */
+typedef PLHashNumber (PR_CALLBACK *PLHashFunction)(const void *key);
+typedef PRIntn (PR_CALLBACK *PLHashComparator)(const void *v1, const void *v2);
+
+typedef PRIntn (PR_CALLBACK *PLHashEnumerator)(PLHashEntry *he, PRIntn i, void *arg);
+
+/* Flag bits in PLHashEnumerator's return value */
+#define HT_ENUMERATE_NEXT 0 /* continue enumerating entries */
+#define HT_ENUMERATE_STOP 1 /* stop enumerating entries */
+#define HT_ENUMERATE_REMOVE 2 /* remove and free the current entry */
+#define HT_ENUMERATE_UNHASH 4 /* just unhash the current entry */
+
+typedef struct PLHashAllocOps {
+ void * (PR_CALLBACK *allocTable)(void *pool, PRSize size);
+ void (PR_CALLBACK *freeTable)(void *pool, void *item);
+ PLHashEntry * (PR_CALLBACK *allocEntry)(void *pool, const void *key);
+ void (PR_CALLBACK *freeEntry)(void *pool, PLHashEntry *he, PRUintn flag);
+} PLHashAllocOps;
+
+#define HT_FREE_VALUE 0 /* just free the entry's value */
+#define HT_FREE_ENTRY 1 /* free value and entire entry */
+
+struct PLHashEntry {
+ PLHashEntry *next; /* hash chain linkage */
+ PLHashNumber keyHash; /* key hash function result */
+ const void *key; /* ptr to opaque key */
+ void *value; /* ptr to opaque value */
+};
+
+struct PLHashTable {
+ PLHashEntry **buckets; /* vector of hash buckets */
+ PRUint32 nentries; /* number of entries in table */
+ PRUint32 shift; /* multiplicative hash shift */
+ PLHashFunction keyHash; /* key hash function */
+ PLHashComparator keyCompare; /* key comparison function */
+ PLHashComparator valueCompare; /* value comparison function */
+ const PLHashAllocOps *allocOps; /* allocation operations */
+ void *allocPriv; /* allocation private data */
+#ifdef HASHMETER
+ PRUint32 nlookups; /* total number of lookups */
+ PRUint32 nsteps; /* number of hash chains traversed */
+ PRUint32 ngrows; /* number of table expansions */
+ PRUint32 nshrinks; /* number of table contractions */
+#endif
+};
+
+/*
+ * Create a new hash table.
+ * If allocOps is null, use default allocator ops built on top of malloc().
+ */
+PR_EXTERN(PLHashTable *)
+PL_NewHashTable(PRUint32 numBuckets, PLHashFunction keyHash,
+ PLHashComparator keyCompare, PLHashComparator valueCompare,
+ const PLHashAllocOps *allocOps, void *allocPriv);
+
+PR_EXTERN(void)
+PL_HashTableDestroy(PLHashTable *ht);
+
+/* Higher level access methods */
+PR_EXTERN(PLHashEntry *)
+PL_HashTableAdd(PLHashTable *ht, const void *key, void *value);
+
+PR_EXTERN(PRBool)
+PL_HashTableRemove(PLHashTable *ht, const void *key);
+
+PR_EXTERN(void *)
+PL_HashTableLookup(PLHashTable *ht, const void *key);
+
+PR_EXTERN(void *)
+PL_HashTableLookupConst(PLHashTable *ht, const void *key);
+
+PR_EXTERN(PRIntn)
+PL_HashTableEnumerateEntries(PLHashTable *ht, PLHashEnumerator f, void *arg);
+
+/* General-purpose C string hash function. */
+PR_EXTERN(PLHashNumber)
+PL_HashString(const void *key);
+
+/* Compare strings using strcmp(), return true if equal. */
+PR_EXTERN(PRIntn)
+PL_CompareStrings(const void *v1, const void *v2);
+
+/* Stub function just returns v1 == v2 */
+PR_EXTERN(PRIntn)
+PL_CompareValues(const void *v1, const void *v2);
+
+/* Low level access methods */
+PR_EXTERN(PLHashEntry **)
+PL_HashTableRawLookup(PLHashTable *ht, PLHashNumber keyHash, const void *key);
+
+PR_EXTERN(PLHashEntry **)
+PL_HashTableRawLookupConst(PLHashTable *ht, PLHashNumber keyHash,
+ const void *key);
+
+PR_EXTERN(PLHashEntry *)
+PL_HashTableRawAdd(PLHashTable *ht, PLHashEntry **hep, PLHashNumber keyHash,
+ const void *key, void *value);
+
+PR_EXTERN(void)
+PL_HashTableRawRemove(PLHashTable *ht, PLHashEntry **hep, PLHashEntry *he);
+
+/* This can be trivially implemented using PL_HashTableEnumerateEntries. */
+PR_EXTERN(PRIntn)
+PL_HashTableDump(PLHashTable *ht, PLHashEnumerator dump, FILE *fp);
+
+PR_END_EXTERN_C
+
+#endif /* plhash_h___ */
diff --git a/nsprpub/lib/ds/plvrsion.c b/nsprpub/lib/ds/plvrsion.c
new file mode 100644
index 0000000000..14c1d676e6
--- /dev/null
+++ b/nsprpub/lib/ds/plvrsion.c
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "prinit.h"
+#include "prvrsion.h"
+
+/************************************************************************/
+/**************************IDENTITY AND VERSIONING***********************/
+/************************************************************************/
+#include "_pl_bld.h"
+#if !defined(_BUILD_TIME)
+#ifdef HAVE_LONG_LONG
+#define _BUILD_TIME 0
+#else
+#define _BUILD_TIME {0, 0}
+#endif
+#endif
+#if !defined(_BUILD_STRING)
+#define _BUILD_STRING ""
+#endif
+#if !defined(_PRODUCTION)
+#define _PRODUCTION ""
+#endif
+#if defined(DEBUG)
+#define _DEBUG_STRING " (debug)"
+#else
+#define _DEBUG_STRING ""
+#endif
+
+/*
+ * A trick to expand the PR_VMAJOR macro before concatenation.
+ */
+#define CONCAT(x, y) x ## y
+#define CONCAT2(x, y) CONCAT(x, y)
+#define VERSION_DESC_NAME CONCAT2(prVersionDescription_libplds, PR_VMAJOR)
+
+PRVersionDescription VERSION_DESC_NAME =
+{
+ /* version */ 2, /* this is the only one supported */
+ /* buildTime */ _BUILD_TIME, /* usecs since midnight 1/1/1970 GMT */
+ /* buildTimeString */ _BUILD_STRING, /* ditto, but human readable */
+ /* vMajor */ PR_VMAJOR, /* NSPR's version number */
+ /* vMinor */ PR_VMINOR, /* and minor version */
+ /* vPatch */ PR_VPATCH, /* and patch */
+ /* beta */ PR_BETA, /* beta build boolean */
+#if defined(DEBUG)
+ /* debug */ PR_TRUE, /* a debug build */
+#else
+ /* debug */ PR_FALSE, /* an optomized build */
+#endif
+ /* special */ PR_FALSE, /* they're all special, but ... */
+ /* filename */ _PRODUCTION, /* the produced library name */
+ /* description */ "Portable runtime", /* what we are */
+ /* security */ "N/A", /* not applicable here */
+ /* copywrite */ "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/.",
+ /* comment */ "http://www.mozilla.org/MPL/",
+ /* specialString */ ""
+};
+
+#ifdef XP_UNIX
+
+/*
+ * Version information for the 'ident' and 'what commands
+ *
+ * NOTE: the first component of the concatenated rcsid string
+ * must not end in a '$' to prevent rcs keyword substitution.
+ */
+static char rcsid[] = "$Header: NSPR " PR_VERSION _DEBUG_STRING
+ " " _BUILD_STRING " $";
+static char sccsid[] = "@(#)NSPR " PR_VERSION _DEBUG_STRING
+ " " _BUILD_STRING;
+
+#endif /* XP_UNIX */
+
+#ifdef _PR_HAS_PRAGMA_DIAGNOSTIC
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#endif
+PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint()
+{
+#ifdef XP_UNIX
+ /*
+ * Add dummy references to rcsid and sccsid to prevent them
+ * from being optimized away as unused variables.
+ */
+ const char *dummy;
+
+ dummy = rcsid;
+ dummy = sccsid;
+#endif
+ return &VERSION_DESC_NAME;
+} /* versionEntryPointType */
+#ifdef _PR_HAS_PRAGMA_DIAGNOSTIC
+#pragma GCC diagnostic pop
+#endif
+
+/* plvrsion.c */
+
diff --git a/nsprpub/lib/libc/Makefile.in b/nsprpub/lib/libc/Makefile.in
new file mode 100644
index 0000000000..28027f9dd1
--- /dev/null
+++ b/nsprpub/lib/libc/Makefile.in
@@ -0,0 +1,24 @@
+#
+# 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/.
+
+#! gmake
+
+MOD_DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+export NSPR20=1
+
+include $(topsrcdir)/config/config.mk
+
+DIRS = include src
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(TARGETS)
+
diff --git a/nsprpub/lib/libc/README b/nsprpub/lib/libc/README
new file mode 100644
index 0000000000..74f246907f
--- /dev/null
+++ b/nsprpub/lib/libc/README
@@ -0,0 +1,20 @@
+NSPR 2.0 libc functions
+-----------------------
+
+Last edited: AOF 04 March 1997
+
+This directory contains various libc-types of functions. All functions in
+this directory are platform independent, thread friendly (both safe and
+efficient). They are contributed from various sources, though the contri-
+butions are monitored by the NSPR group (mailto:freier).
+
+All API items exported by these functions will contain the same three
+character prefix, "PL_" (Portable Library). Internal function names
+that are not exported (static) are of little concern, though some caution
+must be used on those elements that are 'extern' but not really intended
+to be part of the API. Those should all have a prefix of "_PL_" (is that
+legal?).
+
+The responsibility for contributions in this area are distributed among
+all interested parties.
+
diff --git a/nsprpub/lib/libc/include/Makefile.in b/nsprpub/lib/libc/include/Makefile.in
new file mode 100644
index 0000000000..642e0a1842
--- /dev/null
+++ b/nsprpub/lib/libc/include/Makefile.in
@@ -0,0 +1,24 @@
+#
+# 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/.
+
+#! gmake
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+include $(topsrcdir)/config/config.mk
+
+HEADERS = $(wildcard $(srcdir)/*.h)
+
+RELEASE_HEADERS = $(HEADERS)
+RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR)
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(HEADERS)
+ $(INSTALL) -m 444 $(HEADERS) $(dist_includedir)
diff --git a/nsprpub/lib/libc/include/README b/nsprpub/lib/libc/include/README
new file mode 100644
index 0000000000..2b85218910
--- /dev/null
+++ b/nsprpub/lib/libc/include/README
@@ -0,0 +1,7 @@
+NSPR 2.0 libc functions
+-----------------------
+
+Last edited: AOF 04 March 1997
+
+This directory contains the API for various libc-types of functions.
+
diff --git a/nsprpub/lib/libc/include/plbase64.h b/nsprpub/lib/libc/include/plbase64.h
new file mode 100644
index 0000000000..8f2117cc29
--- /dev/null
+++ b/nsprpub/lib/libc/include/plbase64.h
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef _plbase64_h
+#define _plbase64_h
+
+#include "prtypes.h"
+
+PR_BEGIN_EXTERN_C
+
+/*
+ * PL_Base64Encode
+ *
+ * This routine encodes the data pointed to by the "src" parameter using the
+ * base64 algorithm, and returns a pointer to the result. If the "srclen"
+ * parameter is not zero, it specifies the length of the source data. If it
+ * is zero, the source data is assumed to be null-terminated, and PL_strlen
+ * is used to determine the source length. If the "dest" parameter is not
+ * null, it is assumed to point to a buffer of sufficient size (which may be
+ * calculated: ((srclen + 2)/3)*4) into which the encoded data is placed
+ * (without any termination). If the "dest" parameter is null, a buffer is
+ * allocated from the heap to hold the encoded data, and the result *will*
+ * be terminated with an extra null character. It is the caller's
+ * responsibility to free the result when it is allocated. A null is returned
+ * if the allocation fails.
+ *
+ * NOTE: when calculating ((srclen + 2)/3)*4), first ensure that
+ * srclen <= (PR_UINT32_MAX/4) * 3
+ * to avoid PRUint32 overflow.
+ */
+
+PR_EXTERN(char *)
+PL_Base64Encode
+(
+ const char *src,
+ PRUint32 srclen,
+ char *dest
+);
+
+/*
+ * PL_Base64Decode
+ *
+ * This routine decodes the data pointed to by the "src" parameter using
+ * the base64 algorithm, and returns a pointer to the result. The source
+ * may either include or exclude any trailing '=' characters. If the
+ * "srclen" parameter is not zero, it specifies the length of the source
+ * data. If it is zero, PL_strlen will be used to determine the source
+ * length. If the "dest" parameter is not null, it is assumed to point to
+ * a buffer of sufficient size (which may be calculated: (srclen * 3)/4
+ * when srclen includes the '=' characters) into which the decoded data
+ * is placed (without any termination). If the "dest" parameter is null,
+ * a buffer is allocated from the heap to hold the decoded data, and the
+ * result *will* be terminated with an extra null character. It is the
+ * caller's responsibility to free the result when it is allocated. A null
+ * is retuned if the allocation fails, or if the source is not well-coded.
+ *
+ * NOTE: when calculating (srclen * 3)/4, first ensure that
+ * srclen <= PR_UINT32_MAX/3
+ * to avoid PRUint32 overflow. Alternatively, calculate
+ * (srclen/4) * 3 + ((srclen%4) * 3)/4
+ * which is equivalent but doesn't overflow for any value of srclen.
+ */
+
+PR_EXTERN(char *)
+PL_Base64Decode
+(
+ const char *src,
+ PRUint32 srclen,
+ char *dest
+);
+
+PR_END_EXTERN_C
+
+#endif /* _plbase64_h */
diff --git a/nsprpub/lib/libc/include/plerror.h b/nsprpub/lib/libc/include/plerror.h
new file mode 100644
index 0000000000..cd85dd3f8a
--- /dev/null
+++ b/nsprpub/lib/libc/include/plerror.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+/*
+** File: plerror.h
+** Description: Simple routine to print translate the calling thread's
+** error numbers and print them.
+*/
+
+#if defined(PLERROR_H)
+#else
+#define PLERROR_H
+
+#include "prio.h"
+#include "prtypes.h"
+
+PR_BEGIN_EXTERN_C
+/*
+** Print the messages to "syserr" prepending 'msg' if not NULL.
+*/
+PR_EXTERN(void) PL_PrintError(const char *msg);
+
+/*
+** Print the messages to specified output file prepending 'msg' if not NULL.
+*/
+PR_EXTERN(void) PL_FPrintError(PRFileDesc *output, const char *msg);
+
+PR_END_EXTERN_C
+
+#endif /* defined(PLERROR_H) */
+
+/* plerror.h */
diff --git a/nsprpub/lib/libc/include/plgetopt.h b/nsprpub/lib/libc/include/plgetopt.h
new file mode 100644
index 0000000000..bd5181b1db
--- /dev/null
+++ b/nsprpub/lib/libc/include/plgetopt.h
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+/*
+** File: plgetopt.h
+** Description: utilities to parse argc/argv
+*/
+
+#if defined(PLGETOPT_H_)
+#else
+#define PLGETOPT_H_
+
+#include "prtypes.h"
+
+PR_BEGIN_EXTERN_C
+
+typedef struct PLOptionInternal PLOptionInternal;
+
+typedef enum
+{
+ PL_OPT_OK, /* all's well with the option */
+ PL_OPT_EOL, /* end of options list */
+ PL_OPT_BAD /* invalid option (and value) */
+} PLOptStatus;
+
+typedef struct PLLongOpt
+{
+ const char * longOptName; /* long option name string */
+ PRIntn longOption; /* value put in PLOptState for this option. */
+ PRBool valueRequired; /* If option name not followed by '=', */
+ /* value is the next argument from argv. */
+} PLLongOpt;
+
+typedef struct PLOptState
+{
+ char option; /* the name of the option */
+ const char *value; /* the value of that option | NULL */
+
+ PLOptionInternal *internal; /* private processing state */
+
+ PRIntn longOption; /* value from PLLongOpt put here */
+ PRIntn longOptIndex; /* index into caller's array of PLLongOpts */
+} PLOptState;
+
+/*
+ * PL_CreateOptState
+ *
+ * The argument "options" points to a string of single-character option
+ * names. Option names that may have an option argument value must be
+ * followed immediately by a ':' character.
+ */
+PR_EXTERN(PLOptState*) PL_CreateOptState(
+ PRIntn argc, char **argv, const char *options);
+
+/*
+ * PL_CreateLongOptState
+ *
+ * Alternative to PL_CreateOptState.
+ * Allows caller to specify BOTH a string of single-character option names,
+ * AND an array of structures describing "long" (keyword) option names.
+ * The array is terminated by a structure in which longOptName is NULL.
+ * Long option values (arguments) may always be given as "--name=value".
+ * If PLLongOpt.valueRequired is not PR_FALSE, and the option name was not
+ * followed by '=' then the next argument from argv is taken as the value.
+ */
+PR_EXTERN(PLOptState*) PL_CreateLongOptState(
+ PRIntn argc, char **argv, const char *options,
+ const PLLongOpt *longOpts);
+/*
+ * PL_DestroyOptState
+ *
+ * Call this to destroy the PLOptState returned from PL_CreateOptState or
+ * PL_CreateLongOptState.
+ */
+PR_EXTERN(void) PL_DestroyOptState(PLOptState *opt);
+
+/*
+ * PL_GetNextOpt
+ *
+ * When this function returns PL_OPT_OK,
+ * - opt->option will hold the single-character option name that was parsed,
+ * or zero.
+ * When opt->option is zero, the token parsed was either a "long" (keyword)
+ * option or a positional parameter.
+ * For a positional parameter,
+ * - opt->longOptIndex will contain -1, and
+ * - opt->value will point to the positional parameter string.
+ * For a long option name,
+ * - opt->longOptIndex will contain the non-negative index of the
+ * PLLongOpt structure in the caller's array of PLLongOpt structures
+ * corresponding to the long option name, and
+ * For a single-character or long option,
+ * - opt->longOption will contain the value of the single-character option
+ * name, or the value of the longOption from the PLLongOpt structure
+ * for that long option. See notes below.
+ * - opt->value will point to the argument option string, or will
+ * be NULL if option does not require argument. If option requires
+ * argument but it is not provided, PL_OPT_BAD is returned.
+ * When opt->option is non-zero,
+ * - opt->longOptIndex will be -1
+ * When this function returns PL_OPT_EOL, or PL_OPT_BAD, the contents of
+ * opt are undefined.
+ *
+ * Notes: It is possible to ignore opt->option, and always look at
+ * opt->longOption instead. opt->longOption will contain the same value
+ * as opt->option for single-character option names, and will contain the
+ * value of longOption from the PLLongOpt structure for long option names.
+ * This means that it is possible to equivalence long option names to
+ * single character names by giving the longOption in the PLLongOpt struct
+ * the same value as the single-character option name.
+ * For long options that are NOT intended to be equivalent to any single-
+ * character option, the longOption value should be chosen to not match
+ * any possible single character name. It might be advisable to choose
+ * longOption values greater than 0xff for such long options.
+ */
+PR_EXTERN(PLOptStatus) PL_GetNextOpt(PLOptState *opt);
+
+PR_END_EXTERN_C
+
+#endif /* defined(PLGETOPT_H_) */
+
+/* plgetopt.h */
+
diff --git a/nsprpub/lib/libc/include/plstr.h b/nsprpub/lib/libc/include/plstr.h
new file mode 100644
index 0000000000..ea59832a35
--- /dev/null
+++ b/nsprpub/lib/libc/include/plstr.h
@@ -0,0 +1,437 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef _plstr_h
+#define _plstr_h
+
+/*
+ * plstr.h
+ *
+ * This header file exports the API to the NSPR portable library or string-
+ * handling functions.
+ *
+ * This API was not designed as an "optimal" or "ideal" string library; it
+ * was based on the good ol' unix string.3 functions, and was written to
+ *
+ * 1) replace the libc functions, for cross-platform consistency,
+ * 2) complete the API on platforms lacking common functions (e.g.,
+ * strcase*), and
+ * 3) to implement some obvious "closure" functions that I've seen
+ * people hacking around in our code.
+ *
+ * Point number three largely means that most functions have an "strn"
+ * limited-length version, and all comparison routines have a non-case-
+ * sensitive version available.
+ */
+
+#include "prtypes.h"
+
+PR_BEGIN_EXTERN_C
+/*
+ * PL_strlen
+ *
+ * Returns the length of the provided string, not including the trailing '\0'.
+ */
+
+PR_EXTERN(PRUint32)
+PL_strlen(const char *str);
+
+/*
+ * PL_strnlen
+ *
+ * Returns the length of the provided string, not including the trailing '\0',
+ * up to the indicated maximum. The string will not be examined beyond the
+ * maximum; if no terminating '\0' is found, the maximum will be returned.
+ */
+
+PR_EXTERN(PRUint32)
+PL_strnlen(const char *str, PRUint32 max);
+
+/*
+ * PL_strcpy
+ *
+ * Copies the source string, up to and including the trailing '\0', into the
+ * destination buffer. It does not (can not) verify that the destination
+ * buffer is large enough. It returns the "dest" argument.
+ */
+
+PR_EXTERN(char *)
+PL_strcpy(char *dest, const char *src);
+
+/*
+ * PL_strncpy
+ *
+ * Copies the source string into the destination buffer, up to and including
+ * the trailing '\0' or up to and including the max'th character, whichever
+ * comes first. It does not (can not) verify that the destination buffer is
+ * large enough. If the source string is longer than the maximum length,
+ * the result will *not* be null-terminated (JLRU).
+ */
+
+PR_EXTERN(char *)
+PL_strncpy(char *dest, const char *src, PRUint32 max);
+
+/*
+ * PL_strncpyz
+ *
+ * Copies the source string into the destination buffer, up to and including
+ * the trailing '\0' or up but not including the max'th character, whichever
+ * comes first. It does not (can not) verify that the destination buffer is
+ * large enough. The destination string is always terminated with a '\0',
+ * unlike the traditional libc implementation. It returns the "dest" argument.
+ *
+ * NOTE: If you call this with a source "abcdefg" and a max of 5, the
+ * destination will end up with "abcd\0" (i.e., its strlen length will be 4)!
+ *
+ * This means you can do this:
+ *
+ * char buffer[ SOME_SIZE ];
+ * PL_strncpyz(buffer, src, sizeof(buffer));
+ *
+ * and the result will be properly terminated.
+ */
+
+PR_EXTERN(char *)
+PL_strncpyz(char *dest, const char *src, PRUint32 max);
+
+/*
+ * PL_strdup
+ *
+ * Returns a pointer to a malloc'd extent of memory containing a duplicate
+ * of the argument string. The size of the allocated extent is one greater
+ * than the length of the argument string, because of the terminator. A
+ * null argument, like a zero-length argument, will result in a pointer to
+ * a one-byte extent containing the null value. This routine returns null
+ * upon malloc failure.
+ */
+
+PR_EXTERN(char *)
+PL_strdup(const char *s);
+
+/*
+ * PL_strfree
+ *
+ * Free memory allocated by PL_strdup
+ */
+
+PR_EXTERN(void)
+PL_strfree(char *s);
+
+/*
+ * PL_strndup
+ *
+ * Returns a pointer to a malloc'd extent of memory containing a duplicate
+ * of the argument string, up to the maximum specified. If the argument
+ * string has a length greater than the value of the specified maximum, the
+ * return value will be a pointer to an extent of memory of length one
+ * greater than the maximum specified. A null string, a zero-length string,
+ * or a zero maximum will all result in a pointer to a one-byte extent
+ * containing the null value. This routine returns null upon malloc failure.
+ */
+
+PR_EXTERN(char *)
+PL_strndup(const char *s, PRUint32 max);
+
+/*
+ * PL_strcat
+ *
+ * Appends a copy of the string pointed to by the second argument to the
+ * end of the string pointed to by the first. The destination buffer is
+ * not (can not be) checked for sufficient size. A null destination
+ * argument returns null; otherwise, the first argument is returned.
+ */
+
+PR_EXTERN(char *)
+PL_strcat(char *dst, const char *src);
+
+/*
+ * PL_strncat
+ *
+ * Appends a copy of the string pointed to by the second argument, up to
+ * the maximum size specified, to the end of the string pointed to by the
+ * first. The destination buffer is not (can not be) checked for sufficient
+ * size. A null destination argument returns null; otherwise, the first
+ * argument is returned. If the maximum size limits the copy, then the
+ * result will *not* be null-terminated (JLRU). A null destination
+ * returns null; otherwise, the destination argument is returned.
+ */
+
+PR_EXTERN(char *)
+PL_strncat(char *dst, const char *src, PRUint32 max);
+
+/*
+ * PL_strcatn
+ *
+ * Appends a copy of the string pointed to by the third argument, to the
+ * end of the string pointed to by the first. The second argument specifies
+ * the maximum size of the destination buffer, including the null termination.
+ * If the existing string in dst is longer than the max, no action is taken.
+ * The resulting string will be null-terminated. A null destination returns
+ * null; otherwise, the destination argument is returned.
+ */
+
+PR_EXTERN(char *)
+PL_strcatn(char *dst, PRUint32 max, const char *src);
+
+/*
+ * PL_strcmp
+ *
+ * Returns an integer, the sign of which -- positive, zero, or negative --
+ * reflects the lexical sorting order of the two strings indicated. The
+ * result is positive if the first string comes after the second. The
+ * NSPR implementation is not i18n.
+ */
+
+PR_EXTERN(PRIntn)
+PL_strcmp(const char *a, const char *b);
+
+/*
+ * PL_strncmp
+ *
+ * Returns an integer, the sign of which -- positive, zero, or negative --
+ * reflects the lexical sorting order of the two strings indicated, up to
+ * the maximum specified. The result is positive if the first string comes
+ * after the second. The NSPR implementation is not i18n. If the maximum
+ * is zero, only the existance or non-existance (pointer is null) of the
+ * strings is compared.
+ */
+
+PR_EXTERN(PRIntn)
+PL_strncmp(const char *a, const char *b, PRUint32 max);
+
+/*
+ * PL_strcasecmp
+ *
+ * Returns an integer, the sign of which -- positive, zero or negative --
+ * reflects the case-insensitive lexical sorting order of the two strings
+ * indicated. The result is positive if the first string comes after the
+ * second. The NSPR implementation is not i18n.
+ */
+
+PR_EXTERN(PRIntn)
+PL_strcasecmp(const char *a, const char *b);
+
+/*
+ * PL_strncasecmp
+ *
+ * Returns an integer, the sign of which -- positive, zero or negative --
+ * reflects the case-insensitive lexical sorting order of the first n characters
+ * of the two strings indicated. The result is positive if the first string comes
+ * after the second. The NSPR implementation is not i18n.
+ */
+
+PR_EXTERN(PRIntn)
+PL_strncasecmp(const char *a, const char *b, PRUint32 max);
+
+/*
+ * PL_strchr
+ *
+ * Returns a pointer to the first instance of the specified character in the
+ * provided string. It returns null if the character is not found, or if the
+ * provided string is null. The character may be the null character.
+ */
+
+PR_EXTERN(char *)
+PL_strchr(const char *s, char c);
+
+/*
+ * PL_strrchr
+ *
+ * Returns a pointer to the last instance of the specified character in the
+ * provided string. It returns null if the character is not found, or if the
+ * provided string is null. The character may be the null character.
+ */
+
+PR_EXTERN(char *)
+PL_strrchr(const char *s, char c);
+
+/*
+ * PL_strnchr
+ *
+ * Returns a pointer to the first instance of the specified character within the
+ * first n characters of the provided string. It returns null if the character
+ * is not found, or if the provided string is null. The character may be the
+ * null character.
+ */
+
+PR_EXTERN(char *)
+PL_strnchr(const char *s, char c, PRUint32 n);
+
+/*
+ * PL_strnrchr
+ *
+ * Returns a pointer to the last instance of the specified character within the
+ * first n characters of the provided string. It returns null if the character is
+ * not found, or if the provided string is null. The character may be the null
+ * character.
+ */
+
+PR_EXTERN(char *)
+PL_strnrchr(const char *s, char c, PRUint32 n);
+
+/*
+ * NOTE: Looking for strcasechr, strcaserchr, strncasechr, or strncaserchr?
+ * Use strpbrk, strprbrk, strnpbrk or strnprbrk.
+ */
+
+/*
+ * PL_strpbrk
+ *
+ * Returns a pointer to the first instance in the first string of any character
+ * (not including the terminating null character) of the second string. It returns
+ * null if either string is null.
+ */
+
+PR_EXTERN(char *)
+PL_strpbrk(const char *s, const char *list);
+
+/*
+ * PL_strprbrk
+ *
+ * Returns a pointer to the last instance in the first string of any character
+ * (not including the terminating null character) of the second string. It returns
+ * null if either string is null.
+ */
+
+PR_EXTERN(char *)
+PL_strprbrk(const char *s, const char *list);
+
+/*
+ * PL_strnpbrk
+ *
+ * Returns a pointer to the first instance (within the first n characters) of any
+ * character (not including the terminating null character) of the second string.
+ * It returns null if either string is null.
+ */
+
+PR_EXTERN(char *)
+PL_strnpbrk(const char *s, const char *list, PRUint32 n);
+
+/*
+ * PL_strnprbrk
+ *
+ * Returns a pointer to the last instance (within the first n characters) of any
+ * character (not including the terminating null character) of the second string.
+ * It returns null if either string is null.
+ */
+
+PR_EXTERN(char *)
+PL_strnprbrk(const char *s, const char *list, PRUint32 n);
+
+/*
+ * PL_strstr
+ *
+ * Returns a pointer to the first instance of the little string within the
+ * big one. It returns null if either string is null.
+ */
+
+PR_EXTERN(char *)
+PL_strstr(const char *big, const char *little);
+
+/*
+ * PL_strrstr
+ *
+ * Returns a pointer to the last instance of the little string within the big one.
+ * It returns null if either string is null.
+ */
+
+PR_EXTERN(char *)
+PL_strrstr(const char *big, const char *little);
+
+/*
+ * PL_strnstr
+ *
+ * Returns a pointer to the first instance of the little string within the first
+ * n characters of the big one. It returns null if either string is null. It
+ * returns null if the length of the little string is greater than n.
+ */
+
+PR_EXTERN(char *)
+PL_strnstr(const char *big, const char *little, PRUint32 n);
+
+/*
+ * PL_strnrstr
+ *
+ * Returns a pointer to the last instance of the little string within the first
+ * n characters of the big one. It returns null if either string is null. It
+ * returns null if the length of the little string is greater than n.
+ */
+
+PR_EXTERN(char *)
+PL_strnrstr(const char *big, const char *little, PRUint32 max);
+
+/*
+ * PL_strcasestr
+ *
+ * Returns a pointer to the first instance of the little string within the big one,
+ * ignoring case. It returns null if either string is null.
+ */
+
+PR_EXTERN(char *)
+PL_strcasestr(const char *big, const char *little);
+
+/*
+ * PL_strcaserstr
+ *
+ * Returns a pointer to the last instance of the little string within the big one,
+ * ignoring case. It returns null if either string is null.
+ */
+
+PR_EXTERN(char *)
+PL_strcaserstr(const char *big, const char *little);
+
+/*
+ * PL_strncasestr
+ *
+ * Returns a pointer to the first instance of the little string within the first
+ * n characters of the big one, ignoring case. It returns null if either string is
+ * null. It returns null if the length of the little string is greater than n.
+ */
+
+PR_EXTERN(char *)
+PL_strncasestr(const char *big, const char *little, PRUint32 max);
+
+/*
+ * PL_strncaserstr
+ *
+ * Returns a pointer to the last instance of the little string within the first
+ * n characters of the big one, ignoring case. It returns null if either string is
+ * null. It returns null if the length of the little string is greater than n.
+ */
+
+PR_EXTERN(char *)
+PL_strncaserstr(const char *big, const char *little, PRUint32 max);
+
+/*
+ * PL_strtok_r
+ *
+ * Splits the string s1 into tokens, separated by one or more characters
+ * from the separator string s2. The argument lasts points to a
+ * user-supplied char * pointer in which PL_strtok_r stores information
+ * for it to continue scanning the same string.
+ *
+ * In the first call to PL_strtok_r, s1 points to a string and the value
+ * of *lasts is ignored. PL_strtok_r returns a pointer to the first
+ * token, writes '\0' into the character following the first token, and
+ * updates *lasts.
+ *
+ * In subsequent calls, s1 is null and lasts must stay unchanged from the
+ * previous call. The separator string s2 may be different from call to
+ * call. PL_strtok_r returns a pointer to the next token in s1. When no
+ * token remains in s1, PL_strtok_r returns null.
+ */
+
+PR_EXTERN(char *)
+PL_strtok_r(char *s1, const char *s2, char **lasts);
+
+/*
+ * Things not (yet?) included: strspn/strcspn, strsep.
+ * memchr, memcmp, memcpy, memccpy, index, rindex, bcmp, bcopy, bzero.
+ * Any and all i18n/l10n stuff.
+ */
+
+PR_END_EXTERN_C
+
+#endif /* _plstr_h */
diff --git a/nsprpub/lib/libc/src/Makefile.in b/nsprpub/lib/libc/src/Makefile.in
new file mode 100644
index 0000000000..be488e956f
--- /dev/null
+++ b/nsprpub/lib/libc/src/Makefile.in
@@ -0,0 +1,148 @@
+#
+# 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/.
+
+
+#! gmake
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+INCLUDES = -I$(dist_includedir)
+
+CSRCS =\
+ plvrsion.c \
+ strlen.c \
+ strcpy.c \
+ strdup.c \
+ strcase.c \
+ strcat.c \
+ strcmp.c \
+ strchr.c \
+ strpbrk.c \
+ strstr.c \
+ strtok.c \
+ base64.c \
+ plerror.c \
+ plgetopt.c \
+ $(NULL)
+
+LIBRARY_NAME = plc
+LIBRARY_VERSION = $(MOD_MAJOR_VERSION)
+
+RELEASE_LIBS = $(TARGETS)
+
+ifeq ($(OS_ARCH),WINNT)
+RES=$(OBJDIR)/plc.res
+RESNAME=plc.rc
+endif # WINNT
+
+ifeq ($(OS_ARCH), AIX)
+ifeq ($(CLASSIC_NSPR),1)
+OS_LIBS = -lc
+else
+OS_LIBS = -lc_r
+endif
+endif
+
+ifeq ($(OS_ARCH),SunOS)
+OS_LIBS = -lc
+MAPFILE = $(OBJDIR)/plcmap.sun
+GARBAGE += $(MAPFILE)
+ifdef NS_USE_GCC
+ifdef GCC_USE_GNU_LD
+MKSHLIB += -Wl,--version-script,$(MAPFILE)
+else
+MKSHLIB += -Wl,-M,$(MAPFILE)
+endif
+else
+MKSHLIB += -M $(MAPFILE)
+endif
+# The -R '$ORIGIN' linker option instructs this library to search for its
+# dependencies in the same directory where it resides.
+MKSHLIB += -R '$$ORIGIN'
+endif
+
+ifeq ($(OS_ARCH),OS2)
+MAPFILE = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).def
+GARBAGE += $(MAPFILE)
+MKSHLIB += $(MAPFILE)
+endif
+
+EXTRA_LIBS = $(LIBNSPR)
+
+# On SCOOS, we can't link with extra libraries when
+# we build a shared library. If we do so, the linker doesn't
+# complain, but we would run into weird problems at run-time.
+# Therefore on these platforms, we link just the .o files.
+ifeq ($(OS_ARCH),SCOOS)
+EXTRA_LIBS =
+endif
+
+ifdef RESOLVE_LINK_SYMBOLS
+EXTRA_LIBS += $(OS_LIBS)
+endif
+
+include $(topsrcdir)/config/rules.mk
+
+#
+# Version information generation (begin)
+#
+ECHO = echo
+TINC = $(OBJDIR)/_pl_bld.h
+PROD = $(notdir $(SHARED_LIBRARY))
+NOW = $(MOD_DEPTH)/config/$(OBJDIR)/now
+SH_DATE = $(shell date "+%Y-%m-%d %T")
+SH_NOW = $(shell $(NOW))
+
+ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
+ SUF = i64
+else
+ SUF = LL
+endif
+
+GARBAGE += $(TINC)
+
+$(TINC):
+ @$(MAKE_OBJDIR)
+ @$(ECHO) '#define _BUILD_STRING "$(SH_DATE)"' > $(TINC)
+ @if test ! -z "$(SH_NOW)"; then \
+ $(ECHO) '#define _BUILD_TIME $(SH_NOW)$(SUF)' >> $(TINC); \
+ else \
+ true; \
+ fi
+ @$(ECHO) '#define _PRODUCTION "$(PROD)"' >> $(TINC)
+
+
+$(OBJDIR)/plvrsion.$(OBJ_SUFFIX): plvrsion.c $(TINC)
+ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
+ $(CC) -Fo$@ -c $(CFLAGS) -I$(OBJDIR) $<
+else
+ $(CC) -o $@ -c $(CFLAGS) -I$(OBJDIR) $<
+endif
+#
+# Version information generation (end)
+#
+
+#
+# The Client build wants the shared libraries in $(dist_bindir),
+# so we also install them there.
+#
+
+export:: $(TARGETS)
+ $(INSTALL) -m 444 $(TARGETS) $(dist_libdir)
+ifdef SHARED_LIBRARY
+ifeq ($(OS_ARCH),HP-UX)
+ $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_libdir)
+ $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_bindir)
+else
+ $(INSTALL) -m 444 $(SHARED_LIBRARY) $(dist_bindir)
+endif
+endif
diff --git a/nsprpub/lib/libc/src/README b/nsprpub/lib/libc/src/README
new file mode 100644
index 0000000000..74f246907f
--- /dev/null
+++ b/nsprpub/lib/libc/src/README
@@ -0,0 +1,20 @@
+NSPR 2.0 libc functions
+-----------------------
+
+Last edited: AOF 04 March 1997
+
+This directory contains various libc-types of functions. All functions in
+this directory are platform independent, thread friendly (both safe and
+efficient). They are contributed from various sources, though the contri-
+butions are monitored by the NSPR group (mailto:freier).
+
+All API items exported by these functions will contain the same three
+character prefix, "PL_" (Portable Library). Internal function names
+that are not exported (static) are of little concern, though some caution
+must be used on those elements that are 'extern' but not really intended
+to be part of the API. Those should all have a prefix of "_PL_" (is that
+legal?).
+
+The responsibility for contributions in this area are distributed among
+all interested parties.
+
diff --git a/nsprpub/lib/libc/src/base64.c b/nsprpub/lib/libc/src/base64.c
new file mode 100644
index 0000000000..fc1cc51eb8
--- /dev/null
+++ b/nsprpub/lib/libc/src/base64.c
@@ -0,0 +1,416 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "plbase64.h"
+#include "prlog.h" /* For PR_NOT_REACHED */
+#include "prmem.h" /* for malloc / PR_MALLOC */
+
+#include <string.h> /* for strlen */
+
+static unsigned char *base = (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static void
+encode3to4
+(
+ const unsigned char *src,
+ unsigned char *dest
+)
+{
+ PRUint32 b32 = (PRUint32)0;
+ PRIntn i, j = 18;
+
+ for( i = 0; i < 3; i++ )
+ {
+ b32 <<= 8;
+ b32 |= (PRUint32)src[i];
+ }
+
+ for( i = 0; i < 4; i++ )
+ {
+ dest[i] = base[ (PRUint32)((b32>>j) & 0x3F) ];
+ j -= 6;
+ }
+
+ return;
+}
+
+static void
+encode2to4
+(
+ const unsigned char *src,
+ unsigned char *dest
+)
+{
+ dest[0] = base[ (PRUint32)((src[0]>>2) & 0x3F) ];
+ dest[1] = base[ (PRUint32)(((src[0] & 0x03) << 4) | ((src[1] >> 4) & 0x0F)) ];
+ dest[2] = base[ (PRUint32)((src[1] & 0x0F) << 2) ];
+ dest[3] = (unsigned char)'=';
+ return;
+}
+
+static void
+encode1to4
+(
+ const unsigned char *src,
+ unsigned char *dest
+)
+{
+ dest[0] = base[ (PRUint32)((src[0]>>2) & 0x3F) ];
+ dest[1] = base[ (PRUint32)((src[0] & 0x03) << 4) ];
+ dest[2] = (unsigned char)'=';
+ dest[3] = (unsigned char)'=';
+ return;
+}
+
+static void
+encode
+(
+ const unsigned char *src,
+ PRUint32 srclen,
+ unsigned char *dest
+)
+{
+ while( srclen >= 3 )
+ {
+ encode3to4(src, dest);
+ src += 3;
+ dest += 4;
+ srclen -= 3;
+ }
+
+ switch( srclen )
+ {
+ case 2:
+ encode2to4(src, dest);
+ break;
+ case 1:
+ encode1to4(src, dest);
+ break;
+ case 0:
+ break;
+ default:
+ PR_NOT_REACHED("coding error");
+ }
+
+ return;
+}
+
+/*
+ * PL_Base64Encode
+ *
+ * If the destination argument is NULL, a return buffer is
+ * allocated, and the data therein will be null-terminated.
+ * If the destination argument is not NULL, it is assumed to
+ * be of sufficient size, and the contents will not be null-
+ * terminated by this routine.
+ *
+ * Returns null if the allocation fails.
+ */
+
+PR_IMPLEMENT(char *)
+PL_Base64Encode
+(
+ const char *src,
+ PRUint32 srclen,
+ char *dest
+)
+{
+ if( 0 == srclen )
+ {
+ size_t len = strlen(src);
+ srclen = len;
+ /* Detect truncation. */
+ if( srclen != len )
+ {
+ return (char *)0;
+ }
+ }
+
+ if( (char *)0 == dest )
+ {
+ PRUint32 destlen;
+ /* Ensure all PRUint32 values stay within range. */
+ if( srclen > (PR_UINT32_MAX/4) * 3 )
+ {
+ return (char *)0;
+ }
+ destlen = ((srclen + 2)/3) * 4;
+ dest = (char *)PR_MALLOC(destlen + 1);
+ if( (char *)0 == dest )
+ {
+ return (char *)0;
+ }
+ dest[ destlen ] = (char)0; /* null terminate */
+ }
+
+ encode((const unsigned char *)src, srclen, (unsigned char *)dest);
+ return dest;
+}
+
+static PRInt32
+codetovalue
+(
+ unsigned char c
+)
+{
+ if( (c >= (unsigned char)'A') && (c <= (unsigned char)'Z') )
+ {
+ return (PRInt32)(c - (unsigned char)'A');
+ }
+ else if( (c >= (unsigned char)'a') && (c <= (unsigned char)'z') )
+ {
+ return ((PRInt32)(c - (unsigned char)'a') +26);
+ }
+ else if( (c >= (unsigned char)'0') && (c <= (unsigned char)'9') )
+ {
+ return ((PRInt32)(c - (unsigned char)'0') +52);
+ }
+ else if( (unsigned char)'+' == c )
+ {
+ return (PRInt32)62;
+ }
+ else if( (unsigned char)'/' == c )
+ {
+ return (PRInt32)63;
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+static PRStatus
+decode4to3
+(
+ const unsigned char *src,
+ unsigned char *dest
+)
+{
+ PRUint32 b32 = (PRUint32)0;
+ PRInt32 bits;
+ PRIntn i;
+
+ for( i = 0; i < 4; i++ )
+ {
+ bits = codetovalue(src[i]);
+ if( bits < 0 )
+ {
+ return PR_FAILURE;
+ }
+
+ b32 <<= 6;
+ b32 |= bits;
+ }
+
+ dest[0] = (unsigned char)((b32 >> 16) & 0xFF);
+ dest[1] = (unsigned char)((b32 >> 8) & 0xFF);
+ dest[2] = (unsigned char)((b32 ) & 0xFF);
+
+ return PR_SUCCESS;
+}
+
+static PRStatus
+decode3to2
+(
+ const unsigned char *src,
+ unsigned char *dest
+)
+{
+ PRUint32 b32 = (PRUint32)0;
+ PRInt32 bits;
+ PRUint32 ubits;
+
+ bits = codetovalue(src[0]);
+ if( bits < 0 )
+ {
+ return PR_FAILURE;
+ }
+
+ b32 = (PRUint32)bits;
+ b32 <<= 6;
+
+ bits = codetovalue(src[1]);
+ if( bits < 0 )
+ {
+ return PR_FAILURE;
+ }
+
+ b32 |= (PRUint32)bits;
+ b32 <<= 4;
+
+ bits = codetovalue(src[2]);
+ if( bits < 0 )
+ {
+ return PR_FAILURE;
+ }
+
+ ubits = (PRUint32)bits;
+ b32 |= (ubits >> 2);
+
+ dest[0] = (unsigned char)((b32 >> 8) & 0xFF);
+ dest[1] = (unsigned char)((b32 ) & 0xFF);
+
+ return PR_SUCCESS;
+}
+
+static PRStatus
+decode2to1
+(
+ const unsigned char *src,
+ unsigned char *dest
+)
+{
+ PRUint32 b32;
+ PRUint32 ubits;
+ PRInt32 bits;
+
+ bits = codetovalue(src[0]);
+ if( bits < 0 )
+ {
+ return PR_FAILURE;
+ }
+
+ ubits = (PRUint32)bits;
+ b32 = (ubits << 2);
+
+ bits = codetovalue(src[1]);
+ if( bits < 0 )
+ {
+ return PR_FAILURE;
+ }
+
+ ubits = (PRUint32)bits;
+ b32 |= (ubits >> 4);
+
+ dest[0] = (unsigned char)b32;
+
+ return PR_SUCCESS;
+}
+
+static PRStatus
+decode
+(
+ const unsigned char *src,
+ PRUint32 srclen,
+ unsigned char *dest
+)
+{
+ PRStatus rv;
+
+ while( srclen >= 4 )
+ {
+ rv = decode4to3(src, dest);
+ if( PR_SUCCESS != rv )
+ {
+ return PR_FAILURE;
+ }
+
+ src += 4;
+ dest += 3;
+ srclen -= 4;
+ }
+
+ switch( srclen )
+ {
+ case 3:
+ rv = decode3to2(src, dest);
+ break;
+ case 2:
+ rv = decode2to1(src, dest);
+ break;
+ case 1:
+ rv = PR_FAILURE;
+ break;
+ case 0:
+ rv = PR_SUCCESS;
+ break;
+ default:
+ PR_NOT_REACHED("coding error");
+ }
+
+ return rv;
+}
+
+/*
+ * PL_Base64Decode
+ *
+ * If the destination argument is NULL, a return buffer is
+ * allocated and the data therein will be null-terminated.
+ * If the destination argument is not null, it is assumed
+ * to be of sufficient size, and the data will not be null-
+ * terminated by this routine.
+ *
+ * Returns null if the allocation fails, or if the source string is
+ * not well-formed.
+ */
+
+PR_IMPLEMENT(char *)
+PL_Base64Decode
+(
+ const char *src,
+ PRUint32 srclen,
+ char *dest
+)
+{
+ PRStatus status;
+ PRBool allocated = PR_FALSE;
+
+ if( (char *)0 == src )
+ {
+ return (char *)0;
+ }
+
+ if( 0 == srclen )
+ {
+ size_t len = strlen(src);
+ srclen = len;
+ /* Detect truncation. */
+ if( srclen != len )
+ {
+ return (char *)0;
+ }
+ }
+
+ if( srclen && (0 == (srclen & 3)) )
+ {
+ if( (char)'=' == src[ srclen-1 ] )
+ {
+ if( (char)'=' == src[ srclen-2 ] )
+ {
+ srclen -= 2;
+ }
+ else
+ {
+ srclen -= 1;
+ }
+ }
+ }
+
+ if( (char *)0 == dest )
+ {
+ /* The following computes ((srclen * 3) / 4) without overflow. */
+ PRUint32 destlen = (srclen / 4) * 3 + ((srclen % 4) * 3) / 4;
+ dest = (char *)PR_MALLOC(destlen + 1);
+ if( (char *)0 == dest )
+ {
+ return (char *)0;
+ }
+ dest[ destlen ] = (char)0; /* null terminate */
+ allocated = PR_TRUE;
+ }
+
+ status = decode((const unsigned char *)src, srclen, (unsigned char *)dest);
+ if( PR_SUCCESS != status )
+ {
+ if( PR_TRUE == allocated )
+ {
+ PR_DELETE(dest);
+ }
+
+ return (char *)0;
+ }
+
+ return dest;
+}
diff --git a/nsprpub/lib/libc/src/plc.def b/nsprpub/lib/libc/src/plc.def
new file mode 100644
index 0000000000..ac8aa7bf6d
--- /dev/null
+++ b/nsprpub/lib/libc/src/plc.def
@@ -0,0 +1,72 @@
+;+#
+;+# 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/.
+;+#
+;+# OK, this file is meant to support SUN, LINUX, AIX, OS/2 and WINDOWS
+;+# 1. For all unix platforms, the string ";-" means "remove this line"
+;+# 2. For all unix platforms, the string " DATA " will be removed from any
+;+# line on which it occurs.
+;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
+;+# On AIX, lines containing ";+" will be removed.
+;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed.
+;+# 5. For all unix platforms, after the above processing has taken place,
+;+# all characters after the first ";" on the line will be removed.
+;+# And for AIX, the first ";" will also be removed.
+;+# This file is passed directly to windows. Since ';' is a comment, all UNIX
+;+# directives are hidden behind ";", ";+", and ";-"
+;+NSPR_4.0 {
+;+ global:
+LIBRARY plc4 ;-
+EXPORTS ;-
+PL_Base64Decode;
+PL_Base64Encode;
+PL_CreateOptState;
+PL_DestroyOptState;
+PL_FPrintError;
+PL_GetNextOpt;
+PL_PrintError;
+PL_strcasecmp;
+PL_strcaserstr;
+PL_strcasestr;
+PL_strcat;
+PL_strcatn;
+PL_strchr;
+PL_strcmp;
+PL_strcpy;
+PL_strdup;
+PL_strfree;
+PL_strlen;
+PL_strncasecmp;
+PL_strncaserstr;
+PL_strncasestr;
+PL_strncat;
+PL_strnchr;
+PL_strncmp;
+PL_strncpy;
+PL_strncpyz;
+PL_strndup;
+PL_strnlen;
+PL_strnpbrk;
+PL_strnprbrk;
+PL_strnrchr;
+PL_strnrstr;
+PL_strnstr;
+PL_strpbrk;
+PL_strprbrk;
+PL_strrchr;
+PL_strrstr;
+PL_strstr;
+libVersionPoint;
+;+ local: *;
+;+};
+;+
+;+NSPR_4.2 {
+;+ global:
+PL_strtok_r;
+;+} NSPR_4.0;
+;+
+;+NSPR_4.7 {
+;+ global:
+PL_CreateLongOptState;
+;+} NSPR_4.2;
diff --git a/nsprpub/lib/libc/src/plc.rc b/nsprpub/lib/libc/src/plc.rc
new file mode 100644
index 0000000000..144d273751
--- /dev/null
+++ b/nsprpub/lib/libc/src/plc.rc
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+
+#include "prinit.h"
+#include <winver.h>
+
+#define MY_LIBNAME "plc"
+#define MY_FILEDESCRIPTION "PLC Library"
+
+#define STRINGIZE(x) #x
+#define STRINGIZE2(x) STRINGIZE(x)
+#define PR_VMAJOR_STR STRINGIZE2(PR_VMAJOR)
+
+#ifdef _DEBUG
+#define MY_DEBUG_STR " (debug)"
+#define MY_FILEFLAGS_1 VS_FF_DEBUG
+#else
+#define MY_DEBUG_STR ""
+#define MY_FILEFLAGS_1 0x0L
+#endif
+#if PR_BETA
+#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE
+#else
+#define MY_FILEFLAGS_2 MY_FILEFLAGS_1
+#endif
+
+#ifdef WINNT
+#define MY_FILEOS VOS_NT_WINDOWS32
+#define MY_INTERNAL_NAME "lib" MY_LIBNAME PR_VMAJOR_STR
+#else
+#define MY_FILEOS VOS__WINDOWS32
+#define MY_INTERNAL_NAME MY_LIBNAME PR_VMAJOR_STR
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version-information resource
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0
+ PRODUCTVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGS MY_FILEFLAGS_2
+ FILEOS MY_FILEOS
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L // not used
+
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0" // Lang=US English, CharSet=Unicode
+ BEGIN
+ VALUE "CompanyName", "Mozilla Foundation\0"
+ VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0"
+ VALUE "FileVersion", PR_VERSION "\0"
+ VALUE "InternalName", MY_INTERNAL_NAME "\0"
+ VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0"
+ VALUE "ProductName", "Netscape Portable Runtime\0"
+ VALUE "ProductVersion", PR_VERSION "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/nsprpub/lib/libc/src/plerror.c b/nsprpub/lib/libc/src/plerror.c
new file mode 100644
index 0000000000..2a3510f89f
--- /dev/null
+++ b/nsprpub/lib/libc/src/plerror.c
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+/*
+** File:plerror.c
+** Description: Simple routine to print translate the calling thread's
+** error numbers and print them to "syserr".
+*/
+
+#include "plerror.h"
+
+#include "prprf.h"
+#include "prerror.h"
+
+PR_IMPLEMENT(void) PL_FPrintError(PRFileDesc *fd, const char *msg)
+{
+ PRErrorCode error = PR_GetError();
+ PRInt32 oserror = PR_GetOSError();
+ const char *name = PR_ErrorToName(error);
+
+ if (NULL != msg) {
+ PR_fprintf(fd, "%s: ", msg);
+ }
+ if (NULL == name)
+ PR_fprintf(
+ fd, " (%d)OUT OF RANGE, oserror = %d\n", error, oserror);
+ else
+ PR_fprintf(
+ fd, "%s(%d), oserror = %d\n",
+ name, error, oserror);
+} /* PL_FPrintError */
+
+PR_IMPLEMENT(void) PL_PrintError(const char *msg)
+{
+ static PRFileDesc *fd = NULL;
+ if (NULL == fd) {
+ fd = PR_GetSpecialFD(PR_StandardError);
+ }
+ PL_FPrintError(fd, msg);
+} /* PL_PrintError */
+
+/* plerror.c */
diff --git a/nsprpub/lib/libc/src/plgetopt.c b/nsprpub/lib/libc/src/plgetopt.c
new file mode 100644
index 0000000000..4e37e65f51
--- /dev/null
+++ b/nsprpub/lib/libc/src/plgetopt.c
@@ -0,0 +1,251 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+/*
+** File: plgetopt.c
+** Description: utilities to parse argc/argv
+*/
+
+#include "prmem.h"
+#include "prlog.h"
+#include "prerror.h"
+#include "plstr.h"
+#include "plgetopt.h"
+
+#include <string.h>
+
+static char static_Nul = 0;
+
+struct PLOptionInternal
+{
+ const char *options; /* client options list specification */
+ PRIntn argc; /* original number of arguments */
+ char **argv; /* vector of pointers to arguments */
+ PRIntn xargc; /* which one we're processing now */
+ const char *xargv; /* where within *argv[xargc] */
+ PRIntn minus; /* do we already have the '-'? */
+ const PLLongOpt *longOpts; /* Caller's array */
+ PRBool endOfOpts; /* have reached a "--" argument */
+ PRIntn optionsLen; /* is strlen(options) */
+};
+
+/*
+** Create the state in which to parse the tokens.
+**
+** argc the sum of the number of options and their values
+** argv the options and their values
+** options vector of single character options w/ | w/o ':
+*/
+PR_IMPLEMENT(PLOptState*) PL_CreateOptState(
+ PRIntn argc, char **argv, const char *options)
+{
+ return PL_CreateLongOptState( argc, argv, options, NULL);
+} /* PL_CreateOptState */
+
+PR_IMPLEMENT(PLOptState*) PL_CreateLongOptState(
+ PRIntn argc, char **argv, const char *options,
+ const PLLongOpt *longOpts)
+{
+ PLOptState *opt = NULL;
+ PLOptionInternal *internal;
+
+ if (NULL == options)
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return opt;
+ }
+
+ opt = PR_NEWZAP(PLOptState);
+ if (NULL == opt)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return opt;
+ }
+
+ internal = PR_NEW(PLOptionInternal);
+ if (NULL == internal)
+ {
+ PR_DELETE(opt);
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+
+ opt->option = 0;
+ opt->value = NULL;
+ opt->internal = internal;
+ opt->longOption = 0;
+ opt->longOptIndex = -1;
+
+ internal->argc = argc;
+ internal->argv = argv;
+ internal->xargc = 0;
+ internal->xargv = &static_Nul;
+ internal->minus = 0;
+ internal->options = options;
+ internal->longOpts = longOpts;
+ internal->endOfOpts = PR_FALSE;
+ internal->optionsLen = PL_strlen(options);
+
+ return opt;
+} /* PL_CreateLongOptState */
+
+/*
+** Destroy object created by CreateOptState()
+*/
+PR_IMPLEMENT(void) PL_DestroyOptState(PLOptState *opt)
+{
+ PR_DELETE(opt->internal);
+ PR_DELETE(opt);
+} /* PL_DestroyOptState */
+
+PR_IMPLEMENT(PLOptStatus) PL_GetNextOpt(PLOptState *opt)
+{
+ PLOptionInternal *internal = opt->internal;
+
+ opt->longOption = 0;
+ opt->longOptIndex = -1;
+ /*
+ ** If the current xarg points to nul, advance to the next
+ ** element of the argv vector. If the vector index is equal
+ ** to argc, we're out of arguments, so return an EOL.
+ ** Note whether the first character of the new argument is
+ ** a '-' and skip by it if it is.
+ */
+ while (0 == *internal->xargv)
+ {
+ internal->xargc += 1;
+ if (internal->xargc >= internal->argc)
+ {
+ opt->option = 0;
+ opt->value = NULL;
+ return PL_OPT_EOL;
+ }
+ internal->xargv = internal->argv[internal->xargc];
+ internal->minus = 0;
+ if (!internal->endOfOpts && ('-' == *internal->xargv))
+ {
+ internal->minus++;
+ internal->xargv++; /* and consume */
+ if ('-' == *internal->xargv && internal->longOpts)
+ {
+ internal->minus++;
+ internal->xargv++;
+ if (0 == *internal->xargv)
+ {
+ internal->endOfOpts = PR_TRUE;
+ }
+ }
+ }
+ }
+
+ /*
+ ** If we already have a '-' or '--' in hand, xargv points to the next
+ ** option. See if we can find a match in the list of possible
+ ** options supplied.
+ */
+ if (internal->minus == 2)
+ {
+ char * foundEqual = strchr(internal->xargv,'=');
+ PRIntn optNameLen = foundEqual ? (foundEqual - internal->xargv) :
+ strlen(internal->xargv);
+ const PLLongOpt *longOpt = internal->longOpts;
+ PLOptStatus result = PL_OPT_BAD;
+
+ opt->option = 0;
+ opt->value = NULL;
+
+ for (; longOpt->longOptName; ++longOpt)
+ {
+ if (strncmp(longOpt->longOptName, internal->xargv, optNameLen)) {
+ continue; /* not a possible match */
+ }
+ if (strlen(longOpt->longOptName) != optNameLen) {
+ continue; /* not a match */
+ }
+ /* option name match */
+ opt->longOptIndex = longOpt - internal->longOpts;
+ opt->longOption = longOpt->longOption;
+ /* value is part of the current argv[] element if = was found */
+ /* note: this sets value even for long options that do not
+ * require option if specified as --long=value */
+ if (foundEqual)
+ {
+ opt->value = foundEqual + 1;
+ }
+ else if (longOpt->valueRequired)
+ {
+ /* value is the next argv[] element, if any */
+ if (internal->xargc + 1 < internal->argc)
+ {
+ opt->value = internal->argv[++(internal->xargc)];
+ }
+ /* missing value */
+ else
+ {
+ break; /* return PL_OPT_BAD */
+ }
+ }
+ result = PL_OPT_OK;
+ break;
+ }
+ internal->xargv = &static_Nul; /* consume this */
+ return result;
+ }
+ if (internal->minus)
+ {
+ PRIntn cop;
+ PRIntn eoo = internal->optionsLen;
+ for (cop = 0; cop < eoo; ++cop)
+ {
+ if (internal->options[cop] == *internal->xargv)
+ {
+ opt->option = *internal->xargv++;
+ opt->longOption = opt->option & 0xff;
+ /*
+ ** if options indicates that there's an associated
+ ** value, it must be provided, either as part of this
+ ** argv[] element or as the next one
+ */
+ if (':' == internal->options[cop + 1])
+ {
+ /* value is part of the current argv[] element */
+ if (0 != *internal->xargv)
+ {
+ opt->value = internal->xargv;
+ }
+ /* value is the next argv[] element, if any */
+ else if (internal->xargc + 1 < internal->argc)
+ {
+ opt->value = internal->argv[++(internal->xargc)];
+ }
+ /* missing value */
+ else
+ {
+ return PL_OPT_BAD;
+ }
+
+ internal->xargv = &static_Nul;
+ internal->minus = 0;
+ }
+ else {
+ opt->value = NULL;
+ }
+ return PL_OPT_OK;
+ }
+ }
+ internal->xargv += 1; /* consume that option */
+ return PL_OPT_BAD;
+ }
+
+ /*
+ ** No '-', so it must be a standalone value. The option is nul.
+ */
+ opt->value = internal->argv[internal->xargc];
+ internal->xargv = &static_Nul;
+ opt->option = 0;
+ return PL_OPT_OK;
+} /* PL_GetNextOpt */
+
+/* plgetopt.c */
diff --git a/nsprpub/lib/libc/src/plvrsion.c b/nsprpub/lib/libc/src/plvrsion.c
new file mode 100644
index 0000000000..ffa2e95d2d
--- /dev/null
+++ b/nsprpub/lib/libc/src/plvrsion.c
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "prinit.h"
+#include "prvrsion.h"
+
+/************************************************************************/
+/**************************IDENTITY AND VERSIONING***********************/
+/************************************************************************/
+#include "_pl_bld.h"
+#if !defined(_BUILD_TIME)
+#ifdef HAVE_LONG_LONG
+#define _BUILD_TIME 0
+#else
+#define _BUILD_TIME {0, 0}
+#endif
+#endif
+#if !defined(_BUILD_STRING)
+#define _BUILD_STRING ""
+#endif
+#if !defined(_PRODUCTION)
+#define _PRODUCTION ""
+#endif
+#if defined(DEBUG)
+#define _DEBUG_STRING " (debug)"
+#else
+#define _DEBUG_STRING ""
+#endif
+
+/*
+ * A trick to expand the PR_VMAJOR macro before concatenation.
+ */
+#define CONCAT(x, y) x ## y
+#define CONCAT2(x, y) CONCAT(x, y)
+#define VERSION_DESC_NAME CONCAT2(prVersionDescription_libplc, PR_VMAJOR)
+
+PRVersionDescription VERSION_DESC_NAME =
+{
+ /* version */ 2, /* this is the only one supported */
+ /* buildTime */ _BUILD_TIME, /* usecs since midnight 1/1/1970 GMT */
+ /* buildTimeString */ _BUILD_STRING, /* ditto, but human readable */
+ /* vMajor */ PR_VMAJOR, /* NSPR's version number */
+ /* vMinor */ PR_VMINOR, /* and minor version */
+ /* vPatch */ PR_VPATCH, /* and patch */
+ /* beta */ PR_BETA, /* beta build boolean */
+#if defined(DEBUG)
+ /* debug */ PR_TRUE, /* a debug build */
+#else
+ /* debug */ PR_FALSE, /* an optomized build */
+#endif
+ /* special */ PR_FALSE, /* they're all special, but ... */
+ /* filename */ _PRODUCTION, /* the produced library name */
+ /* description */ "Portable runtime", /* what we are */
+ /* security */ "N/A", /* not applicable here */
+ /* copywrite */ "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/.",
+ /* comment */ "http://www.mozilla.org/MPL/",
+ /* specialString */ ""
+};
+
+#ifdef XP_UNIX
+
+/*
+ * Version information for the 'ident' and 'what commands
+ *
+ * NOTE: the first component of the concatenated rcsid string
+ * must not end in a '$' to prevent rcs keyword substitution.
+ */
+static char rcsid[] = "$Header: NSPR " PR_VERSION _DEBUG_STRING
+ " " _BUILD_STRING " $";
+static char sccsid[] = "@(#)NSPR " PR_VERSION _DEBUG_STRING
+ " " _BUILD_STRING;
+
+#endif /* XP_UNIX */
+
+#ifdef _PR_HAS_PRAGMA_DIAGNOSTIC
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#endif
+PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint()
+{
+#ifdef XP_UNIX
+ /*
+ * Add dummy references to rcsid and sccsid to prevent them
+ * from being optimized away as unused variables.
+ */
+ const char *dummy;
+
+ dummy = rcsid;
+ dummy = sccsid;
+#endif
+ return &VERSION_DESC_NAME;
+} /* versionEntryPointType */
+#ifdef _PR_HAS_PRAGMA_DIAGNOSTIC
+#pragma GCC diagnostic pop
+#endif
+
+/* plvrsion.c */
+
diff --git a/nsprpub/lib/libc/src/strcase.c b/nsprpub/lib/libc/src/strcase.c
new file mode 100644
index 0000000000..f1ab038cd9
--- /dev/null
+++ b/nsprpub/lib/libc/src/strcase.c
@@ -0,0 +1,206 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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/. */
+
+#include "plstr.h"
+#include <string.h>
+
+static const unsigned char uc[] =
+{
+ '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+ '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+ '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+ '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+ ' ', '!', '"', '#', '$', '%', '&', '\'',
+ '(', ')', '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', ':', ';', '<', '=', '>', '?',
+ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
+ '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '{', '|', '}', '~', '\177',
+ 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
+ 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
+ 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
+ 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
+ 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
+ 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
+ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
+ 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
+ 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
+ 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
+ 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
+ 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
+ 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
+ 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
+ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
+ 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377
+};
+
+PR_IMPLEMENT(PRIntn)
+PL_strcasecmp(const char *a, const char *b)
+{
+ const unsigned char *ua = (const unsigned char *)a;
+ const unsigned char *ub = (const unsigned char *)b;
+
+ if( (const char *)0 == a ) {
+ return ((const char *)0 == b) ? 0 : -1;
+ }
+ if( (const char *)0 == b ) {
+ return 1;
+ }
+
+ while( (uc[*ua] == uc[*ub]) && ('\0' != *a) )
+ {
+ a++;
+ ua++;
+ ub++;
+ }
+
+ return (PRIntn)(uc[*ua] - uc[*ub]);
+}
+
+PR_IMPLEMENT(PRIntn)
+PL_strncasecmp(const char *a, const char *b, PRUint32 max)
+{
+ const unsigned char *ua = (const unsigned char *)a;
+ const unsigned char *ub = (const unsigned char *)b;
+
+ if( (const char *)0 == a ) {
+ return ((const char *)0 == b) ? 0 : -1;
+ }
+ if( (const char *)0 == b ) {
+ return 1;
+ }
+
+ while( max && (uc[*ua] == uc[*ub]) && ('\0' != *a) )
+ {
+ a++;
+ ua++;
+ ub++;
+ max--;
+ }
+
+ if( 0 == max ) {
+ return (PRIntn)0;
+ }
+
+ return (PRIntn)(uc[*ua] - uc[*ub]);
+}
+
+PR_IMPLEMENT(char *)
+PL_strcasestr(const char *big, const char *little)
+{
+ PRUint32 ll;
+
+ if( ((const char *)0 == big) || ((const char *)0 == little) ) {
+ return (char *)0;
+ }
+ if( ((char)0 == *big) || ((char)0 == *little) ) {
+ return (char *)0;
+ }
+
+ ll = strlen(little);
+
+ for( ; *big; big++ )
+ /* obvious improvement available here */
+ if( 0 == PL_strncasecmp(big, little, ll) ) {
+ return (char *)big;
+ }
+
+ return (char *)0;
+}
+
+PR_IMPLEMENT(char *)
+PL_strcaserstr(const char *big, const char *little)
+{
+ const char *p;
+ PRUint32 bl, ll;
+
+ if( ((const char *)0 == big) || ((const char *)0 == little) ) {
+ return (char *)0;
+ }
+ if( ((char)0 == *big) || ((char)0 == *little) ) {
+ return (char *)0;
+ }
+
+ bl = strlen(big);
+ ll = strlen(little);
+ if( bl < ll ) {
+ return (char *)0;
+ }
+ p = &big[ bl - ll ];
+
+ for( ; p >= big; p-- )
+ /* obvious improvement available here */
+ if( 0 == PL_strncasecmp(p, little, ll) ) {
+ return (char *)p;
+ }
+
+ return (char *)0;
+}
+
+PR_IMPLEMENT(char *)
+PL_strncasestr(const char *big, const char *little, PRUint32 max)
+{
+ PRUint32 ll;
+
+ if( ((const char *)0 == big) || ((const char *)0 == little) ) {
+ return (char *)0;
+ }
+ if( ((char)0 == *big) || ((char)0 == *little) ) {
+ return (char *)0;
+ }
+
+ ll = strlen(little);
+ if( ll > max ) {
+ return (char *)0;
+ }
+ max -= ll;
+ max++;
+
+ for( ; max && *big; big++, max-- )
+ /* obvious improvement available here */
+ if( 0 == PL_strncasecmp(big, little, ll) ) {
+ return (char *)big;
+ }
+
+ return (char *)0;
+}
+
+PR_IMPLEMENT(char *)
+PL_strncaserstr(const char *big, const char *little, PRUint32 max)
+{
+ const char *p;
+ PRUint32 ll;
+
+ if( ((const char *)0 == big) || ((const char *)0 == little) ) {
+ return (char *)0;
+ }
+ if( ((char)0 == *big) || ((char)0 == *little) ) {
+ return (char *)0;
+ }
+
+ ll = strlen(little);
+
+ for( p = big; max && *p; p++, max-- )
+ ;
+
+ p -= ll;
+ if( p < big ) {
+ return (char *)0;
+ }
+
+ for( ; p >= big; p-- )
+ /* obvious improvement available here */
+ if( 0 == PL_strncasecmp(p, little, ll) ) {
+ return (char *)p;
+ }
+
+ return (char *)0;
+}
diff --git a/nsprpub/lib/libc/src/strcat.c b/nsprpub/lib/libc/src/strcat.c
new file mode 100644
index 0000000000..df847d36aa
--- /dev/null
+++ b/nsprpub/lib/libc/src/strcat.c
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "plstr.h"
+#include <string.h>
+
+PR_IMPLEMENT(char *)
+PL_strcat(char *dest, const char *src)
+{
+ if( ((char *)0 == dest) || ((const char *)0 == src) ) {
+ return dest;
+ }
+
+ return strcat(dest, src);
+}
+
+PR_IMPLEMENT(char *)
+PL_strncat(char *dest, const char *src, PRUint32 max)
+{
+ char *rv;
+
+ if( ((char *)0 == dest) || ((const char *)0 == src) || (0 == max) ) {
+ return dest;
+ }
+
+ for( rv = dest; *dest; dest++ )
+ ;
+
+ (void)PL_strncpy(dest, src, max);
+ return rv;
+}
+
+PR_IMPLEMENT(char *)
+PL_strcatn(char *dest, PRUint32 max, const char *src)
+{
+ char *rv;
+ PRUint32 dl;
+
+ if( ((char *)0 == dest) || ((const char *)0 == src) ) {
+ return dest;
+ }
+
+ for( rv = dest, dl = 0; *dest; dest++, dl++ )
+ ;
+
+ if( max <= dl ) {
+ return rv;
+ }
+ (void)PL_strncpyz(dest, src, max-dl);
+
+ return rv;
+}
diff --git a/nsprpub/lib/libc/src/strchr.c b/nsprpub/lib/libc/src/strchr.c
new file mode 100644
index 0000000000..7de1887dc3
--- /dev/null
+++ b/nsprpub/lib/libc/src/strchr.c
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "plstr.h"
+#include <string.h>
+
+PR_IMPLEMENT(char *)
+PL_strchr(const char *s, char c)
+{
+ if( (const char *)0 == s ) {
+ return (char *)0;
+ }
+
+ return strchr(s, c);
+}
+
+PR_IMPLEMENT(char *)
+PL_strrchr(const char *s, char c)
+{
+ if( (const char *)0 == s ) {
+ return (char *)0;
+ }
+
+ return strrchr(s, c);
+}
+
+PR_IMPLEMENT(char *)
+PL_strnchr(const char *s, char c, PRUint32 n)
+{
+ if( (const char *)0 == s ) {
+ return (char *)0;
+ }
+
+ for( ; n && *s; s++, n-- )
+ if( *s == c ) {
+ return (char *)s;
+ }
+
+ if( ((char)0 == c) && (n > 0) && ((char)0 == *s) ) {
+ return (char *)s;
+ }
+
+ return (char *)0;
+}
+
+PR_IMPLEMENT(char *)
+PL_strnrchr(const char *s, char c, PRUint32 n)
+{
+ const char *p;
+
+ if( (const char *)0 == s ) {
+ return (char *)0;
+ }
+
+ for( p = s; n && *p; p++, n-- )
+ ;
+
+ if( ((char)0 == c) && (n > 0) && ((char)0 == *p) ) {
+ return (char *)p;
+ }
+
+ for( p--; p >= s; p-- )
+ if( *p == c ) {
+ return (char *)p;
+ }
+
+ return (char *)0;
+}
diff --git a/nsprpub/lib/libc/src/strcmp.c b/nsprpub/lib/libc/src/strcmp.c
new file mode 100644
index 0000000000..9b00bbc521
--- /dev/null
+++ b/nsprpub/lib/libc/src/strcmp.c
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "plstr.h"
+#include <string.h>
+
+PR_IMPLEMENT(PRIntn)
+PL_strcmp(const char *a, const char *b)
+{
+ if( (const char *)0 == a ) {
+ return ((const char *)0 == b) ? 0 : -1;
+ }
+ if( (const char *)0 == b ) {
+ return 1;
+ }
+
+ return (PRIntn)strcmp(a, b);
+}
+
+PR_IMPLEMENT(PRIntn)
+PL_strncmp(const char *a, const char *b, PRUint32 max)
+{
+ if( (const char *)0 == a ) {
+ return ((const char *)0 == b) ? 0 : -1;
+ }
+ if( (const char *)0 == b ) {
+ return 1;
+ }
+
+ return (PRIntn)strncmp(a, b, (size_t)max);
+}
diff --git a/nsprpub/lib/libc/src/strcpy.c b/nsprpub/lib/libc/src/strcpy.c
new file mode 100644
index 0000000000..f49b3e75e6
--- /dev/null
+++ b/nsprpub/lib/libc/src/strcpy.c
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "plstr.h"
+#include <string.h>
+
+PR_IMPLEMENT(char *)
+PL_strcpy(char *dest, const char *src)
+{
+ if( ((char *)0 == dest) || ((const char *)0 == src) ) {
+ return (char *)0;
+ }
+
+ return strcpy(dest, src);
+}
+
+PR_IMPLEMENT(char *)
+PL_strncpy(char *dest, const char *src, PRUint32 max)
+{
+ char *rv;
+
+ if( (char *)0 == dest ) {
+ return (char *)0;
+ }
+ if( (const char *)0 == src ) {
+ return (char *)0;
+ }
+
+ for( rv = dest; max && ((*dest = *src) != 0); dest++, src++, max-- )
+ ;
+
+#ifdef JLRU
+ /* XXX I (wtc) think the -- and ++ operators should be postfix. */
+ while( --max ) {
+ *++dest = '\0';
+ }
+#endif /* JLRU */
+
+ return rv;
+}
+
+PR_IMPLEMENT(char *)
+PL_strncpyz(char *dest, const char *src, PRUint32 max)
+{
+ char *rv;
+
+ if( (char *)0 == dest ) {
+ return (char *)0;
+ }
+ if( (const char *)0 == src ) {
+ return (char *)0;
+ }
+ if( 0 == max ) {
+ return (char *)0;
+ }
+
+ for( rv = dest, max--; max && ((*dest = *src) != 0); dest++, src++, max-- )
+ ;
+
+ *dest = '\0';
+
+ return rv;
+}
diff --git a/nsprpub/lib/libc/src/strdup.c b/nsprpub/lib/libc/src/strdup.c
new file mode 100644
index 0000000000..d2deae43c4
--- /dev/null
+++ b/nsprpub/lib/libc/src/strdup.c
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "plstr.h"
+#include "prmem.h"
+#include <string.h>
+
+PR_IMPLEMENT(char *)
+PL_strdup(const char *s)
+{
+ char *rv;
+ size_t n;
+
+ if( (const char *)0 == s ) {
+ s = "";
+ }
+
+ n = strlen(s) + 1;
+
+ rv = (char *)malloc(n);
+ if( (char *)0 == rv ) {
+ return rv;
+ }
+
+ (void)memcpy(rv, s, n);
+
+ return rv;
+}
+
+PR_IMPLEMENT(void)
+PL_strfree(char *s)
+{
+ free(s);
+}
+
+PR_IMPLEMENT(char *)
+PL_strndup(const char *s, PRUint32 max)
+{
+ char *rv;
+ size_t l;
+
+ if( (const char *)0 == s ) {
+ s = "";
+ }
+
+ l = PL_strnlen(s, max);
+
+ rv = (char *)malloc(l+1);
+ if( (char *)0 == rv ) {
+ return rv;
+ }
+
+ (void)memcpy(rv, s, l);
+ rv[l] = '\0';
+
+ return rv;
+}
diff --git a/nsprpub/lib/libc/src/strlen.c b/nsprpub/lib/libc/src/strlen.c
new file mode 100644
index 0000000000..2888175dfc
--- /dev/null
+++ b/nsprpub/lib/libc/src/strlen.c
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "plstr.h"
+#include "prtypes.h"
+#include "prlog.h"
+#include <string.h>
+
+PR_IMPLEMENT(PRUint32)
+PL_strlen(const char *str)
+{
+ size_t l;
+
+ if( (const char *)0 == str ) {
+ return 0;
+ }
+
+ l = strlen(str);
+
+ /* error checking in case we have a 64-bit platform -- make sure
+ * we don't have ultra long strings that overflow an int32
+ */
+ if( sizeof(PRUint32) < sizeof(size_t) )
+ {
+ if( l > PR_INT32_MAX ) {
+ PR_Assert("l <= PR_INT32_MAX", __FILE__, __LINE__);
+ }
+ }
+
+ return (PRUint32)l;
+}
+
+PR_IMPLEMENT(PRUint32)
+PL_strnlen(const char *str, PRUint32 max)
+{
+ register const char *s;
+
+ if( (const char *)0 == str ) {
+ return 0;
+ }
+ for( s = str; max && *s; s++, max-- )
+ ;
+
+ return (PRUint32)(s - str);
+}
diff --git a/nsprpub/lib/libc/src/strpbrk.c b/nsprpub/lib/libc/src/strpbrk.c
new file mode 100644
index 0000000000..89ccbe698e
--- /dev/null
+++ b/nsprpub/lib/libc/src/strpbrk.c
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "plstr.h"
+#include <string.h>
+
+PR_IMPLEMENT(char *)
+PL_strpbrk(const char *s, const char *list)
+{
+ if( ((const char *)0 == s) || ((const char *)0 == list) ) {
+ return (char *)0;
+ }
+
+ return strpbrk(s, list);
+}
+
+PR_IMPLEMENT(char *)
+PL_strprbrk(const char *s, const char *list)
+{
+ const char *p;
+ const char *r;
+
+ if( ((const char *)0 == s) || ((const char *)0 == list) ) {
+ return (char *)0;
+ }
+
+ for( r = s; *r; r++ )
+ ;
+
+ for( r--; r >= s; r-- )
+ for( p = list; *p; p++ )
+ if( *r == *p ) {
+ return (char *)r;
+ }
+
+ return (char *)0;
+}
+
+PR_IMPLEMENT(char *)
+PL_strnpbrk(const char *s, const char *list, PRUint32 max)
+{
+ const char *p;
+
+ if( ((const char *)0 == s) || ((const char *)0 == list) ) {
+ return (char *)0;
+ }
+
+ for( ; max && *s; s++, max-- )
+ for( p = list; *p; p++ )
+ if( *s == *p ) {
+ return (char *)s;
+ }
+
+ return (char *)0;
+}
+
+PR_IMPLEMENT(char *)
+PL_strnprbrk(const char *s, const char *list, PRUint32 max)
+{
+ const char *p;
+ const char *r;
+
+ if( ((const char *)0 == s) || ((const char *)0 == list) ) {
+ return (char *)0;
+ }
+
+ for( r = s; max && *r; r++, max-- )
+ ;
+
+ for( r--; r >= s; r-- )
+ for( p = list; *p; p++ )
+ if( *r == *p ) {
+ return (char *)r;
+ }
+
+ return (char *)0;
+}
diff --git a/nsprpub/lib/libc/src/strstr.c b/nsprpub/lib/libc/src/strstr.c
new file mode 100644
index 0000000000..dd27a23ee7
--- /dev/null
+++ b/nsprpub/lib/libc/src/strstr.c
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "plstr.h"
+#include <string.h>
+
+PR_IMPLEMENT(char *)
+PL_strstr(const char *big, const char *little)
+{
+ if( ((const char *)0 == big) || ((const char *)0 == little) ) {
+ return (char *)0;
+ }
+ if( ((char)0 == *big) || ((char)0 == *little) ) {
+ return (char *)0;
+ }
+
+ return strstr(big, little);
+}
+
+PR_IMPLEMENT(char *)
+PL_strrstr(const char *big, const char *little)
+{
+ const char *p;
+ size_t ll;
+ size_t bl;
+
+ if( ((const char *)0 == big) || ((const char *)0 == little) ) {
+ return (char *)0;
+ }
+ if( ((char)0 == *big) || ((char)0 == *little) ) {
+ return (char *)0;
+ }
+
+ ll = strlen(little);
+ bl = strlen(big);
+ if( bl < ll ) {
+ return (char *)0;
+ }
+ p = &big[ bl - ll ];
+
+ for( ; p >= big; p-- )
+ if( *little == *p )
+ if( 0 == strncmp(p, little, ll) ) {
+ return (char *)p;
+ }
+
+ return (char *)0;
+}
+
+PR_IMPLEMENT(char *)
+PL_strnstr(const char *big, const char *little, PRUint32 max)
+{
+ size_t ll;
+
+ if( ((const char *)0 == big) || ((const char *)0 == little) ) {
+ return (char *)0;
+ }
+ if( ((char)0 == *big) || ((char)0 == *little) ) {
+ return (char *)0;
+ }
+
+ ll = strlen(little);
+ if( ll > (size_t)max ) {
+ return (char *)0;
+ }
+ max -= (PRUint32)ll;
+ max++;
+
+ for( ; max && *big; big++, max-- )
+ if( *little == *big )
+ if( 0 == strncmp(big, little, ll) ) {
+ return (char *)big;
+ }
+
+ return (char *)0;
+}
+
+PR_IMPLEMENT(char *)
+PL_strnrstr(const char *big, const char *little, PRUint32 max)
+{
+ const char *p;
+ size_t ll;
+
+ if( ((const char *)0 == big) || ((const char *)0 == little) ) {
+ return (char *)0;
+ }
+ if( ((char)0 == *big) || ((char)0 == *little) ) {
+ return (char *)0;
+ }
+
+ ll = strlen(little);
+
+ for( p = big; max && *p; p++, max-- )
+ ;
+
+ p -= ll;
+ if( p < big ) {
+ return (char *)0;
+ }
+
+ for( ; p >= big; p-- )
+ if( *little == *p )
+ if( 0 == strncmp(p, little, ll) ) {
+ return (char *)p;
+ }
+
+ return (char *)0;
+}
diff --git a/nsprpub/lib/libc/src/strtok.c b/nsprpub/lib/libc/src/strtok.c
new file mode 100644
index 0000000000..df404494fb
--- /dev/null
+++ b/nsprpub/lib/libc/src/strtok.c
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "plstr.h"
+
+PR_IMPLEMENT(char *)
+PL_strtok_r(char *s1, const char *s2, char **lasts)
+{
+ const char *sepp;
+ int c, sc;
+ char *tok;
+
+ if( s1 == NULL )
+ {
+ if( *lasts == NULL ) {
+ return NULL;
+ }
+
+ s1 = *lasts;
+ }
+
+ for( ; (c = *s1) != 0; s1++ )
+ {
+ for( sepp = s2 ; (sc = *sepp) != 0 ; sepp++ )
+ {
+ if( c == sc ) {
+ break;
+ }
+ }
+ if( sc == 0 ) {
+ break;
+ }
+ }
+
+ if( c == 0 )
+ {
+ *lasts = NULL;
+ return NULL;
+ }
+
+ tok = s1++;
+
+ for( ; (c = *s1) != 0; s1++ )
+ {
+ for( sepp = s2; (sc = *sepp) != 0; sepp++ )
+ {
+ if( c == sc )
+ {
+ *s1++ = '\0';
+ *lasts = s1;
+ return tok;
+ }
+ }
+ }
+ *lasts = NULL;
+ return tok;
+}
diff --git a/nsprpub/lib/prstreams/Makefile.in b/nsprpub/lib/prstreams/Makefile.in
new file mode 100644
index 0000000000..a380cab400
--- /dev/null
+++ b/nsprpub/lib/prstreams/Makefile.in
@@ -0,0 +1,142 @@
+#
+# 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/.
+
+#! gmake
+
+MOD_DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+ifeq ($(OS_ARCH), BeOS)
+ CFLAGS += -frtti -fexceptions
+endif
+
+INCLUDES = -I$(dist_includedir)
+
+HEADERS = $(wildcard $(srcdir)/*.h)
+
+CSRCS = \
+ plvrsion.c \
+ $(NULL)
+
+CXXSRCS = \
+ prstrms.cpp \
+ $(NULL)
+
+OBJS = $(addprefix $(OBJDIR)/,$(CSRCS:.c=.$(OBJ_SUFFIX)) $(CXXSRCS:.cpp=.$(OBJ_SUFFIX)))
+
+ifeq ($(OS_ARCH), WINNT)
+ RES=$(OBJDIR)/prstrms.res
+ RESNAME=prstrms.rc
+ OS_LIBS = user32.lib
+else
+ ifeq ($(OS_ARCH),OS2)
+ OS_LIBS = -lstdcpp
+ else
+ ifeq ($(OS_ARCH), AIX)
+ ifeq ($(OS_RELEASE), 4.1)
+ ifeq ($(CLASSIC_NSPR),1)
+ OS_LIBS += -lC -lc
+ else
+ OS_LIBS += -lC_r -lc_r
+ endif
+ else
+ # makeC++SharedLib(_r) is in either /usr/lpp/xlC/bin
+ # or /usr/ibmcxx/bin.
+ ifeq ($(CLASSIC_NSPR),1)
+ MKSHLIB = makeC++SharedLib -p 0
+ else
+ MKSHLIB = makeC++SharedLib_r -p 0
+ endif
+ OS_LIBS += -ldl
+ endif
+ endif
+ endif
+endif
+
+ifeq ($(OS_ARCH),BeOS)
+ OS_LIBS = -lstdc++.r4
+endif
+
+ifeq ($(OS_ARCH), UNIXWARE)
+ OS_LIBS += -lC
+endif
+
+EXTRA_LIBS = $(LIBNSPR)
+
+# On SCOOS, we can't link with extra libraries when
+# we build a shared library. If we do so, the linker doesn't
+# complain, but we would run into weird problems at run-time.
+# Therefore on these platforms, we link just the object files.
+ifeq ($(OS_ARCH),SCOOS)
+ EXTRA_LIBS =
+endif
+
+ifdef RESOLVE_LINK_SYMBOLS
+EXTRA_LIBS += $(OS_LIBS)
+endif
+
+LIBRARY_NAME = prstrms
+LIBRARY_VERSION = $(MOD_MAJOR_VERSION)
+
+RELEASE_HEADERS = $(HEADERS)
+RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR)
+RELEASE_LIBS = $(TARGETS)
+
+include $(topsrcdir)/config/rules.mk
+
+#
+# Version information generation (begin)
+#
+ECHO = echo
+TINC = $(OBJDIR)/_pl_bld.h
+PROD = $(notdir $(SHARED_LIBRARY))
+NOW = $(MOD_DEPTH)/config/$(OBJDIR)/now
+SH_DATE = $(shell date "+%Y-%m-%d %T")
+SH_NOW = $(shell $(NOW))
+
+ifeq ($(OS_ARCH), WINNT)
+ SUF = i64
+else
+ SUF = LL
+endif
+
+$(TINC):
+ @$(MAKE_OBJDIR)
+ @$(ECHO) '#define _BUILD_STRING "$(SH_DATE)"' > $(TINC)
+ @if test ! -z "$(SH_NOW)"; then \
+ $(ECHO) '#define _BUILD_TIME $(SH_NOW)$(SUF)' >> $(TINC); \
+ else \
+ true; \
+ fi
+ @$(ECHO) '#define _PRODUCTION "$(PROD)"' >> $(TINC)
+
+
+$(OBJDIR)/plvrsion.$(OBJ_SUFFIX): plvrsion.c $(TINC)
+ifeq ($(OS_ARCH), WINNT)
+ $(CC) -o $@ -c $(CFLAGS) -I$(OBJDIR) $<
+else
+ $(CC) -o $@ -c $(CFLAGS) -I$(OBJDIR) $<
+endif
+#
+# Version information generation (end)
+#
+
+export:: $(TARGETS) $(HEADERS)
+ $(INSTALL) -m 444 $(HEADERS) $(dist_includedir)
+ $(INSTALL) -m 444 $(TARGETS) $(dist_libdir)
+ifeq ($(OS_ARCH),OS2)
+ $(INSTALL) -m 444 $(TARGETS) $(dist_bindir)
+endif
+ifeq ($(OS_ARCH),HP-UX)
+ifdef SHARED_LIBRARY
+ $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_libdir)
+endif
+endif
diff --git a/nsprpub/lib/prstreams/plvrsion.c b/nsprpub/lib/prstreams/plvrsion.c
new file mode 100644
index 0000000000..a8332ff6f7
--- /dev/null
+++ b/nsprpub/lib/prstreams/plvrsion.c
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "prinit.h"
+#include "prvrsion.h"
+
+/************************************************************************/
+/**************************IDENTITY AND VERSIONING***********************/
+/************************************************************************/
+#include "_pl_bld.h"
+#if !defined(_BUILD_TIME)
+#ifdef HAVE_LONG_LONG
+#define _BUILD_TIME 0
+#else
+#define _BUILD_TIME {0, 0}
+#endif
+#endif
+#if !defined(_BUILD_STRING)
+#define _BUILD_STRING ""
+#endif
+#if !defined(_PRODUCTION)
+#define _PRODUCTION ""
+#endif
+#if defined(DEBUG)
+#define _DEBUG_STRING " (debug)"
+#else
+#define _DEBUG_STRING ""
+#endif
+
+/*
+ * A trick to expand the PR_VMAJOR macro before concatenation.
+ */
+#define CONCAT(x, y) x ## y
+#define CONCAT2(x, y) CONCAT(x, y)
+#define VERSION_DESC_NAME CONCAT2(prVersionDescription_libprstrms, PR_VMAJOR)
+
+PRVersionDescription VERSION_DESC_NAME =
+{
+ /* version */ 2, /* this is the only one supported */
+ /* buildTime */ _BUILD_TIME, /* usecs since midnight 1/1/1970 GMT */
+ /* buildTimeString */ _BUILD_STRING, /* ditto, but human readable */
+ /* vMajor */ PR_VMAJOR, /* NSPR's version number */
+ /* vMinor */ PR_VMINOR, /* and minor version */
+ /* vPatch */ PR_VPATCH, /* and patch */
+ /* beta */ PR_BETA, /* beta build boolean */
+#if defined(DEBUG)
+ /* debug */ PR_TRUE, /* a debug build */
+#else
+ /* debug */ PR_FALSE, /* an optomized build */
+#endif
+ /* special */ PR_FALSE, /* they're all special, but ... */
+ /* filename */ _PRODUCTION, /* the produced library name */
+ /* description */ "Portable runtime", /* what we are */
+ /* security */ "N/A", /* not applicable here */
+ /* copywrite */ "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/.",
+ /* comment */ "http://www.mozilla.org/MPL/",
+ /* specialString */ ""
+};
+
+#ifdef XP_UNIX
+
+/*
+ * Version information for the 'ident' and 'what commands
+ *
+ * NOTE: the first component of the concatenated rcsid string
+ * must not end in a '$' to prevent rcs keyword substitution.
+ */
+static char rcsid[] = "$Header: NSPR " PR_VERSION _DEBUG_STRING
+ " " _BUILD_STRING " $";
+static char sccsid[] = "@(#)NSPR " PR_VERSION _DEBUG_STRING
+ " " _BUILD_STRING;
+
+#endif /* XP_UNIX */
+
+#ifdef _PR_HAS_PRAGMA_DIAGNOSTIC
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#endif
+PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint()
+{
+#ifdef XP_UNIX
+ /*
+ * Add dummy references to rcsid and sccsid to prevent them
+ * from being optimized away as unused variables.
+ */
+ const char *dummy;
+
+ dummy = rcsid;
+ dummy = sccsid;
+#endif
+ return &VERSION_DESC_NAME;
+} /* versionEntryPointType */
+#ifdef _PR_HAS_PRAGMA_DIAGNOSTIC
+#pragma GCC diagnostic pop
+#endif
+
+/* plvrsion.c */
+
diff --git a/nsprpub/lib/prstreams/prstrms.cpp b/nsprpub/lib/prstreams/prstrms.cpp
new file mode 100644
index 0000000000..878175df5a
--- /dev/null
+++ b/nsprpub/lib/prstreams/prstrms.cpp
@@ -0,0 +1,517 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+/*
+ * Robin J. Maxwell 11-22-96
+ * Fredrik Roubert <roubert@google.com> 2010-07-23
+ * Matt Austern <austern@google.com> 2010-07-23
+ */
+
+#include "prstrms.h"
+
+#include <cstdio>
+#include <cstring>
+#include <ios>
+#include <new>
+
+using std::ios_base;
+using std::iostream;
+using std::istream;
+using std::nothrow;
+using std::ostream;
+using std::streambuf;
+using std::streamsize;
+
+
+PRfilebuf::PRfilebuf():
+ _fd(NULL),
+ _opened(false),
+ _allocated(false),
+ _unbuffered(false),
+ _user_buf(false),
+ _buf_base(NULL),
+ _buf_end(NULL) { }
+
+
+PRfilebuf::PRfilebuf(PRFileDesc *fd):
+ _fd(fd),
+ _opened(false),
+ _allocated(false),
+ _unbuffered(false),
+ _user_buf(false),
+ _buf_base(NULL),
+ _buf_end(NULL) { }
+
+
+PRfilebuf::PRfilebuf(PRFileDesc *fd, char_type *ptr, streamsize len):
+ _fd(fd),
+ _opened(false),
+ _allocated(false),
+ _unbuffered(false),
+ _user_buf(false),
+ _buf_base(NULL),
+ _buf_end(NULL)
+{
+ setbuf(ptr, len);
+}
+
+
+PRfilebuf::~PRfilebuf()
+{
+ if (_opened) {
+ close();
+ } else {
+ sync();
+ }
+ if (_allocated) {
+ delete _buf_base;
+ }
+}
+
+
+PRfilebuf *PRfilebuf::open(
+ const char *name, ios_base::openmode flags, PRIntn mode)
+{
+ if (_fd != NULL) {
+ return NULL; // Error if already open.
+ }
+
+ // Translate flags argument.
+ PRIntn prflags = 0;
+ bool ate = (flags & ios_base::ate) != 0;
+ flags &= ~(ios_base::ate | ios_base::binary);
+
+ // TODO: The flag PR_CREATE_FILE should probably be used for the cases
+ // (out), (out|app), (out|trunc) and (in|out|trunc) as the C++ standard
+ // specifies that these cases should open files 'as if by using fopen with
+ // "w"'. But adding that flag here will cause the unit test to leave files
+ // behind after running (which might or might not be an error in the unit
+ // test) so the matter needs further investigation before any changes are
+ // made. The old prstreams implementation used the non-standard flag
+ // ios::nocreate to control the use of PR_CREATE_FILE.
+
+ if (flags == (ios_base::out)) {
+ prflags = PR_WRONLY | PR_TRUNCATE;
+ } else if (flags == (ios_base::out | ios_base::app)) {
+ prflags = PR_RDWR | PR_APPEND;
+ } else if (flags == (ios_base::out | ios_base::trunc)) {
+ prflags = PR_WRONLY | PR_TRUNCATE;
+ } else if (flags == (ios_base::in)) {
+ prflags = PR_RDONLY;
+ } else if (flags == (ios_base::in | ios_base::out)) {
+ prflags = PR_RDWR;
+ } else if (flags == (ios_base::in | ios_base::out | ios_base::trunc)) {
+ prflags = PR_RDWR | PR_TRUNCATE;
+ } else {
+ return NULL; // Unrecognized flag combination.
+ }
+
+ if ((_fd = PR_Open(name, prflags, mode)) == NULL) {
+ return NULL;
+ }
+
+ _opened = true;
+
+ if (ate &&
+ seekoff(0, ios_base::end, flags) == pos_type(traits_type::eof())) {
+ close();
+ return NULL;
+ }
+
+ return this;
+}
+
+
+PRfilebuf *PRfilebuf::attach(PRFileDesc *fd)
+{
+ if (_fd != NULL) {
+ return NULL; // Error if already open.
+ }
+
+ _opened = false;
+ _fd = fd;
+ return this;
+}
+
+
+PRfilebuf *PRfilebuf::close()
+{
+ if (_fd == NULL) {
+ return NULL;
+ }
+
+ int status = sync();
+
+ if (PR_Close(_fd) == PR_FAILURE ||
+ traits_type::eq_int_type(status, traits_type::eof())) {
+ return NULL;
+ }
+
+ _fd = NULL;
+ return this;
+}
+
+
+streambuf *PRfilebuf::setbuf(char_type *ptr, streamsize len)
+{
+ if (is_open() && _buf_end) {
+ return NULL;
+ }
+
+ if (!ptr || len <= 0) {
+ _unbuffered = true;
+ } else {
+ setb(ptr, ptr + len, false);
+ }
+
+ return this;
+}
+
+
+streambuf::pos_type PRfilebuf::seekoff(
+ off_type offset, ios_base::seekdir dir, ios_base::openmode /*flags*/)
+{
+ if (PR_GetDescType(_fd) != PR_DESC_FILE) {
+ return traits_type::eof();
+ }
+
+ PRSeekWhence whence;
+ PRInt64 pos;
+
+ switch (dir) {
+ case ios_base::beg: whence = PR_SEEK_SET; break;
+ case ios_base::cur: whence = PR_SEEK_CUR; break;
+ case ios_base::end: whence = PR_SEEK_END; break;
+ default:
+ return traits_type::eof(); // This should never happen.
+ }
+
+ if (traits_type::eq_int_type(sync(), traits_type::eof())) {
+ return traits_type::eof();
+ }
+
+ if ((pos = PR_Seek64(_fd, offset, whence)) == -1) {
+ return traits_type::eof();
+ }
+
+ return pos;
+}
+
+
+int PRfilebuf::sync()
+{
+ if (_fd == NULL) {
+ return traits_type::eof();
+ }
+
+ if (!_unbuffered) {
+ // Sync write area.
+ PRInt32 waiting;
+ if ((waiting = pptr() - pbase()) != 0) {
+ PRInt32 nout;
+ if ((nout = PR_Write(_fd, pbase(), waiting)) != waiting) {
+ if (nout > 0) {
+ // Should set _pptr -= nout.
+ pbump(-nout);
+ memmove(pbase(), pbase() + nout, waiting - nout);
+ }
+ return traits_type::eof();
+ }
+ }
+ setp(NULL, NULL); // Empty put area.
+
+ if (PR_GetDescType(_fd) == PR_DESC_FILE) {
+ // Sockets can't seek; don't need this.
+ PROffset64 avail;
+ if ((avail = in_avail()) > 0) {
+ if (PR_Seek64(_fd, -avail, PR_SEEK_CUR) != -1) {
+ return traits_type::eof();
+ }
+ }
+ }
+ setg(NULL, NULL, NULL); // Empty get area.
+ }
+
+ return 0;
+}
+
+
+streambuf::int_type PRfilebuf::underflow()
+{
+ PRInt32 count;
+ char_type byte;
+
+ if (gptr() != NULL && gptr() < egptr()) {
+ return traits_type::to_int_type(*gptr());
+ }
+
+ // Make sure there is a reserve area.
+ if (!_unbuffered && _buf_base == NULL && !allocate()) {
+ return traits_type::eof();
+ }
+
+ // Sync before new buffer created below.
+ if (traits_type::eq_int_type(sync(), traits_type::eof())) {
+ return traits_type::eof();
+ }
+
+ if (_unbuffered) {
+ if (PR_Read(_fd, &byte, 1) <= 0) {
+ return traits_type::eof();
+ }
+
+ return traits_type::to_int_type(byte);
+ }
+
+ if ((count = PR_Read(_fd, _buf_base, _buf_end - _buf_base)) <= 0) {
+ return traits_type::eof(); // Reached EOF.
+ }
+
+ setg(_buf_base, _buf_base, _buf_base + count);
+ return traits_type::to_int_type(*gptr());
+}
+
+
+streambuf::int_type PRfilebuf::overflow(int_type c)
+{
+ // Make sure there is a reserve area.
+ if (!_unbuffered && _buf_base == NULL && !allocate()) {
+ return traits_type::eof();
+ }
+
+ // Sync before new buffer created below.
+ if (traits_type::eq_int_type(sync(), traits_type::eof())) {
+ return traits_type::eof();
+ }
+
+ if (!_unbuffered) {
+ setp(_buf_base, _buf_end);
+ }
+
+ if (!traits_type::eq_int_type(c, traits_type::eof())) {
+ // Extract the byte to be written.
+ // (Required on big-endian architectures.)
+ char_type byte = traits_type::to_char_type(c);
+ if (!_unbuffered && pptr() < epptr()) { // Guard against recursion.
+ return sputc(byte);
+ } else {
+ if (PR_Write(_fd, &byte, 1) != 1) {
+ return traits_type::eof();
+ }
+ }
+ }
+
+ return traits_type::not_eof(c);
+}
+
+
+bool PRfilebuf::allocate()
+{
+ char_type *buf = new(nothrow) char_type[BUFSIZ];
+ if (buf == NULL) {
+ return false;
+ }
+
+ setb(buf, buf + BUFSIZ, true);
+ return true;
+}
+
+
+void PRfilebuf::setb(char_type *buf_base, char_type *buf_end, bool user_buf)
+{
+ if (_buf_base && !_user_buf) {
+ delete[] _buf_base;
+ }
+
+ _buf_base = buf_base;
+ _buf_end = buf_end;
+ _user_buf = user_buf;
+}
+
+
+PRifstream::PRifstream():
+ istream(NULL),
+ _filebuf()
+{
+ init(&_filebuf);
+}
+
+
+PRifstream::PRifstream(PRFileDesc *fd):
+ istream(NULL),
+ _filebuf(fd)
+{
+ init(&_filebuf);
+}
+
+
+PRifstream::PRifstream(PRFileDesc *fd, char_type *ptr, streamsize len):
+ istream(NULL),
+ _filebuf(fd, ptr, len)
+{
+ init(&_filebuf);
+}
+
+
+PRifstream::PRifstream(const char *name, openmode flags, PRIntn mode):
+ istream(NULL),
+ _filebuf()
+{
+ init(&_filebuf);
+ if (!_filebuf.open(name, flags | in, mode)) {
+ setstate(failbit);
+ }
+}
+
+
+PRifstream::~PRifstream() { }
+
+
+void PRifstream::open(const char *name, openmode flags, PRIntn mode)
+{
+ if (is_open() || !_filebuf.open(name, flags | in, mode)) {
+ setstate(failbit);
+ }
+}
+
+
+void PRifstream::attach(PRFileDesc *fd)
+{
+ if (!_filebuf.attach(fd)) {
+ setstate(failbit);
+ }
+}
+
+
+void PRifstream::close()
+{
+ if (_filebuf.close() == NULL) {
+ setstate(failbit);
+ }
+}
+
+
+PRofstream::PRofstream():
+ ostream(NULL),
+ _filebuf()
+{
+ init(&_filebuf);
+}
+
+
+PRofstream::PRofstream(PRFileDesc *fd):
+ ostream(NULL),
+ _filebuf(fd)
+{
+ init(&_filebuf);
+}
+
+
+PRofstream::PRofstream(PRFileDesc *fd, char_type *ptr, streamsize len):
+ ostream(NULL),
+ _filebuf(fd, ptr, len)
+{
+ init(&_filebuf);
+}
+
+
+PRofstream::PRofstream(const char *name, openmode flags, PRIntn mode):
+ ostream(NULL),
+ _filebuf()
+{
+ init(&_filebuf);
+ if (!_filebuf.open(name, flags | out, mode)) {
+ setstate(failbit);
+ }
+}
+
+
+PRofstream::~PRofstream() { }
+
+
+void PRofstream::open(const char *name, openmode flags, PRIntn mode)
+{
+ if (is_open() || !_filebuf.open(name, flags | out, mode)) {
+ setstate(failbit);
+ }
+}
+
+
+void PRofstream::attach(PRFileDesc *fd)
+{
+ if (!_filebuf.attach(fd)) {
+ setstate(failbit);
+ }
+}
+
+
+void PRofstream::close()
+{
+ if (_filebuf.close() == NULL) {
+ setstate(failbit);
+ }
+}
+
+
+PRfstream::PRfstream():
+ iostream(NULL),
+ _filebuf()
+{
+ init(&_filebuf);
+}
+
+
+PRfstream::PRfstream(PRFileDesc *fd):
+ iostream(NULL),
+ _filebuf(fd)
+{
+ init(&_filebuf);
+}
+
+
+PRfstream::PRfstream(PRFileDesc *fd, char_type *ptr, streamsize len):
+ iostream(NULL),
+ _filebuf(fd, ptr, len)
+{
+ init(&_filebuf);
+}
+
+
+PRfstream::PRfstream(const char *name, openmode flags, PRIntn mode):
+ iostream(NULL),
+ _filebuf()
+{
+ init(&_filebuf);
+ if (!_filebuf.open(name, flags | in | out, mode)) {
+ setstate(failbit);
+ }
+}
+
+
+PRfstream::~PRfstream() { }
+
+
+void PRfstream::open(const char *name, openmode flags, PRIntn mode)
+{
+ if (is_open() || !_filebuf.open(name, flags | in | out, mode)) {
+ setstate(failbit);
+ }
+}
+
+
+void PRfstream::attach(PRFileDesc *fd)
+{
+ if (!_filebuf.attach(fd)) {
+ setstate(failbit);
+ }
+}
+
+
+void PRfstream::close()
+{
+ if (_filebuf.close() == NULL) {
+ setstate(failbit);
+ }
+}
diff --git a/nsprpub/lib/prstreams/prstrms.h b/nsprpub/lib/prstreams/prstrms.h
new file mode 100644
index 0000000000..113a41627e
--- /dev/null
+++ b/nsprpub/lib/prstreams/prstrms.h
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+/*
+ * Robin J. Maxwell 11-22-96
+ * Fredrik Roubert <roubert@google.com> 2010-07-23
+ * Matt Austern <austern@google.com> 2010-07-23
+ */
+
+#ifndef _PRSTRMS_H
+#define _PRSTRMS_H
+
+#include <cstddef>
+#include <istream>
+#include <ostream>
+#include <streambuf>
+
+#include "prio.h"
+
+#ifdef _MSC_VER
+// http://support.microsoft.com/kb/q168958/
+class PR_IMPLEMENT(std::_Mutex);
+class PR_IMPLEMENT(std::ios_base);
+#endif
+
+
+class PR_IMPLEMENT(PRfilebuf): public std::streambuf
+{
+public:
+ PRfilebuf();
+ PRfilebuf(PRFileDesc *fd);
+ PRfilebuf(PRFileDesc *fd, char_type *ptr, std::streamsize len);
+ virtual ~PRfilebuf();
+
+ bool is_open() const {
+ return _fd != NULL;
+ }
+
+ PRfilebuf *open(
+ const char *name,
+ std::ios_base::openmode flags,
+ PRIntn mode);
+ PRfilebuf *attach(PRFileDesc *fd);
+ PRfilebuf *close();
+
+protected:
+ virtual std::streambuf *setbuf(char_type *ptr, std::streamsize len);
+ virtual pos_type seekoff(
+ off_type offset,
+ std::ios_base::seekdir dir,
+ std::ios_base::openmode flags);
+ virtual pos_type seekpos(
+ pos_type pos,
+ std::ios_base::openmode flags) {
+ return seekoff(pos, std::ios_base::beg, flags);
+ }
+ virtual int sync();
+ virtual int_type underflow();
+ virtual int_type overflow(int_type c = traits_type::eof());
+
+ // TODO: Override pbackfail(), showmanyc(), uflow(), xsgetn(), and xsputn().
+
+private:
+ bool allocate();
+ void setb(char_type *buf_base, char_type *buf_end, bool user_buf);
+
+ PRFileDesc *_fd;
+ bool _opened;
+ bool _allocated;
+ bool _unbuffered;
+ bool _user_buf;
+ char_type *_buf_base;
+ char_type *_buf_end;
+};
+
+
+class PR_IMPLEMENT(PRifstream): public std::istream
+{
+public:
+ PRifstream();
+ PRifstream(PRFileDesc *fd);
+ PRifstream(PRFileDesc *fd, char_type *ptr, std::streamsize len);
+ PRifstream(const char *name, openmode flags = in, PRIntn mode = 0);
+ virtual ~PRifstream();
+
+ PRfilebuf *rdbuf() const {
+ return &_filebuf;
+ }
+ bool is_open() const {
+ return _filebuf.is_open();
+ }
+
+ void open(const char *name, openmode flags = in, PRIntn mode = 0);
+ void attach(PRFileDesc *fd);
+ void close();
+
+private:
+ mutable PRfilebuf _filebuf;
+};
+
+
+class PR_IMPLEMENT(PRofstream): public std::ostream
+{
+public:
+ PRofstream();
+ PRofstream(PRFileDesc *fd);
+ PRofstream(PRFileDesc *fd, char_type *ptr, std::streamsize len);
+ PRofstream(const char *name, openmode flags = out, PRIntn mode = 0);
+ virtual ~PRofstream();
+
+ PRfilebuf *rdbuf() const {
+ return &_filebuf;
+ }
+ bool is_open() const {
+ return _filebuf.is_open();
+ }
+
+ void open(const char *name, openmode flags = out, PRIntn mode = 0);
+ void attach(PRFileDesc *fd);
+ void close();
+
+private:
+ mutable PRfilebuf _filebuf;
+};
+
+
+class PR_IMPLEMENT(PRfstream): public std::iostream
+{
+public:
+ PRfstream();
+ PRfstream(PRFileDesc *fd);
+ PRfstream(PRFileDesc *fd, char_type *ptr, std::streamsize len);
+ PRfstream(const char *name, openmode flags = in | out, PRIntn mode = 0);
+ virtual ~PRfstream();
+
+ PRfilebuf *rdbuf() const {
+ return &_filebuf;
+ }
+ bool is_open() const {
+ return _filebuf.is_open();
+ }
+
+ void open(const char *name, openmode flags = in | out, PRIntn mode = 0);
+ void attach(PRFileDesc *fd);
+ void close();
+
+private:
+ mutable PRfilebuf _filebuf;
+};
+
+
+#endif /* _PRSTRMS_H */
diff --git a/nsprpub/lib/prstreams/prstrms.rc b/nsprpub/lib/prstreams/prstrms.rc
new file mode 100644
index 0000000000..5f72583783
--- /dev/null
+++ b/nsprpub/lib/prstreams/prstrms.rc
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "prinit.h"
+#include <winver.h>
+
+#define MY_LIBNAME "prstrms"
+#define MY_FILEDESCRIPTION "PRSTRMS Library"
+
+#define STRINGIZE(x) #x
+#define STRINGIZE2(x) STRINGIZE(x)
+#define PR_VMAJOR_STR STRINGIZE2(PR_VMAJOR)
+
+#ifdef _DEBUG
+#define MY_DEBUG_STR " (debug)"
+#define MY_FILEFLAGS_1 VS_FF_DEBUG
+#else
+#define MY_DEBUG_STR ""
+#define MY_FILEFLAGS_1 0x0L
+#endif
+#if PR_BETA
+#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE
+#else
+#define MY_FILEFLAGS_2 MY_FILEFLAGS_1
+#endif
+
+#ifdef WINNT
+#define MY_FILEOS VOS_NT_WINDOWS32
+#define MY_INTERNAL_NAME "lib" MY_LIBNAME PR_VMAJOR_STR
+#else
+#define MY_FILEOS VOS__WINDOWS32
+#define MY_INTERNAL_NAME MY_LIBNAME PR_VMAJOR_STR
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version-information resource
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0
+ PRODUCTVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGS MY_FILEFLAGS_2
+ FILEOS MY_FILEOS
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L // not used
+
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0" // Lang=US English, CharSet=Unicode
+ BEGIN
+ VALUE "CompanyName", "Mozilla Foundation\0"
+ VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0"
+ VALUE "FileVersion", PR_VERSION "\0"
+ VALUE "InternalName", MY_INTERNAL_NAME "\0"
+ VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0"
+ VALUE "ProductName", "Netscape Portable Runtime\0"
+ VALUE "ProductVersion", PR_VERSION "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/nsprpub/lib/prstreams/tests/testprstrm/Makefile.in b/nsprpub/lib/prstreams/tests/testprstrm/Makefile.in
new file mode 100644
index 0000000000..74ef1ac2c9
--- /dev/null
+++ b/nsprpub/lib/prstreams/tests/testprstrm/Makefile.in
@@ -0,0 +1,160 @@
+#
+# 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/.
+
+#! gmake
+
+MOD_DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+CXXSRCS = \
+ testprstrm.cpp \
+ $(NULL)
+
+OBJS = $(addprefix $(OBJDIR)/,$(CXXSRCS:.cpp=.$(OBJ_SUFFIX)))
+
+ifeq (,$(filter-out WINNT OS2,$(OS_ARCH)))
+PROG_SUFFIX = .exe
+else
+PROG_SUFFIX =
+endif
+
+PROGS = $(addprefix $(OBJDIR)/, $(CXXSRCS:.cpp=$(PROG_SUFFIX)))
+
+TARGETS = $(PROGS) $(OBJS)
+
+INCLUDES = -I$(dist_includedir)
+
+# Setting the variables LDOPTS and LIBPR. We first initialize
+# them to the default values, then adjust them for some platforms.
+LDOPTS = -L$(dist_libdir)
+LIBPR = -lnspr$(MOD_MAJOR_VERSION)
+LIBPRSTRMS = -lprstrms$(MOD_MAJOR_VERSION)
+
+ifeq ($(OS_ARCH), WINNT)
+ LDOPTS = -NOLOGO -DEBUG -INCREMENTAL:NO
+ ifeq ($(OS_TARGET), WIN95)
+ LIBPR = $(dist_libdir)/nspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ LIBPRSTRMS = $(dist_libdir)/prstrms$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ else
+ LIBPR = $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ LIBPRSTRMS = $(dist_libdir)/libprstrms$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ endif
+endif
+
+ifeq ($(OS_ARCH),OS2)
+LDOPTS += -Zomf -Zlinker /PM:VIO -lstdcpp
+endif
+
+ifneq ($(OS_ARCH), WINNT)
+PWD = $(shell pwd)
+endif
+
+ifeq ($(OS_ARCH), HP-UX)
+LDOPTS += -Wl,+s,+b,$(PWD)/$(dist_libdir)
+endif
+
+# AIX
+ifeq ($(OS_ARCH),AIX)
+LDOPTS += -blibpath:$(PWD)/$(dist_libdir):/usr/lib:/lib
+ifeq ($(OS_ARCH)$(OS_RELEASE),AIX4.1)
+LIBPR = -lnspr$(MOD_MAJOR_VERSION)_shr
+LIBPRSTRMS = -lprstrms$(MOD_MAJOR_VERSION)_shr
+else
+LDOPTS += -brtl
+EXTRA_LIBS = -ldl
+endif
+endif
+
+# Solaris
+ifeq ($(OS_ARCH), SunOS)
+ifdef NS_USE_GCC
+LDOPTS += -Xlinker -R -Xlinker $(PWD)/$(dist_libdir)
+else
+LDOPTS += -R $(PWD)/$(dist_libdir)
+# CC on SunOS 5.5.x needs to link with -lpthread even though we already
+# linked with this system library when we built libnspr.so.
+ifdef USE_PTHREADS
+EXTRA_LIBS = -lpthread
+endif # USE_PTHREADS
+endif # NS_USE_GCC
+endif # SunOS
+
+ifeq ($(OS_ARCH), SCOOS)
+# SCO Unix needs to link against -lsocket again even though we
+# already linked with these system libraries when we built libnspr.so.
+EXTRA_LIBS = -lsocket
+# This hardcodes in the executable programs the directory to find
+# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
+# option for ld on other platforms.
+export LD_RUN_PATH = $(PWD)/$(dist_libdir)
+endif
+
+ifeq ($(OS_ARCH), UNIXWARE)
+export LD_RUN_PATH = $(PWD)/$(dist_libdir)
+endif
+
+#####################################################
+#
+# The rules
+#
+#####################################################
+
+include $(topsrcdir)/config/rules.mk
+
+AIX_PRE_4_2 = 0
+ifeq ($(OS_ARCH),AIX)
+ifneq ($(OS_RELEASE),4.2)
+ifneq ($(USE_PTHREADS), 1)
+#AIX_PRE_4_2 = 1
+endif
+endif
+endif
+
+ifeq ($(AIX_PRE_4_2),1)
+
+# AIX releases prior to 4.2 need a special two-step linking hack
+# in order to both override the system select() and be able to
+# get at the original system select().
+#
+# We use a pattern rule in ns/nspr20/config/rules.mk to generate
+# the .$(OBJ_SUFFIX) file from the .c source file, then do the
+# two-step linking hack below.
+
+$(OBJDIR)/%: $(OBJDIR)/%.$(OBJ_SUFFIX)
+ @$(MAKE_OBJDIR)
+ rm -f $@ $(AIX_TMP)
+ $(CC) $(AIX_LINK_OPTS) -o $(AIX_TMP) $< $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).a
+ $(CC) -o $@ $(AIX_TMP) $(AIX_WRAP)
+ rm -f $(AIX_TMP)
+
+else
+
+# All platforms that are not AIX pre-4.2.
+
+$(OBJDIR)/%$(PROG_SUFFIX): $(OBJDIR)/%.$(OBJ_SUFFIX)
+ @$(MAKE_OBJDIR)
+ifeq ($(OS_ARCH), WINNT)
+ link $(LDOPTS) $< $(LIBPR) $(LIBPRSTRMS) ws2_32.lib -out:$@
+else
+ifeq ($(OS_ARCH),OS2)
+ $(LINK) $(EXEFLAGS) $(LDOPTS) $< $(LIBPR) $(LIBPRSTRMS) $(OS_LIBS) $(EXTRA_LIBS)
+else
+ $(CCC) $(XCFLAGS) $< $(LDOPTS) $(LIBPR) $(LIBPRSTRMS) $(EXTRA_LIBS) -o $@
+endif
+endif
+endif
+
+export:: $(TARGETS)
+clean::
+ rm -f $(TARGETS)
+
+testlinker:
+ echo $(LINK)
diff --git a/nsprpub/lib/prstreams/tests/testprstrm/testprstrm.cpp b/nsprpub/lib/prstreams/tests/testprstrm/testprstrm.cpp
new file mode 100644
index 0000000000..236e6ac64c
--- /dev/null
+++ b/nsprpub/lib/prstreams/tests/testprstrm/testprstrm.cpp
@@ -0,0 +1,172 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "prstrms.h"
+
+#include "prinit.h"
+#include "prio.h"
+#include "prthread.h"
+
+#include <cstring>
+#include <iostream>
+
+#ifdef XP_UNIX
+#include <sys/stat.h>
+#endif
+
+using std::cout;
+using std::endl;
+using std::ios;
+
+const unsigned int MaxCnt = 1;
+
+typedef struct threadarg {
+ const char *mytag;
+} threadarg;
+
+void threadwork(threadarg *arg);
+
+void
+threadmain(void *mytag)
+{
+ threadarg arg;
+
+ arg.mytag = static_cast<const char *>(mytag);
+
+ threadwork(&arg);
+}
+
+void
+threadwork(threadarg *arg)
+{
+ unsigned int i;
+
+ char fname1[256];
+ char fname2[256];
+
+ strcpy(fname1, arg->mytag);
+ strcpy(fname2, arg->mytag);
+ strcat(fname2, "2");
+ PR_Delete(fname1);
+ PR_Delete(fname2);
+
+ PRfilebuf *fb[MaxCnt];
+ PRifstream *ifs[MaxCnt];
+ PRofstream *ofs[MaxCnt];
+ int mode = 0;
+#ifdef XP_UNIX
+ mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
+#endif
+
+ //
+ // Allocate a bunch
+ cout << "Testing unused filebufs ----------------" << endl;
+ for (i=0; i < MaxCnt; i++) {
+ fb[i] = new PRfilebuf;
+ }
+ // Delete them
+ for (i=0; i < MaxCnt; i++) {
+ delete fb[i];
+ }
+ cout << "Unused filebufs complete ---------------" << endl;
+
+ //
+ // Allocate a bunch
+ cout << "Testing unused ifstream -----------------" << endl;
+ for (i=0; i < MaxCnt; i++) {
+ ifs[i] = new PRifstream;
+ }
+ //
+ // Delete them
+ for (i=0; i < MaxCnt; i++) {
+ delete ifs[i];
+ }
+ cout << "Unused ifstream complete ----------------" << endl;
+ //
+ // Allocate a bunch
+ cout << "Testing unused ofstream -----------------" << endl;
+ for (i=0; i < MaxCnt; i++) {
+ ofs[i] = new PRofstream;
+ }
+ for (i=0; i < MaxCnt; i++) {
+ *(ofs[i]) << "A"; // Write a bit
+ delete ofs[i]; // Delete it.
+ }
+ cout << "Unused ofstream complete ----------------" << endl;
+
+ cout << "Testing use of ofstream 1 (extra filebuf allocated) ---------" << endl;
+ PRofstream *aos = new PRofstream(fname1, ios::out|ios::ate, mode);
+ for (i=0; i < MaxCnt; i++) {
+ for (int j=0; j < 8192; j++) {
+ *aos << "AaBbCcDdEeFfGg" << endl;
+ }
+ fb[i] = new PRfilebuf; // Allocate as we go to hack at the heap
+ }
+ //
+ // Delete the extra foo we allocated
+ for (i=0; i < MaxCnt; i++) {
+ delete fb[i];
+ }
+ aos->flush(); // Explicit flush
+ delete aos;
+ cout << "Testing use of ofstream 1 complete (extra filebuf deleted) --" << endl;
+ cout << "Testing use of ofstream 2 (extra filebuf allocated) ---------" << endl;
+ PRofstream *aos2 = new PRofstream(fname2, ios::out, mode);
+
+ for (i=0; i < MaxCnt; i++) {
+ *aos2 << "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+ }
+ // Force flushing in the dtor
+ delete aos2;
+ cout << "Testing use of ofstream 2 complete (extra filebuf deleted) --" << endl;
+ char line[1024];
+ cout << "Testing use of ifstream 1 (stack allocation) -------------" << endl;
+ PRifstream ais(fname1);
+ for (i=0; i < MaxCnt; i++) {
+ ais >> line;
+ }
+ cout << "Testing use of ifstream 1 complete -----------------------" << endl;
+ cout << "Testing use of ifstream 2 ----------------------" << endl;
+ PRifstream *ais2 = new PRifstream(fname2);
+ char achar;
+ for (i=0; i < MaxCnt*10; i++) {
+ *ais2 >> achar;
+ }
+ delete ais2;
+ cout << "Testing use of ifstream 2 complete -------------" << endl;
+}
+
+#define STACKSIZE 1024*1024
+int
+main()
+{
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 256);
+ threadmain(const_cast<char *>("TestFile"));
+ PRThread *thr1 = PR_CreateThread(PR_SYSTEM_THREAD,
+ threadmain,
+ const_cast<char *>("TestFile1"),
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ STACKSIZE);
+ PRThread *thr2 = PR_CreateThread(PR_SYSTEM_THREAD,
+ threadmain,
+ const_cast<char *>("TestFile2"),
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ STACKSIZE);
+ PRThread *thr3 = PR_CreateThread(PR_SYSTEM_THREAD,
+ threadmain,
+ const_cast<char *>("TestFile3"),
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ STACKSIZE);
+ PR_JoinThread(thr1);
+ PR_JoinThread(thr2);
+ PR_JoinThread(thr3);
+ return 0;
+}
diff --git a/nsprpub/lib/tests/Makefile.in b/nsprpub/lib/tests/Makefile.in
new file mode 100644
index 0000000000..76b567d0ca
--- /dev/null
+++ b/nsprpub/lib/tests/Makefile.in
@@ -0,0 +1,170 @@
+#
+# 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/.
+
+#! gmake
+
+MOD_DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+CSRCS = \
+ arena.c \
+ base64t.c \
+ getopt.c \
+ string.c
+
+ifeq (,$(filter-out WINCE WINNT OS2,$(OS_ARCH)))
+CSRCS += arena.c
+endif
+
+ifeq (,$(filter-out WINCE WINNT OS2,$(OS_ARCH)))
+PROG_SUFFIX = .exe
+else
+PROG_SUFFIX =
+endif
+
+PROGS = $(addprefix $(OBJDIR)/, $(CSRCS:.c=$(PROG_SUFFIX)))
+
+TARGETS = $(PROGS) $(OBJS)
+
+INCLUDES = -I$(dist_includedir)
+
+# Setting the variables LDOPTS and LIBPR. We first initialize
+# them to the default values, then adjust them for some platforms.
+LDOPTS = -L$(dist_libdir)
+LIBPR = -lnspr$(MOD_MAJOR_VERSION)
+LIBPLC = -lplc$(MOD_MAJOR_VERSION)
+LIBPLDS = -lplds$(MOD_MAJOR_VERSION)
+
+ifeq (,$(filter-out WINCE WINNT, $(OS_ARCH)))
+ LDOPTS = -NOLOGO -DEBUG -INCREMENTAL:NO
+ ifeq (,$(filter-out WIN95 WINCE WINMO, $(OS_TARGET)))
+ LIBPR = $(dist_libdir)/nspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ LIBPLC= $(dist_libdir)/plc$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ LIBPLDS= $(dist_libdir)/plds$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ else
+ LIBPR = $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ LIBPLC= $(dist_libdir)/libplc$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ LIBPLDS= $(dist_libdir)/libplds$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ endif
+endif
+
+ifeq ($(OS_ARCH),OS2)
+LDOPTS += -Zomf -Zlinker /PM:VIO
+endif
+
+ifneq ($(OS_ARCH), WINNT)
+PWD = $(shell pwd)
+endif
+
+ifeq ($(OS_ARCH), Linux)
+ ifeq ($(OS_RELEASE), 1.2)
+ EXTRA_LIBS = -ldl
+ else
+ LDOPTS += -Xlinker -rpath $(PWD)/$(dist_libdir)
+ ifeq ($(USE_PTHREADS),1)
+ EXTRA_LIBS = -lpthread
+ endif
+ endif
+endif
+
+ifeq (,$(filter-out OpenBSD,$(OS_ARCH)))
+ ifeq ($(USE_PTHREADS),1)
+ EXTRA_LIBS = -lpthread
+ endif
+endif
+
+ifeq ($(OS_ARCH), HP-UX)
+LDOPTS += -Wl,+s,+b,$(PWD)/$(dist_libdir)
+endif
+
+# AIX
+ifeq ($(OS_ARCH),AIX)
+LDOPTS += -blibpath:$(PWD)/$(dist_libdir):/usr/lib:/lib
+LIBPR = -lnspr$(MOD_MAJOR_VERSION)_shr
+LIBPLC = -lplc$(MOD_MAJOR_VERSION)_shr
+endif
+
+# Solaris
+ifeq ($(OS_ARCH), SunOS)
+ifdef NS_USE_GCC
+LDOPTS += -Xlinker -R -Xlinker $(PWD)/$(dist_libdir)
+else
+LDOPTS += -R $(PWD)/$(dist_libdir)
+endif
+
+# SunOS 5.5 needs to link with -lpthread, even though we already
+# linked with this system library when we built libnspr.so.
+ifeq ($(OS_RELEASE), 5.5)
+ifdef USE_PTHREADS
+EXTRA_LIBS = -lpthread
+endif
+endif
+endif # SunOS
+
+#####################################################
+#
+# The rules
+#
+#####################################################
+
+include $(topsrcdir)/config/rules.mk
+
+AIX_PRE_4_2 = 0
+ifeq ($(OS_ARCH),AIX)
+ifneq ($(OS_RELEASE),4.2)
+ifneq ($(USE_PTHREADS), 1)
+#AIX_PRE_4_2 = 1
+endif
+endif
+endif
+
+ifeq ($(AIX_PRE_4_2),1)
+
+# AIX releases prior to 4.2 need a special two-step linking hack
+# in order to both override the system select() and be able to
+# get at the original system select().
+#
+# We use a pattern rule in ns/nspr20/config/rules.mk to generate
+# the .$(OBJ_SUFFIX) file from the .c source file, then do the
+# two-step linking hack below.
+
+$(OBJDIR)/%: $(OBJDIR)/%.$(OBJ_SUFFIX)
+ @$(MAKE_OBJDIR)
+ rm -f $@ $(AIX_TMP)
+ $(CC) $(AIX_LINK_OPTS) -o $(AIX_TMP) $< $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).a
+ $(CC) -o $@ $(AIX_TMP) $(AIX_WRAP)
+ rm -f $(AIX_TMP)
+
+else
+
+# All platforms that are not AIX pre-4.2.
+
+$(OBJDIR)/%$(PROG_SUFFIX): $(OBJDIR)/%.$(OBJ_SUFFIX)
+ @$(MAKE_OBJDIR)
+
+ifeq ($(OS_ARCH), WINNT)
+ link $(LDOPTS) $< $(LIBPLC) $(LIBPLDS) $(LIBPR) ws2_32.lib -out:$@
+else
+ifeq ($(OS_ARCH), WINCE)
+ $(LD) $(LDOPTS) $< $(LIBPLC) $(LIBPLDS) $(LIBPR) ws2.lib -out:$@
+else
+ifeq ($(OS_ARCH),OS2)
+ $(LINK) $(EXEFLAGS) $(LDOPTS) $< $(LIBPLC) $(LIBPLDS) $(LIBPR) $(OS_LIBS) $(EXTRA_LIBS)
+else
+ $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBPLDS) $(LIBPR) $(EXTRA_LIBS) -o $@
+endif
+endif
+endif
+endif
+
+export:: $(TARGETS)
+clean::
+ rm -f $(TARGETS)
diff --git a/nsprpub/lib/tests/arena.c b/nsprpub/lib/tests/arena.c
new file mode 100644
index 0000000000..2be2d5b4c1
--- /dev/null
+++ b/nsprpub/lib/tests/arena.c
@@ -0,0 +1,371 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+/*
+** File: arena.c
+** Description: Testing arenas
+**
+*/
+
+#include <string.h>
+#include <time.h>
+#include <stdlib.h>
+#include "nspr.h"
+#include "plarena.h"
+#include "plgetopt.h"
+
+PRLogModuleInfo *tLM;
+PRIntn threadCount = 0;
+PRMonitor *tMon;
+PRBool failed_already = PR_FALSE;
+
+/* Arguments from the command line with default values */
+PRIntn debug_mode = 0;
+PRIntn poolMin = 4096;
+PRIntn poolMax = (100 * 4096);
+PRIntn arenaMin = 40;
+PRIntn arenaMax = (100 * 40);
+PRIntn stressIterations = 15;
+PRIntn maxAlloc = (1024 * 1024);
+PRIntn stressThreads = 4;
+
+void DumpAll( void )
+{
+ return;
+}
+
+/*
+** Test Arena allocation.
+*/
+static void ArenaAllocate( void )
+{
+ PLArenaPool ap;
+ void *ptr;
+ PRInt32 i;
+
+ PL_InitArenaPool( &ap, "AllocArena", 2048, sizeof(double));
+ PR_LOG( tLM, PR_LOG_DEBUG, ("AA, InitPool -- Pool: %p. first: %p, current: %p, size: %d",
+ &ap, ap.first, ap.current, ap.arenasize ));
+
+ for( i = 0; i < 150; i++ )
+ {
+ PL_ARENA_ALLOCATE( ptr, &ap, 512 );
+ PR_LOG( tLM, PR_LOG_DEBUG,("AA, after alloc -- Pool: %p. first: %p, current: %p, size: %d",
+ &ap, ap.first, ap.current, ap.arenasize ));
+ PR_LOG( tLM, PR_LOG_DEBUG,(
+ "AA -- Pool: %p. alloc: %p ", &ap, ptr ));
+ }
+
+ PL_FreeArenaPool( &ap );
+
+ for( i = 0; i < 221; i++ )
+ {
+ PL_ARENA_ALLOCATE( ptr, &ap, 512 );
+ PR_LOG( tLM, PR_LOG_DEBUG,("AA, after alloc -- Pool: %p. first: %p, current: %p, size: %d",
+ &ap, ap.first, ap.current, ap.arenasize ));
+ PR_LOG( tLM, PR_LOG_DEBUG,(
+ "AA -- Pool: %p. alloc: %p ", &ap, ptr ));
+ }
+
+ PL_FreeArenaPool( &ap );
+
+ return;
+} /* end ArenaGrow() */
+/*
+** Test Arena grow.
+*/
+static void ArenaGrow( void )
+{
+ PLArenaPool ap;
+ void *ptr;
+ PRInt32 i;
+
+ PL_InitArenaPool( &ap, "TheArena", 4096, sizeof(double));
+ PL_ARENA_ALLOCATE( ptr, &ap, 512 );
+
+ PR_LOG( tLM, PR_LOG_DEBUG, ("Before growth -- Pool: %p. alloc: %p ", &ap, ptr ));
+
+ for( i = 0; i < 10; i++ )
+ {
+ PL_ARENA_GROW( ptr, &ap, 512, 7000 );
+ PR_LOG( tLM, PR_LOG_DEBUG, ("After growth -- Pool: %p. alloc: %p ", &ap, ptr ));
+ }
+
+
+ return;
+} /* end ArenaGrow() */
+
+
+/*
+** Test arena Mark and Release.
+*/
+static void MarkAndRelease( void )
+{
+ PLArenaPool ap;
+ void *ptr = NULL;
+ void *mark0, *mark1;
+ PRIntn i;
+
+ PL_InitArenaPool( &ap, "TheArena", 4096, sizeof(double));
+ mark0 = PL_ARENA_MARK( &ap );
+ PR_LOG( tLM, PR_LOG_DEBUG,
+ ("mark0. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p, m0: %p",
+ &ap, ap.first.next, ap.current, ap.arenasize, ptr, mark0 ));
+
+ for( i = 0; i < 201; i++ )
+ {
+ PL_ARENA_ALLOCATE( ptr, &ap, 512 );
+ PR_LOG( tLM, PR_LOG_DEBUG,
+ ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
+ &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
+ }
+
+ mark1 = PL_ARENA_MARK( &ap );
+ PR_LOG( tLM, PR_LOG_DEBUG,
+ ("mark1. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p, m1: %p",
+ &ap, ap.first.next, ap.current, ap.arenasize, ptr, mark1 ));
+
+
+ for( i = 0; i < 225; i++ )
+ {
+ PL_ARENA_ALLOCATE( ptr, &ap, 512 );
+ PR_LOG( tLM, PR_LOG_DEBUG,
+ ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
+ &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
+ }
+
+ PL_ARENA_RELEASE( &ap, mark1 );
+ PR_LOG( tLM, PR_LOG_DEBUG,
+ ("Release-1: %p -- Pool: %p. first: %p, current: %p, size: %d",
+ mark1, &ap, ap.first, ap.current, ap.arenasize ));
+
+ for( i = 0; i < 20; i++ )
+ {
+ PL_ARENA_ALLOCATE( ptr, &ap, 512 );
+ PR_LOG( tLM, PR_LOG_DEBUG,
+ ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
+ &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
+ }
+
+ PL_ARENA_RELEASE( &ap, mark1 );
+ PR_LOG( tLM, PR_LOG_DEBUG,
+ ("Release-1. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
+ &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
+
+ PL_ARENA_RELEASE( &ap, mark0 );
+ PR_LOG( tLM, PR_LOG_DEBUG,
+ ("Release-0. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
+ &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
+
+ PL_FreeArenaPool( &ap );
+ PR_LOG( tLM, PR_LOG_DEBUG,
+ ("Free. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
+ &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
+
+ PL_FinishArenaPool( &ap );
+ PR_LOG( tLM, PR_LOG_DEBUG,
+ ("Finish. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
+ &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
+
+ return;
+} /* end MarkAndRelease() */
+
+/*
+** RandSize() returns a random number in the range
+** min..max, rounded to the next doubleword
+**
+*/
+static PRIntn RandSize( PRIntn min, PRIntn max )
+{
+ PRIntn sz = (rand() % (max -min)) + min + sizeof(double);
+
+ sz &= ~sizeof(double)-1;
+
+ return(sz);
+}
+
+
+/*
+** StressThread()
+** A bunch of these beat on individual arenas
+** This tests the free_list protection.
+**
+*/
+static void PR_CALLBACK StressThread( void *arg )
+{
+ PLArenaPool ap;
+ PRIntn i;
+ PRIntn sz;
+ void *ptr;
+ PRThread *tp = PR_GetCurrentThread();
+
+ PR_LOG( tLM, PR_LOG_DEBUG, ("Stress Thread %p started\n", PR_GetCurrentThread()));
+ PL_InitArenaPool( &ap, "TheArena", RandSize( poolMin, poolMax), sizeof(double));
+
+ for ( i = 0; i < stressIterations; i++ )
+ {
+ PRIntn allocated = 0;
+
+ while ( allocated < maxAlloc )
+ {
+ sz = RandSize( arenaMin, arenaMax );
+ PL_ARENA_ALLOCATE( ptr, &ap, sz );
+ if ( ptr == NULL )
+ {
+ PR_LOG( tLM, PR_LOG_ERROR, ("ARENA_ALLOCATE() returned NULL\n\tAllocated: %d\n", allocated));
+ break;
+ }
+ allocated += sz;
+ }
+ PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p finished one iteration\n", tp));
+ PL_FreeArenaPool( &ap );
+ }
+ PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p finished all iteration\n", tp));
+ PL_FinishArenaPool( &ap );
+ PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p after FinishArenaPool()\n", tp));
+
+ /* That's all folks! let's quit */
+ PR_EnterMonitor(tMon);
+ threadCount--;
+ PR_Notify(tMon);
+ PR_ExitMonitor(tMon);
+ return;
+}
+
+/*
+** Stress()
+** Flog the hell out of arenas multi-threaded.
+** Do NOT pass an individual arena to another thread.
+**
+*/
+static void Stress( void )
+{
+ PRThread *tt;
+ PRIntn i;
+
+ tMon = PR_NewMonitor();
+
+ for ( i = 0 ; i < stressThreads ; i++ )
+ {
+ PR_EnterMonitor(tMon);
+ tt = PR_CreateThread(PR_USER_THREAD,
+ StressThread,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ threadCount++;
+ PR_ExitMonitor(tMon);
+ }
+
+ /* Wait for all threads to exit */
+ PR_EnterMonitor(tMon);
+ while ( threadCount != 0 )
+ {
+ PR_Wait(tMon, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_ExitMonitor(tMon);
+ PR_DestroyMonitor(tMon);
+
+ return;
+} /* end Stress() */
+
+/*
+** EvaluateResults()
+** uses failed_already to display results and set program
+** exit code.
+*/
+static PRIntn EvaluateResults(void)
+{
+ PRIntn rc = 0;
+
+ if ( failed_already == PR_TRUE )
+ {
+ PR_LOG( tLM, PR_LOG_DEBUG, ("FAIL\n"));
+ rc =1;
+ }
+ else
+ {
+ PR_LOG( tLM, PR_LOG_DEBUG, ("PASS\n"));
+ }
+ return(rc);
+} /* EvaluateResults() */
+
+void Help( void )
+{
+ printf("arena [options]\n");
+ printf("where options are:\n");
+ printf("-p <n> minimum size of an arena pool. Default(%d)\n", poolMin);
+ printf("-P <n> maximum size of an arena pool. Default(%d)\n", poolMax);
+ printf("-a <n> minimum size of an arena allocation. Default(%d)\n", arenaMin);
+ printf("-A <n> maximum size of an arena allocation. Default(%d)\n", arenaMax);
+ printf("-i <n> number of iterations in a stress thread. Default(%d)\n", stressIterations);
+ printf("-s <n> maximum allocation for a single stress thread. Default(%d)\n", maxAlloc);
+ printf("-t <n> number of stress threads. Default(%d)\n", stressThreads );
+ printf("-d enable debug mode\n");
+ printf("\n");
+ exit(1);
+}
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dhp:P:a:A:i:s:t:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) {
+ continue;
+ }
+ switch (opt->option)
+ {
+ case 'a': /* arena Min size */
+ arenaMin = atol( opt->value );
+ break;
+ case 'A': /* arena Max size */
+ arenaMax = atol( opt->value );
+ break;
+ case 'p': /* pool Min size */
+ poolMin = atol( opt->value );
+ break;
+ case 'P': /* pool Max size */
+ poolMax = atol( opt->value );
+ break;
+ case 'i': /* Iterations in stress tests */
+ stressIterations = atol( opt->value );
+ break;
+ case 's': /* storage to get per iteration */
+ maxAlloc = atol( opt->value );
+ break;
+ case 't': /* Number of stress threads to create */
+ stressThreads = atol( opt->value );
+ break;
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ case 'h': /* help */
+ default:
+ Help();
+ } /* end switch() */
+ } /* end while() */
+ PL_DestroyOptState(opt);
+
+ srand( (unsigned)time( NULL ) ); /* seed random number generator */
+ tLM = PR_NewLogModule("testcase");
+
+
+#if 0
+ ArenaAllocate();
+ ArenaGrow();
+#endif
+
+ MarkAndRelease();
+
+ Stress();
+
+ return(EvaluateResults());
+} /* end main() */
+
+/* arena.c */
diff --git a/nsprpub/lib/tests/base64t.c b/nsprpub/lib/tests/base64t.c
new file mode 100644
index 0000000000..adbbb813bf
--- /dev/null
+++ b/nsprpub/lib/tests/base64t.c
@@ -0,0 +1,3390 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "plbase64.h"
+#include "plstr.h"
+#include "nspr.h"
+
+#include <stdio.h>
+
+static unsigned char *base = (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/* PL_Base64Encode, single characters */
+PRBool test_001(void)
+{
+ PRUint32 a, b;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char result[ 8 ];
+ char *rv;
+
+ printf("Test 001 (PL_Base64Encode, single characters) ..."); fflush(stdout);
+
+ plain[1] = plain[2] = plain[3] = (unsigned char)0;
+ cypher[2] = cypher[3] = (unsigned char)'=';
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (unsigned char)(a * 4 + b);
+ cypher[1] = base[(b * 16)];
+
+ rv = PL_Base64Encode((char *)plain, 1, result);
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d, %d): return value\n", a, b);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp((char *)cypher, result, 4) )
+ {
+ printf("FAIL\n\t(%d, %d): expected \"%s,\" got \"%.4s.\"\n",
+ a, b, cypher, result);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Encode, double characters */
+PRBool test_002(void)
+{
+ PRUint32 a, b, c, d;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char result[ 8 ];
+ char *rv;
+
+ printf("Test 002 (PL_Base64Encode, double characters) ..."); fflush(stdout);
+
+ plain[2] = plain[3] = (unsigned char)0;
+ cypher[3] = (unsigned char)'=';
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (a*4) + b;
+ for( c = 0; c < 16; c++ )
+ {
+ cypher[1] = base[b*16 + c];
+ for( d = 0; d < 16; d++ )
+ {
+ plain[1] = c*16 + d;
+ cypher[2] = base[d*4];
+
+ rv = PL_Base64Encode((char *)plain, 2, result);
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): return value\n", a, b, c, d);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp((char *)cypher, result, 4) )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): expected \"%s,\" got \"%.4s.\"\n",
+ a, b, c, d, cypher, result);
+ return PR_FALSE;
+ }
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Encode, triple characters */
+PRBool test_003(void)
+{
+ PRUint32 a, b, c, d, e, f;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char result[ 8 ];
+ char *rv;
+
+ printf("Test 003 (PL_Base64Encode, triple characters) ..."); fflush(stdout);
+
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (a*4) + b;
+ for( c = 0; c < 16; c++ )
+ {
+ cypher[1] = base[b*16 + c];
+ for( d = 0; d < 16; d++ )
+ {
+ plain[1] = c*16 + d;
+ for( e = 0; e < 4; e++ )
+ {
+ cypher[2] = base[d*4 + e];
+ for( f = 0; f < 64; f++ )
+ {
+ plain[2] = e * 64 + f;
+ cypher[3] = base[f];
+
+ rv = PL_Base64Encode((char *)plain, 3, result);
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): return value\n", a, b, c, d, e, f);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp((char *)cypher, result, 4) )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): expected \"%s,\" got \"%.4s.\"\n",
+ a, b, c, d, e, f, cypher, result);
+ return PR_FALSE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+static struct
+{
+ const char *plaintext;
+ const char *cyphertext;
+} array[] =
+{
+ /* Cyphertexts generated with uuenview 0.5.13 */
+ { " ", "IA==" },
+ { ".", "Lg==" },
+ { "/", "Lw==" },
+ { "C", "Qw==" },
+ { "H", "SA==" },
+ { "S", "Uw==" },
+ { "^", "Xg==" },
+ { "a", "YQ==" },
+ { "o", "bw==" },
+ { "t", "dA==" },
+
+ { "AB", "QUI=" },
+ { "AH", "QUg=" },
+ { "AQ", "QVE=" },
+ { "BD", "QkQ=" },
+ { "CR", "Q1I=" },
+ { "CS", "Q1M=" },
+ { "DB", "REI=" },
+ { "DC", "REM=" },
+ { "EK", "RUs=" },
+ { "ET", "RVQ=" },
+ { "IM", "SU0=" },
+ { "JR", "SlI=" },
+ { "LO", "TE8=" },
+ { "LW", "TFc=" },
+ { "ML", "TUw=" },
+ { "SB", "U0I=" },
+ { "TO", "VE8=" },
+ { "VS", "VlM=" },
+ { "WP", "V1A=" },
+ /* legitimate two-letter words */
+ { "ad", "YWQ=" },
+ { "ah", "YWg=" },
+ { "am", "YW0=" },
+ { "an", "YW4=" },
+ { "as", "YXM=" },
+ { "at", "YXQ=" },
+ { "ax", "YXg=" },
+ { "be", "YmU=" },
+ { "by", "Ynk=" },
+ { "do", "ZG8=" },
+ { "go", "Z28=" },
+ { "he", "aGU=" },
+ { "hi", "aGk=" },
+ { "if", "aWY=" },
+ { "in", "aW4=" },
+ { "is", "aXM=" },
+ { "it", "aXQ=" },
+ { "me", "bWU=" },
+ { "my", "bXk=" },
+ { "no", "bm8=" },
+ { "of", "b2Y=" },
+ { "on", "b24=" },
+ { "or", "b3I=" },
+ { "ox", "b3g=" },
+ { "so", "c28=" },
+ { "to", "dG8=" },
+ { "up", "dXA=" },
+ { "us", "dXM=" },
+ { "we", "d2U=" },
+ /* all three-letter entries in /usr/dict/words */
+ { "1st", "MXN0" },
+ { "2nd", "Mm5k" },
+ { "3rd", "M3Jk" },
+ { "4th", "NHRo" },
+ { "5th", "NXRo" },
+ { "6th", "NnRo" },
+ { "7th", "N3Ro" },
+ { "8th", "OHRo" },
+ { "9th", "OXRo" },
+ { "AAA", "QUFB" },
+ { "AAU", "QUFV" },
+ { "ABA", "QUJB" },
+ { "abc", "YWJj" },
+ { "Abe", "QWJl" },
+ { "Abo", "QWJv" },
+ { "ace", "YWNl" },
+ { "ACM", "QUNN" },
+ { "ACS", "QUNT" },
+ { "act", "YWN0" },
+ { "Ada", "QWRh" },
+ { "add", "YWRk" },
+ { "ado", "YWRv" },
+ { "aft", "YWZ0" },
+ { "age", "YWdl" },
+ { "ago", "YWdv" },
+ { "aid", "YWlk" },
+ { "ail", "YWls" },
+ { "aim", "YWlt" },
+ { "air", "YWly" },
+ { "ala", "YWxh" },
+ { "alb", "YWxi" },
+ { "ale", "YWxl" },
+ { "Ali", "QWxp" },
+ { "all", "YWxs" },
+ { "alp", "YWxw" },
+ { "A&M", "QSZN" },
+ { "AMA", "QU1B" },
+ { "ami", "YW1p" },
+ { "amp", "YW1w" },
+ { "Amy", "QW15" },
+ { "amy", "YW15" },
+ { "ana", "YW5h" },
+ { "and", "YW5k" },
+ { "ani", "YW5p" },
+ { "Ann", "QW5u" },
+ { "ant", "YW50" },
+ { "any", "YW55" },
+ { "A&P", "QSZQ" },
+ { "ape", "YXBl" },
+ { "Apr", "QXBy" },
+ { "APS", "QVBT" },
+ { "apt", "YXB0" },
+ { "arc", "YXJj" },
+ { "are", "YXJl" },
+ { "ark", "YXJr" },
+ { "arm", "YXJt" },
+ { "art", "YXJ0" },
+ { "a's", "YSdz" },
+ { "ash", "YXNo" },
+ { "ask", "YXNr" },
+ { "ass", "YXNz" },
+ { "ate", "YXRl" },
+ { "Aug", "QXVn" },
+ { "auk", "YXVr" },
+ { "Ave", "QXZl" },
+ { "awe", "YXdl" },
+ { "awl", "YXds" },
+ { "awn", "YXdu" },
+ { "axe", "YXhl" },
+ { "aye", "YXll" },
+ { "bad", "YmFk" },
+ { "bag", "YmFn" },
+ { "bah", "YmFo" },
+ { "bam", "YmFt" },
+ { "ban", "YmFu" },
+ { "bar", "YmFy" },
+ { "bat", "YmF0" },
+ { "bay", "YmF5" },
+ { "bed", "YmVk" },
+ { "bee", "YmVl" },
+ { "beg", "YmVn" },
+ { "bel", "YmVs" },
+ { "Ben", "QmVu" },
+ { "bet", "YmV0" },
+ { "bey", "YmV5" },
+ { "bib", "Ymli" },
+ { "bid", "Ymlk" },
+ { "big", "Ymln" },
+ { "bin", "Ymlu" },
+ { "bit", "Yml0" },
+ { "biz", "Yml6" },
+ { "BMW", "Qk1X" },
+ { "boa", "Ym9h" },
+ { "bob", "Ym9i" },
+ { "bog", "Ym9n" },
+ { "bon", "Ym9u" },
+ { "boo", "Ym9v" },
+ { "bop", "Ym9w" },
+ { "bow", "Ym93" },
+ { "box", "Ym94" },
+ { "boy", "Ym95" },
+ { "b's", "Yidz" },
+ { "BTL", "QlRM" },
+ { "BTU", "QlRV" },
+ { "bub", "YnVi" },
+ { "bud", "YnVk" },
+ { "bug", "YnVn" },
+ { "bum", "YnVt" },
+ { "bun", "YnVu" },
+ { "bus", "YnVz" },
+ { "but", "YnV0" },
+ { "buy", "YnV5" },
+ { "bye", "Ynll" },
+ { "cab", "Y2Fi" },
+ { "Cal", "Q2Fs" },
+ { "cam", "Y2Ft" },
+ { "can", "Y2Fu" },
+ { "cap", "Y2Fw" },
+ { "car", "Y2Fy" },
+ { "cat", "Y2F0" },
+ { "caw", "Y2F3" },
+ { "CBS", "Q0JT" },
+ { "CDC", "Q0RD" },
+ { "CEQ", "Q0VR" },
+ { "chi", "Y2hp" },
+ { "CIA", "Q0lB" },
+ { "cit", "Y2l0" },
+ { "cod", "Y29k" },
+ { "cog", "Y29n" },
+ { "col", "Y29s" },
+ { "con", "Y29u" },
+ { "coo", "Y29v" },
+ { "cop", "Y29w" },
+ { "cos", "Y29z" },
+ { "cot", "Y290" },
+ { "cow", "Y293" },
+ { "cox", "Y294" },
+ { "coy", "Y295" },
+ { "CPA", "Q1BB" },
+ { "cpu", "Y3B1" },
+ { "CRT", "Q1JU" },
+ { "cry", "Y3J5" },
+ { "c's", "Yydz" },
+ { "cub", "Y3Vi" },
+ { "cud", "Y3Vk" },
+ { "cue", "Y3Vl" },
+ { "cup", "Y3Vw" },
+ { "cur", "Y3Vy" },
+ { "cut", "Y3V0" },
+ { "dab", "ZGFi" },
+ { "dad", "ZGFk" },
+ { "dam", "ZGFt" },
+ { "Dan", "RGFu" },
+ { "Dar", "RGFy" },
+ { "day", "ZGF5" },
+ { "Dec", "RGVj" },
+ { "Dee", "RGVl" },
+ { "Del", "RGVs" },
+ { "den", "ZGVu" },
+ { "Des", "RGVz" },
+ { "dew", "ZGV3" },
+ { "dey", "ZGV5" },
+ { "did", "ZGlk" },
+ { "die", "ZGll" },
+ { "dig", "ZGln" },
+ { "dim", "ZGlt" },
+ { "din", "ZGlu" },
+ { "dip", "ZGlw" },
+ { "Dis", "RGlz" },
+ { "DNA", "RE5B" },
+ { "DOD", "RE9E" },
+ { "doe", "ZG9l" },
+ { "dog", "ZG9n" },
+ { "don", "ZG9u" },
+ { "dot", "ZG90" },
+ { "Dow", "RG93" },
+ { "dry", "ZHJ5" },
+ { "d's", "ZCdz" },
+ { "dub", "ZHVi" },
+ { "dud", "ZHVk" },
+ { "due", "ZHVl" },
+ { "dug", "ZHVn" },
+ { "dun", "ZHVu" },
+ { "dye", "ZHll" },
+ { "ear", "ZWFy" },
+ { "eat", "ZWF0" },
+ { "ebb", "ZWJi" },
+ { "EDT", "RURU" },
+ { "eel", "ZWVs" },
+ { "eft", "ZWZ0" },
+ { "e.g", "ZS5n" },
+ { "egg", "ZWdn" },
+ { "ego", "ZWdv" },
+ { "eke", "ZWtl" },
+ { "Eli", "RWxp" },
+ { "elk", "ZWxr" },
+ { "ell", "ZWxs" },
+ { "elm", "ZWxt" },
+ { "Ely", "RWx5" },
+ { "end", "ZW5k" },
+ { "Eng", "RW5n" },
+ { "EPA", "RVBB" },
+ { "era", "ZXJh" },
+ { "ere", "ZXJl" },
+ { "erg", "ZXJn" },
+ { "err", "ZXJy" },
+ { "e's", "ZSdz" },
+ { "EST", "RVNU" },
+ { "eta", "ZXRh" },
+ { "etc", "ZXRj" },
+ { "Eva", "RXZh" },
+ { "eve", "ZXZl" },
+ { "ewe", "ZXdl" },
+ { "eye", "ZXll" },
+ { "FAA", "RkFB" },
+ { "fad", "ZmFk" },
+ { "fag", "ZmFn" },
+ { "fan", "ZmFu" },
+ { "far", "ZmFy" },
+ { "fat", "ZmF0" },
+ { "fay", "ZmF5" },
+ { "FBI", "RkJJ" },
+ { "FCC", "RkND" },
+ { "FDA", "RkRB" },
+ { "Feb", "RmVi" },
+ { "fed", "ZmVk" },
+ { "fee", "ZmVl" },
+ { "few", "ZmV3" },
+ { "fib", "Zmli" },
+ { "fig", "Zmln" },
+ { "fin", "Zmlu" },
+ { "fir", "Zmly" },
+ { "fit", "Zml0" },
+ { "fix", "Zml4" },
+ { "Flo", "Rmxv" },
+ { "flu", "Zmx1" },
+ { "fly", "Zmx5" },
+ { "FMC", "Rk1D" },
+ { "fob", "Zm9i" },
+ { "foe", "Zm9l" },
+ { "fog", "Zm9n" },
+ { "fop", "Zm9w" },
+ { "for", "Zm9y" },
+ { "fox", "Zm94" },
+ { "FPC", "RlBD" },
+ { "fro", "ZnJv" },
+ { "fry", "ZnJ5" },
+ { "f's", "Zidz" },
+ { "FTC", "RlRD" },
+ { "fum", "ZnVt" },
+ { "fun", "ZnVu" },
+ { "fur", "ZnVy" },
+ { "gab", "Z2Fi" },
+ { "gad", "Z2Fk" },
+ { "gag", "Z2Fn" },
+ { "gal", "Z2Fs" },
+ { "gam", "Z2Ft" },
+ { "GAO", "R0FP" },
+ { "gap", "Z2Fw" },
+ { "gar", "Z2Fy" },
+ { "gas", "Z2Fz" },
+ { "gay", "Z2F5" },
+ { "gee", "Z2Vl" },
+ { "gel", "Z2Vs" },
+ { "gem", "Z2Vt" },
+ { "get", "Z2V0" },
+ { "gig", "Z2ln" },
+ { "Gil", "R2ls" },
+ { "gin", "Z2lu" },
+ { "GMT", "R01U" },
+ { "GNP", "R05Q" },
+ { "gnu", "Z251" },
+ { "Goa", "R29h" },
+ { "gob", "Z29i" },
+ { "god", "Z29k" },
+ { "gog", "Z29n" },
+ { "GOP", "R09Q" },
+ { "got", "Z290" },
+ { "GPO", "R1BP" },
+ { "g's", "Zydz" },
+ { "GSA", "R1NB" },
+ { "gum", "Z3Vt" },
+ { "gun", "Z3Vu" },
+ { "Gus", "R3Vz" },
+ { "gut", "Z3V0" },
+ { "guy", "Z3V5" },
+ { "gym", "Z3lt" },
+ { "gyp", "Z3lw" },
+ { "had", "aGFk" },
+ { "Hal", "SGFs" },
+ { "ham", "aGFt" },
+ { "Han", "SGFu" },
+ { "hap", "aGFw" },
+ { "hat", "aGF0" },
+ { "haw", "aGF3" },
+ { "hay", "aGF5" },
+ { "hem", "aGVt" },
+ { "hen", "aGVu" },
+ { "her", "aGVy" },
+ { "hew", "aGV3" },
+ { "hex", "aGV4" },
+ { "hey", "aGV5" },
+ { "hid", "aGlk" },
+ { "him", "aGlt" },
+ { "hip", "aGlw" },
+ { "his", "aGlz" },
+ { "hit", "aGl0" },
+ { "hob", "aG9i" },
+ { "hoc", "aG9j" },
+ { "hoe", "aG9l" },
+ { "hog", "aG9n" },
+ { "hoi", "aG9p" },
+ { "Hom", "SG9t" },
+ { "hop", "aG9w" },
+ { "hot", "aG90" },
+ { "how", "aG93" },
+ { "hoy", "aG95" },
+ { "h's", "aCdz" },
+ { "hub", "aHVi" },
+ { "hue", "aHVl" },
+ { "hug", "aHVn" },
+ { "huh", "aHVo" },
+ { "hum", "aHVt" },
+ { "Hun", "SHVu" },
+ { "hut", "aHV0" },
+ { "Ian", "SWFu" },
+ { "IBM", "SUJN" },
+ { "Ibn", "SWJu" },
+ { "ICC", "SUND" },
+ { "ice", "aWNl" },
+ { "icy", "aWN5" },
+ { "I'd", "SSdk" },
+ { "Ida", "SWRh" },
+ { "i.e", "aS5l" },
+ { "iii", "aWlp" },
+ { "Ike", "SWtl" },
+ { "ill", "aWxs" },
+ { "I'm", "SSdt" },
+ { "imp", "aW1w" },
+ { "Inc", "SW5j" },
+ { "ink", "aW5r" },
+ { "inn", "aW5u" },
+ { "ion", "aW9u" },
+ { "Ira", "SXJh" },
+ { "ire", "aXJl" },
+ { "irk", "aXJr" },
+ { "IRS", "SVJT" },
+ { "i's", "aSdz" },
+ { "Ito", "SXRv" },
+ { "ITT", "SVRU" },
+ { "ivy", "aXZ5" },
+ { "jab", "amFi" },
+ { "jag", "amFn" },
+ { "jam", "amFt" },
+ { "Jan", "SmFu" },
+ { "jar", "amFy" },
+ { "jaw", "amF3" },
+ { "jay", "amF5" },
+ { "Jed", "SmVk" },
+ { "jet", "amV0" },
+ { "Jew", "SmV3" },
+ { "jig", "amln" },
+ { "Jim", "Smlt" },
+ { "job", "am9i" },
+ { "Joe", "Sm9l" },
+ { "jog", "am9n" },
+ { "Jon", "Sm9u" },
+ { "jot", "am90" },
+ { "joy", "am95" },
+ { "j's", "aidz" },
+ { "jug", "anVn" },
+ { "jut", "anV0" },
+ { "Kay", "S2F5" },
+ { "keg", "a2Vn" },
+ { "ken", "a2Vu" },
+ { "key", "a2V5" },
+ { "kid", "a2lk" },
+ { "Kim", "S2lt" },
+ { "kin", "a2lu" },
+ { "kit", "a2l0" },
+ { "k's", "aydz" },
+ { "lab", "bGFi" },
+ { "lac", "bGFj" },
+ { "lad", "bGFk" },
+ { "lag", "bGFn" },
+ { "lam", "bGFt" },
+ { "Lao", "TGFv" },
+ { "lap", "bGFw" },
+ { "law", "bGF3" },
+ { "lax", "bGF4" },
+ { "lay", "bGF5" },
+ { "lea", "bGVh" },
+ { "led", "bGVk" },
+ { "lee", "bGVl" },
+ { "leg", "bGVn" },
+ { "Len", "TGVu" },
+ { "Leo", "TGVv" },
+ { "let", "bGV0" },
+ { "Lev", "TGV2" },
+ { "Lew", "TGV3" },
+ { "lew", "bGV3" },
+ { "lid", "bGlk" },
+ { "lie", "bGll" },
+ { "lim", "bGlt" },
+ { "Lin", "TGlu" },
+ { "lip", "bGlw" },
+ { "lit", "bGl0" },
+ { "Liz", "TGl6" },
+ { "lob", "bG9i" },
+ { "log", "bG9n" },
+ { "lop", "bG9w" },
+ { "Los", "TG9z" },
+ { "lot", "bG90" },
+ { "Lou", "TG91" },
+ { "low", "bG93" },
+ { "loy", "bG95" },
+ { "l's", "bCdz" },
+ { "LSI", "TFNJ" },
+ { "Ltd", "THRk" },
+ { "LTV", "TFRW" },
+ { "lug", "bHVn" },
+ { "lux", "bHV4" },
+ { "lye", "bHll" },
+ { "Mac", "TWFj" },
+ { "mad", "bWFk" },
+ { "Mae", "TWFl" },
+ { "man", "bWFu" },
+ { "Mao", "TWFv" },
+ { "map", "bWFw" },
+ { "mar", "bWFy" },
+ { "mat", "bWF0" },
+ { "maw", "bWF3" },
+ { "Max", "TWF4" },
+ { "max", "bWF4" },
+ { "may", "bWF5" },
+ { "MBA", "TUJB" },
+ { "Meg", "TWVn" },
+ { "Mel", "TWVs" },
+ { "men", "bWVu" },
+ { "met", "bWV0" },
+ { "mew", "bWV3" },
+ { "mid", "bWlk" },
+ { "mig", "bWln" },
+ { "min", "bWlu" },
+ { "MIT", "TUlU" },
+ { "mix", "bWl4" },
+ { "mob", "bW9i" },
+ { "Moe", "TW9l" },
+ { "moo", "bW9v" },
+ { "mop", "bW9w" },
+ { "mot", "bW90" },
+ { "mow", "bW93" },
+ { "MPH", "TVBI" },
+ { "Mrs", "TXJz" },
+ { "m's", "bSdz" },
+ { "mud", "bXVk" },
+ { "mug", "bXVn" },
+ { "mum", "bXVt" },
+ { "nab", "bmFi" },
+ { "nag", "bmFn" },
+ { "Nan", "TmFu" },
+ { "nap", "bmFw" },
+ { "Nat", "TmF0" },
+ { "nay", "bmF5" },
+ { "NBC", "TkJD" },
+ { "NBS", "TkJT" },
+ { "NCO", "TkNP" },
+ { "NCR", "TkNS" },
+ { "Ned", "TmVk" },
+ { "nee", "bmVl" },
+ { "net", "bmV0" },
+ { "new", "bmV3" },
+ { "nib", "bmli" },
+ { "NIH", "TklI" },
+ { "nil", "bmls" },
+ { "nip", "bmlw" },
+ { "nit", "bml0" },
+ { "NNE", "Tk5F" },
+ { "NNW", "Tk5X" },
+ { "nob", "bm9i" },
+ { "nod", "bm9k" },
+ { "non", "bm9u" },
+ { "nor", "bm9y" },
+ { "not", "bm90" },
+ { "Nov", "Tm92" },
+ { "now", "bm93" },
+ { "NRC", "TlJD" },
+ { "n's", "bidz" },
+ { "NSF", "TlNG" },
+ { "nun", "bnVu" },
+ { "nut", "bnV0" },
+ { "NYC", "TllD" },
+ { "NYU", "TllV" },
+ { "oaf", "b2Fm" },
+ { "oak", "b2Fr" },
+ { "oar", "b2Fy" },
+ { "oat", "b2F0" },
+ { "Oct", "T2N0" },
+ { "odd", "b2Rk" },
+ { "ode", "b2Rl" },
+ { "off", "b2Zm" },
+ { "oft", "b2Z0" },
+ { "ohm", "b2ht" },
+ { "oil", "b2ls" },
+ { "old", "b2xk" },
+ { "one", "b25l" },
+ { "opt", "b3B0" },
+ { "orb", "b3Ji" },
+ { "ore", "b3Jl" },
+ { "Orr", "T3Jy" },
+ { "o's", "bydz" },
+ { "Ott", "T3R0" },
+ { "our", "b3Vy" },
+ { "out", "b3V0" },
+ { "ova", "b3Zh" },
+ { "owe", "b3dl" },
+ { "owl", "b3ds" },
+ { "own", "b3du" },
+ { "pad", "cGFk" },
+ { "pal", "cGFs" },
+ { "Pam", "UGFt" },
+ { "pan", "cGFu" },
+ { "pap", "cGFw" },
+ { "par", "cGFy" },
+ { "pat", "cGF0" },
+ { "paw", "cGF3" },
+ { "pax", "cGF4" },
+ { "pay", "cGF5" },
+ { "Paz", "UGF6" },
+ { "PBS", "UEJT" },
+ { "PDP", "UERQ" },
+ { "pea", "cGVh" },
+ { "pee", "cGVl" },
+ { "peg", "cGVn" },
+ { "pen", "cGVu" },
+ { "pep", "cGVw" },
+ { "per", "cGVy" },
+ { "pet", "cGV0" },
+ { "pew", "cGV3" },
+ { "PhD", "UGhE" },
+ { "phi", "cGhp" },
+ { "pie", "cGll" },
+ { "pig", "cGln" },
+ { "pin", "cGlu" },
+ { "pip", "cGlw" },
+ { "pit", "cGl0" },
+ { "ply", "cGx5" },
+ { "pod", "cG9k" },
+ { "Poe", "UG9l" },
+ { "poi", "cG9p" },
+ { "pol", "cG9s" },
+ { "pop", "cG9w" },
+ { "pot", "cG90" },
+ { "pow", "cG93" },
+ { "ppm", "cHBt" },
+ { "pro", "cHJv" },
+ { "pry", "cHJ5" },
+ { "p's", "cCdz" },
+ { "psi", "cHNp" },
+ { "PTA", "UFRB" },
+ { "pub", "cHVi" },
+ { "PUC", "UFVD" },
+ { "pug", "cHVn" },
+ { "pun", "cHVu" },
+ { "pup", "cHVw" },
+ { "pus", "cHVz" },
+ { "put", "cHV0" },
+ { "PVC", "UFZD" },
+ { "QED", "UUVE" },
+ { "q's", "cSdz" },
+ { "qua", "cXVh" },
+ { "quo", "cXVv" },
+ { "Rae", "UmFl" },
+ { "rag", "cmFn" },
+ { "raj", "cmFq" },
+ { "ram", "cmFt" },
+ { "ran", "cmFu" },
+ { "rap", "cmFw" },
+ { "rat", "cmF0" },
+ { "raw", "cmF3" },
+ { "ray", "cmF5" },
+ { "RCA", "UkNB" },
+ { "R&D", "UiZE" },
+ { "reb", "cmVi" },
+ { "red", "cmVk" },
+ { "rep", "cmVw" },
+ { "ret", "cmV0" },
+ { "rev", "cmV2" },
+ { "Rex", "UmV4" },
+ { "rho", "cmhv" },
+ { "rib", "cmli" },
+ { "rid", "cmlk" },
+ { "rig", "cmln" },
+ { "rim", "cmlt" },
+ { "Rio", "Umlv" },
+ { "rip", "cmlw" },
+ { "RNA", "Uk5B" },
+ { "rob", "cm9i" },
+ { "rod", "cm9k" },
+ { "roe", "cm9l" },
+ { "Ron", "Um9u" },
+ { "rot", "cm90" },
+ { "row", "cm93" },
+ { "Roy", "Um95" },
+ { "RPM", "UlBN" },
+ { "r's", "cidz" },
+ { "rub", "cnVi" },
+ { "rue", "cnVl" },
+ { "rug", "cnVn" },
+ { "rum", "cnVt" },
+ { "run", "cnVu" },
+ { "rut", "cnV0" },
+ { "rye", "cnll" },
+ { "sac", "c2Fj" },
+ { "sad", "c2Fk" },
+ { "sag", "c2Fn" },
+ { "Sal", "U2Fs" },
+ { "Sam", "U2Ft" },
+ { "San", "U2Fu" },
+ { "Sao", "U2Fv" },
+ { "sap", "c2Fw" },
+ { "sat", "c2F0" },
+ { "saw", "c2F3" },
+ { "sax", "c2F4" },
+ { "say", "c2F5" },
+ { "Sci", "U2Np" },
+ { "SCM", "U0NN" },
+ { "sea", "c2Vh" },
+ { "sec", "c2Vj" },
+ { "see", "c2Vl" },
+ { "sen", "c2Vu" },
+ { "seq", "c2Vx" },
+ { "set", "c2V0" },
+ { "sew", "c2V3" },
+ { "sex", "c2V4" },
+ { "she", "c2hl" },
+ { "Shu", "U2h1" },
+ { "shy", "c2h5" },
+ { "sib", "c2li" },
+ { "sic", "c2lj" },
+ { "sin", "c2lu" },
+ { "sip", "c2lw" },
+ { "sir", "c2ly" },
+ { "sis", "c2lz" },
+ { "sit", "c2l0" },
+ { "six", "c2l4" },
+ { "ski", "c2tp" },
+ { "sky", "c2t5" },
+ { "sly", "c2x5" },
+ { "sob", "c29i" },
+ { "Soc", "U29j" },
+ { "sod", "c29k" },
+ { "Sol", "U29s" },
+ { "son", "c29u" },
+ { "sop", "c29w" },
+ { "sou", "c291" },
+ { "sow", "c293" },
+ { "soy", "c295" },
+ { "spa", "c3Bh" },
+ { "spy", "c3B5" },
+ { "Sri", "U3Jp" },
+ { "s's", "cydz" },
+ { "SSE", "U1NF" },
+ { "SST", "U1NU" },
+ { "SSW", "U1NX" },
+ { "Stu", "U3R1" },
+ { "sub", "c3Vi" },
+ { "sud", "c3Vk" },
+ { "sue", "c3Vl" },
+ { "sum", "c3Vt" },
+ { "sun", "c3Vu" },
+ { "sup", "c3Vw" },
+ { "Sus", "U3Vz" },
+ { "tab", "dGFi" },
+ { "tad", "dGFk" },
+ { "tag", "dGFn" },
+ { "tam", "dGFt" },
+ { "tan", "dGFu" },
+ { "tao", "dGFv" },
+ { "tap", "dGFw" },
+ { "tar", "dGFy" },
+ { "tat", "dGF0" },
+ { "tau", "dGF1" },
+ { "tax", "dGF4" },
+ { "tea", "dGVh" },
+ { "Ted", "VGVk" },
+ { "ted", "dGVk" },
+ { "tee", "dGVl" },
+ { "Tel", "VGVs" },
+ { "ten", "dGVu" },
+ { "the", "dGhl" },
+ { "thy", "dGh5" },
+ { "tic", "dGlj" },
+ { "tid", "dGlk" },
+ { "tie", "dGll" },
+ { "til", "dGls" },
+ { "Tim", "VGlt" },
+ { "tin", "dGlu" },
+ { "tip", "dGlw" },
+ { "tit", "dGl0" },
+ { "TNT", "VE5U" },
+ { "toe", "dG9l" },
+ { "tog", "dG9n" },
+ { "Tom", "VG9t" },
+ { "ton", "dG9u" },
+ { "too", "dG9v" },
+ { "top", "dG9w" },
+ { "tor", "dG9y" },
+ { "tot", "dG90" },
+ { "tow", "dG93" },
+ { "toy", "dG95" },
+ { "TRW", "VFJX" },
+ { "try", "dHJ5" },
+ { "t's", "dCdz" },
+ { "TTL", "VFRM" },
+ { "TTY", "VFRZ" },
+ { "tub", "dHVi" },
+ { "tug", "dHVn" },
+ { "tum", "dHVt" },
+ { "tun", "dHVu" },
+ { "TVA", "VFZB" },
+ { "TWA", "VFdB" },
+ { "two", "dHdv" },
+ { "TWX", "VFdY" },
+ { "ugh", "dWdo" },
+ { "UHF", "VUhG" },
+ { "Uri", "VXJp" },
+ { "urn", "dXJu" },
+ { "U.S", "VS5T" },
+ { "u's", "dSdz" },
+ { "USA", "VVNB" },
+ { "USC", "VVND" },
+ { "use", "dXNl" },
+ { "USN", "VVNO" },
+ { "van", "dmFu" },
+ { "vat", "dmF0" },
+ { "vee", "dmVl" },
+ { "vet", "dmV0" },
+ { "vex", "dmV4" },
+ { "VHF", "VkhG" },
+ { "via", "dmlh" },
+ { "vie", "dmll" },
+ { "vii", "dmlp" },
+ { "vis", "dmlz" },
+ { "viz", "dml6" },
+ { "von", "dm9u" },
+ { "vow", "dm93" },
+ { "v's", "didz" },
+ { "WAC", "V0FD" },
+ { "wad", "d2Fk" },
+ { "wag", "d2Fn" },
+ { "wah", "d2Fo" },
+ { "wan", "d2Fu" },
+ { "war", "d2Fy" },
+ { "was", "d2Fz" },
+ { "wax", "d2F4" },
+ { "way", "d2F5" },
+ { "web", "d2Vi" },
+ { "wed", "d2Vk" },
+ { "wee", "d2Vl" },
+ { "Wei", "V2Vp" },
+ { "wet", "d2V0" },
+ { "who", "d2hv" },
+ { "why", "d2h5" },
+ { "wig", "d2ln" },
+ { "win", "d2lu" },
+ { "wit", "d2l0" },
+ { "woe", "d29l" },
+ { "wok", "d29r" },
+ { "won", "d29u" },
+ { "woo", "d29v" },
+ { "wop", "d29w" },
+ { "wow", "d293" },
+ { "wry", "d3J5" },
+ { "w's", "dydz" },
+ { "x's", "eCdz" },
+ { "yah", "eWFo" },
+ { "yak", "eWFr" },
+ { "yam", "eWFt" },
+ { "yap", "eWFw" },
+ { "yaw", "eWF3" },
+ { "yea", "eWVh" },
+ { "yen", "eWVu" },
+ { "yet", "eWV0" },
+ { "yin", "eWlu" },
+ { "yip", "eWlw" },
+ { "yon", "eW9u" },
+ { "you", "eW91" },
+ { "yow", "eW93" },
+ { "y's", "eSdz" },
+ { "yuh", "eXVo" },
+ { "zag", "emFn" },
+ { "Zan", "WmFu" },
+ { "zap", "emFw" },
+ { "Zen", "WmVu" },
+ { "zig", "emln" },
+ { "zip", "emlw" },
+ { "Zoe", "Wm9l" },
+ { "zoo", "em9v" },
+ { "z's", "eidz" },
+ /* the false rumors file */
+ { "\"So when I die, the first thing I will see in heaven is a score list?\"",
+ "IlNvIHdoZW4gSSBkaWUsIHRoZSBmaXJzdCB0aGluZyBJIHdpbGwgc2VlIGluIGhlYXZlbiBpcyBhIHNjb3JlIGxpc3Q/Ig=="
+ },
+ { "1st Law of Hacking: leaving is much more difficult than entering.",
+ "MXN0IExhdyBvZiBIYWNraW5nOiBsZWF2aW5nIGlzIG11Y2ggbW9yZSBkaWZmaWN1bHQgdGhhbiBlbnRlcmluZy4="
+ },
+ { "2nd Law of Hacking: first in, first out.",
+ "Mm5kIExhdyBvZiBIYWNraW5nOiBmaXJzdCBpbiwgZmlyc3Qgb3V0Lg=="
+ },
+ { "3rd Law of Hacking: the last blow counts most.",
+ "M3JkIExhdyBvZiBIYWNraW5nOiB0aGUgbGFzdCBibG93IGNvdW50cyBtb3N0Lg=="
+ },
+ { "4th Law of Hacking: you will find the exit at the entrance.",
+ "NHRoIExhdyBvZiBIYWNraW5nOiB5b3Ugd2lsbCBmaW5kIHRoZSBleGl0IGF0IHRoZSBlbnRyYW5jZS4="
+ },
+ { "A chameleon imitating a mail daemon often delivers scrolls of fire.",
+ "QSBjaGFtZWxlb24gaW1pdGF0aW5nIGEgbWFpbCBkYWVtb24gb2Z0ZW4gZGVsaXZlcnMgc2Nyb2xscyBvZiBmaXJlLg=="
+ },
+ { "A cockatrice corpse is guaranteed to be untainted!",
+ "QSBjb2NrYXRyaWNlIGNvcnBzZSBpcyBndWFyYW50ZWVkIHRvIGJlIHVudGFpbnRlZCE="
+ },
+ { "A dead cockatrice is just a dead lizard.",
+ "QSBkZWFkIGNvY2thdHJpY2UgaXMganVzdCBhIGRlYWQgbGl6YXJkLg=="
+ },
+ { "A dragon is just a snake that ate a scroll of fire.",
+ "QSBkcmFnb24gaXMganVzdCBhIHNuYWtlIHRoYXQgYXRlIGEgc2Nyb2xsIG9mIGZpcmUu"
+ },
+ { "A fading corridor enlightens your insight.",
+ "QSBmYWRpbmcgY29ycmlkb3IgZW5saWdodGVucyB5b3VyIGluc2lnaHQu"
+ },
+ { "A glowing potion is too hot to drink.",
+ "QSBnbG93aW5nIHBvdGlvbiBpcyB0b28gaG90IHRvIGRyaW5rLg=="
+ },
+ { "A good amulet may protect you against guards.",
+ "QSBnb29kIGFtdWxldCBtYXkgcHJvdGVjdCB5b3UgYWdhaW5zdCBndWFyZHMu"
+ },
+ { "A lizard corpse is a good thing to turn undead.",
+ "QSBsaXphcmQgY29ycHNlIGlzIGEgZ29vZCB0aGluZyB0byB0dXJuIHVuZGVhZC4="
+ },
+ { "A long worm can be defined recursively. So how should you attack it?",
+ "QSBsb25nIHdvcm0gY2FuIGJlIGRlZmluZWQgcmVjdXJzaXZlbHkuIFNvIGhvdyBzaG91bGQgeW91IGF0dGFjayBpdD8="
+ },
+ { "A monstrous mind is a toy forever.",
+ "QSBtb25zdHJvdXMgbWluZCBpcyBhIHRveSBmb3JldmVyLg=="
+ },
+ { "A nymph will be very pleased if you call her by her real name: Lorelei.",
+ "QSBueW1waCB3aWxsIGJlIHZlcnkgcGxlYXNlZCBpZiB5b3UgY2FsbCBoZXIgYnkgaGVyIHJlYWwgbmFtZTogTG9yZWxlaS4="
+ },
+ { "A ring of dungeon master control is a great find.",
+ "QSByaW5nIG9mIGR1bmdlb24gbWFzdGVyIGNvbnRyb2wgaXMgYSBncmVhdCBmaW5kLg=="
+ },
+ { "A ring of extra ring finger is useless if not enchanted.",
+ "QSByaW5nIG9mIGV4dHJhIHJpbmcgZmluZ2VyIGlzIHVzZWxlc3MgaWYgbm90IGVuY2hhbnRlZC4="
+ },
+ { "A rope may form a trail in a maze.",
+ "QSByb3BlIG1heSBmb3JtIGEgdHJhaWwgaW4gYSBtYXplLg=="
+ },
+ { "A staff may recharge if you drop it for awhile.",
+ "QSBzdGFmZiBtYXkgcmVjaGFyZ2UgaWYgeW91IGRyb3AgaXQgZm9yIGF3aGlsZS4="
+ },
+ { "A visit to the Zoo is very educational; you meet interesting animals.",
+ "QSB2aXNpdCB0byB0aGUgWm9vIGlzIHZlcnkgZWR1Y2F0aW9uYWw7IHlvdSBtZWV0IGludGVyZXN0aW5nIGFuaW1hbHMu"
+ },
+ { "A wand of deaf is a more dangerous weapon than a wand of sheep.",
+ "QSB3YW5kIG9mIGRlYWYgaXMgYSBtb3JlIGRhbmdlcm91cyB3ZWFwb24gdGhhbiBhIHdhbmQgb2Ygc2hlZXAu"
+ },
+ { "A wand of vibration might bring the whole cave crashing about your ears.",
+ "QSB3YW5kIG9mIHZpYnJhdGlvbiBtaWdodCBicmluZyB0aGUgd2hvbGUgY2F2ZSBjcmFzaGluZyBhYm91dCB5b3VyIGVhcnMu"
+ },
+ { "A winner never quits. A quitter never wins.",
+ "QSB3aW5uZXIgbmV2ZXIgcXVpdHMuIEEgcXVpdHRlciBuZXZlciB3aW5zLg=="
+ },
+ { "A wish? Okay, make me a fortune cookie!",
+ "QSB3aXNoPyBPa2F5LCBtYWtlIG1lIGEgZm9ydHVuZSBjb29raWUh"
+ },
+ { "Afraid of mimics? Try to wear a ring of true seeing.",
+ "QWZyYWlkIG9mIG1pbWljcz8gVHJ5IHRvIHdlYXIgYSByaW5nIG9mIHRydWUgc2VlaW5nLg=="
+ },
+ { "All monsters are created evil, but some are more evil than others.",
+ "QWxsIG1vbnN0ZXJzIGFyZSBjcmVhdGVkIGV2aWwsIGJ1dCBzb21lIGFyZSBtb3JlIGV2aWwgdGhhbiBvdGhlcnMu"
+ },
+ { "Always attack a floating eye from behind!",
+ "QWx3YXlzIGF0dGFjayBhIGZsb2F0aW5nIGV5ZSBmcm9tIGJlaGluZCE="
+ },
+ { "An elven cloak is always the height of fashion.",
+ "QW4gZWx2ZW4gY2xvYWsgaXMgYWx3YXlzIHRoZSBoZWlnaHQgb2YgZmFzaGlvbi4="
+ },
+ { "Any small object that is accidentally dropped will hide under a larger object.",
+ "QW55IHNtYWxsIG9iamVjdCB0aGF0IGlzIGFjY2lkZW50YWxseSBkcm9wcGVkIHdpbGwgaGlkZSB1bmRlciBhIGxhcmdlciBvYmplY3Qu"
+ },
+ { "Balrogs do not appear above level 20.",
+ "QmFscm9ncyBkbyBub3QgYXBwZWFyIGFib3ZlIGxldmVsIDIwLg=="
+ },
+ { "Banana peels work especially well against Keystone Kops.",
+ "QmFuYW5hIHBlZWxzIHdvcmsgZXNwZWNpYWxseSB3ZWxsIGFnYWluc3QgS2V5c3RvbmUgS29wcy4="
+ },
+ { "Be careful when eating bananas. Monsters might slip on the peels.",
+ "QmUgY2FyZWZ1bCB3aGVuIGVhdGluZyBiYW5hbmFzLiBNb25zdGVycyBtaWdodCBzbGlwIG9uIHRoZSBwZWVscy4="
+ },
+ { "Better leave the dungeon; otherwise you might get hurt badly.",
+ "QmV0dGVyIGxlYXZlIHRoZSBkdW5nZW9uOyBvdGhlcndpc2UgeW91IG1pZ2h0IGdldCBodXJ0IGJhZGx5Lg=="
+ },
+ { "Beware of the potion of nitroglycerin -- it's not for the weak of heart.",
+ "QmV3YXJlIG9mIHRoZSBwb3Rpb24gb2Ygbml0cm9nbHljZXJpbiAtLSBpdCdzIG5vdCBmb3IgdGhlIHdlYWsgb2YgaGVhcnQu"
+ },
+ { "Beware: there's always a chance that your wand explodes as you try to zap it!",
+ "QmV3YXJlOiB0aGVyZSdzIGFsd2F5cyBhIGNoYW5jZSB0aGF0IHlvdXIgd2FuZCBleHBsb2RlcyBhcyB5b3UgdHJ5IHRvIHphcCBpdCE="
+ },
+ { "Beyond the 23rd level lies a happy retirement in a room of your own.",
+ "QmV5b25kIHRoZSAyM3JkIGxldmVsIGxpZXMgYSBoYXBweSByZXRpcmVtZW50IGluIGEgcm9vbSBvZiB5b3VyIG93bi4="
+ },
+ { "Changing your suit without dropping your sword? You must be kidding!",
+ "Q2hhbmdpbmcgeW91ciBzdWl0IHdpdGhvdXQgZHJvcHBpbmcgeW91ciBzd29yZD8gWW91IG11c3QgYmUga2lkZGluZyE="
+ },
+ { "Cockatrices might turn themselves to stone faced with a mirror.",
+ "Q29ja2F0cmljZXMgbWlnaHQgdHVybiB0aGVtc2VsdmVzIHRvIHN0b25lIGZhY2VkIHdpdGggYSBtaXJyb3Iu"
+ },
+ { "Consumption of home-made food is strictly forbidden in this dungeon.",
+ "Q29uc3VtcHRpb24gb2YgaG9tZS1tYWRlIGZvb2QgaXMgc3RyaWN0bHkgZm9yYmlkZGVuIGluIHRoaXMgZHVuZ2Vvbi4="
+ },
+ { "Dark room? Your chance to develop your photographs!",
+ "RGFyayByb29tPyBZb3VyIGNoYW5jZSB0byBkZXZlbG9wIHlvdXIgcGhvdG9ncmFwaHMh"
+ },
+ { "Dark rooms are not *completely* dark: just wait and let your eyes adjust...",
+ "RGFyayByb29tcyBhcmUgbm90ICpjb21wbGV0ZWx5KiBkYXJrOiBqdXN0IHdhaXQgYW5kIGxldCB5b3VyIGV5ZXMgYWRqdXN0Li4u"
+ },
+ { "David London sez, \"Hey guys, *WIELD* a lizard corpse against a cockatrice!\"",
+ "RGF2aWQgTG9uZG9uIHNleiwgIkhleSBndXlzLCAqV0lFTEQqIGEgbGl6YXJkIGNvcnBzZSBhZ2FpbnN0IGEgY29ja2F0cmljZSEi"
+ },
+ { "Death is just life's way of telling you you've been fired.",
+ "RGVhdGggaXMganVzdCBsaWZlJ3Mgd2F5IG9mIHRlbGxpbmcgeW91IHlvdSd2ZSBiZWVuIGZpcmVkLg=="
+ },
+ { "Demi-gods don't need any help from the gods.",
+ "RGVtaS1nb2RzIGRvbid0IG5lZWQgYW55IGhlbHAgZnJvbSB0aGUgZ29kcy4="
+ },
+ { "Demons *HATE* Priests and Priestesses.",
+ "RGVtb25zICpIQVRFKiBQcmllc3RzIGFuZCBQcmllc3Rlc3Nlcy4="
+ },
+ { "Didn't you forget to pay?",
+ "RGlkbid0IHlvdSBmb3JnZXQgdG8gcGF5Pw=="
+ },
+ { "Didn't your mother tell you not to eat food off the floor?",
+ "RGlkbid0IHlvdXIgbW90aGVyIHRlbGwgeW91IG5vdCB0byBlYXQgZm9vZCBvZmYgdGhlIGZsb29yPw=="
+ },
+ { "Direct a direct hit on your direct opponent, directing in the right direction.",
+ "RGlyZWN0IGEgZGlyZWN0IGhpdCBvbiB5b3VyIGRpcmVjdCBvcHBvbmVudCwgZGlyZWN0aW5nIGluIHRoZSByaWdodCBkaXJlY3Rpb24u"
+ },
+ { "Do you want to make more money? Sure, we all do! Join the Fort Ludios guard!",
+ "RG8geW91IHdhbnQgdG8gbWFrZSBtb3JlIG1vbmV5PyBTdXJlLCB3ZSBhbGwgZG8hIEpvaW4gdGhlIEZvcnQgTHVkaW9zIGd1YXJkIQ=="
+ },
+ { "Don't eat too much: you might start hiccoughing!",
+ "RG9uJ3QgZWF0IHRvbyBtdWNoOiB5b3UgbWlnaHQgc3RhcnQgaGljY291Z2hpbmch"
+ },
+ { "Don't play hack at your work; your boss might hit you!",
+ "RG9uJ3QgcGxheSBoYWNrIGF0IHlvdXIgd29yazsgeW91ciBib3NzIG1pZ2h0IGhpdCB5b3Uh"
+ },
+ { "Don't tell a soul you found a secret door, otherwise it isn't a secret anymore.",
+ "RG9uJ3QgdGVsbCBhIHNvdWwgeW91IGZvdW5kIGEgc2VjcmV0IGRvb3IsIG90aGVyd2lzZSBpdCBpc24ndCBhIHNlY3JldCBhbnltb3JlLg=="
+ },
+ { "Drinking potions of booze may land you in jail if you are under 21.",
+ "RHJpbmtpbmcgcG90aW9ucyBvZiBib296ZSBtYXkgbGFuZCB5b3UgaW4gamFpbCBpZiB5b3UgYXJlIHVuZGVyIDIxLg=="
+ },
+ { "Drop your vanity and get rid of your jewels! Pickpockets about!",
+ "RHJvcCB5b3VyIHZhbml0eSBhbmQgZ2V0IHJpZCBvZiB5b3VyIGpld2VscyEgUGlja3BvY2tldHMgYWJvdXQh"
+ },
+ { "Eat 10 cloves of garlic and keep all humans at a two-square distance.",
+ "RWF0IDEwIGNsb3ZlcyBvZiBnYXJsaWMgYW5kIGtlZXAgYWxsIGh1bWFucyBhdCBhIHR3by1zcXVhcmUgZGlzdGFuY2Uu"
+ },
+ { "Eels hide under mud. Use a unicorn to clear the water and make them visible.",
+ "RWVscyBoaWRlIHVuZGVyIG11ZC4gVXNlIGEgdW5pY29ybiB0byBjbGVhciB0aGUgd2F0ZXIgYW5kIG1ha2UgdGhlbSB2aXNpYmxlLg=="
+ },
+ { "Engrave your wishes with a wand of wishing.",
+ "RW5ncmF2ZSB5b3VyIHdpc2hlcyB3aXRoIGEgd2FuZCBvZiB3aXNoaW5nLg=="
+ },
+ { "Eventually you will come to admire the swift elegance of a retreating nymph.",
+ "RXZlbnR1YWxseSB5b3Ugd2lsbCBjb21lIHRvIGFkbWlyZSB0aGUgc3dpZnQgZWxlZ2FuY2Ugb2YgYSByZXRyZWF0aW5nIG55bXBoLg=="
+ },
+ { "Ever heard hissing outside? I *knew* you hadn't!",
+ "RXZlciBoZWFyZCBoaXNzaW5nIG91dHNpZGU/IEkgKmtuZXcqIHlvdSBoYWRuJ3Qh"
+ },
+ { "Ever lifted a dragon corpse?",
+ "RXZlciBsaWZ0ZWQgYSBkcmFnb24gY29ycHNlPw=="
+ },
+ { "Ever seen a leocrotta dancing the tengu?",
+ "RXZlciBzZWVuIGEgbGVvY3JvdHRhIGRhbmNpbmcgdGhlIHRlbmd1Pw=="
+ },
+ { "Ever seen your weapon glow plaid?",
+ "RXZlciBzZWVuIHlvdXIgd2VhcG9uIGdsb3cgcGxhaWQ/"
+ },
+ { "Ever tamed a shopkeeper?",
+ "RXZlciB0YW1lZCBhIHNob3BrZWVwZXI/"
+ },
+ { "Ever tried digging through a Vault Guard?",
+ "RXZlciB0cmllZCBkaWdnaW5nIHRocm91Z2ggYSBWYXVsdCBHdWFyZD8="
+ },
+ { "Ever tried enchanting a rope?",
+ "RXZlciB0cmllZCBlbmNoYW50aW5nIGEgcm9wZT8="
+ },
+ { "Floating eyes can't stand Hawaiian shirts.",
+ "RmxvYXRpbmcgZXllcyBjYW4ndCBzdGFuZCBIYXdhaWlhbiBzaGlydHMu"
+ },
+ { "For any remedy there is a misery.",
+ "Rm9yIGFueSByZW1lZHkgdGhlcmUgaXMgYSBtaXNlcnku"
+ },
+ { "Giant bats turn into giant vampires.",
+ "R2lhbnQgYmF0cyB0dXJuIGludG8gZ2lhbnQgdmFtcGlyZXMu"
+ },
+ { "Good day for overcoming obstacles. Try a steeplechase.",
+ "R29vZCBkYXkgZm9yIG92ZXJjb21pbmcgb2JzdGFjbGVzLiBUcnkgYSBzdGVlcGxlY2hhc2Uu"
+ },
+ { "Half Moon tonight. (At least it's better than no Moon at all.)",
+ "SGFsZiBNb29uIHRvbmlnaHQuIChBdCBsZWFzdCBpdCdzIGJldHRlciB0aGFuIG5vIE1vb24gYXQgYWxsLik="
+ },
+ { "Help! I'm being held prisoner in a fortune cookie factory!",
+ "SGVscCEgSSdtIGJlaW5nIGhlbGQgcHJpc29uZXIgaW4gYSBmb3J0dW5lIGNvb2tpZSBmYWN0b3J5IQ=="
+ },
+ { "Housecats have nine lives, kittens only one.",
+ "SG91c2VjYXRzIGhhdmUgbmluZSBsaXZlcywga2l0dGVucyBvbmx5IG9uZS4="
+ },
+ { "How long can you tread water?",
+ "SG93IGxvbmcgY2FuIHlvdSB0cmVhZCB3YXRlcj8="
+ },
+ { "Hungry? There is an abundance of food on the next level.",
+ "SHVuZ3J5PyBUaGVyZSBpcyBhbiBhYnVuZGFuY2Ugb2YgZm9vZCBvbiB0aGUgbmV4dCBsZXZlbC4="
+ },
+ { "I guess you've never hit a mail daemon with the Amulet of Yendor...",
+ "SSBndWVzcyB5b3UndmUgbmV2ZXIgaGl0IGEgbWFpbCBkYWVtb24gd2l0aCB0aGUgQW11bGV0IG9mIFllbmRvci4uLg=="
+ },
+ { "If you are the shopkeeper, you can take things for free.",
+ "SWYgeW91IGFyZSB0aGUgc2hvcGtlZXBlciwgeW91IGNhbiB0YWtlIHRoaW5ncyBmb3IgZnJlZS4="
+ },
+ { "If you can't learn to do it well, learn to enjoy doing it badly.",
+ "SWYgeW91IGNhbid0IGxlYXJuIHRvIGRvIGl0IHdlbGwsIGxlYXJuIHRvIGVuam95IGRvaW5nIGl0IGJhZGx5Lg=="
+ },
+ { "If you thought the Wizard was bad, just wait till you meet the Warlord!",
+ "SWYgeW91IHRob3VnaHQgdGhlIFdpemFyZCB3YXMgYmFkLCBqdXN0IHdhaXQgdGlsbCB5b3UgbWVldCB0aGUgV2FybG9yZCE="
+ },
+ { "If you turn blind, don't expect your dog to be turned into a seeing-eye dog.",
+ "SWYgeW91IHR1cm4gYmxpbmQsIGRvbid0IGV4cGVjdCB5b3VyIGRvZyB0byBiZSB0dXJuZWQgaW50byBhIHNlZWluZy1leWUgZG9nLg=="
+ },
+ { "If you want to feel great, you must eat something real big.",
+ "SWYgeW91IHdhbnQgdG8gZmVlbCBncmVhdCwgeW91IG11c3QgZWF0IHNvbWV0aGluZyByZWFsIGJpZy4="
+ },
+ { "If you want to float, you'd better eat a floating eye.",
+ "SWYgeW91IHdhbnQgdG8gZmxvYXQsIHlvdSdkIGJldHRlciBlYXQgYSBmbG9hdGluZyBleWUu"
+ },
+ { "If your ghost kills a player, it increases your score.",
+ "SWYgeW91ciBnaG9zdCBraWxscyBhIHBsYXllciwgaXQgaW5jcmVhc2VzIHlvdXIgc2NvcmUu"
+ },
+ { "Increase mindpower: Tame your own ghost!",
+ "SW5jcmVhc2UgbWluZHBvd2VyOiBUYW1lIHlvdXIgb3duIGdob3N0IQ=="
+ },
+ { "It furthers one to see the great man.",
+ "SXQgZnVydGhlcnMgb25lIHRvIHNlZSB0aGUgZ3JlYXQgbWFuLg=="
+ },
+ { "It's easy to overlook a monster in a wood.",
+ "SXQncyBlYXN5IHRvIG92ZXJsb29rIGEgbW9uc3RlciBpbiBhIHdvb2Qu"
+ },
+ { "Just below any trapdoor there may be another one. Just keep falling!",
+ "SnVzdCBiZWxvdyBhbnkgdHJhcGRvb3IgdGhlcmUgbWF5IGJlIGFub3RoZXIgb25lLiBKdXN0IGtlZXAgZmFsbGluZyE="
+ },
+ { "Katanas are very sharp; watch you don't cut yourself.",
+ "S2F0YW5hcyBhcmUgdmVyeSBzaGFycDsgd2F0Y2ggeW91IGRvbid0IGN1dCB5b3Vyc2VsZi4="
+ },
+ { "Keep a clear mind: quaff clear potions.",
+ "S2VlcCBhIGNsZWFyIG1pbmQ6IHF1YWZmIGNsZWFyIHBvdGlvbnMu"
+ },
+ { "Kicking the terminal doesn't hurt the monsters.",
+ "S2lja2luZyB0aGUgdGVybWluYWwgZG9lc24ndCBodXJ0IHRoZSBtb25zdGVycy4="
+ },
+ { "Killer bees keep appearing till you kill their queen.",
+ "S2lsbGVyIGJlZXMga2VlcCBhcHBlYXJpbmcgdGlsbCB5b3Uga2lsbCB0aGVpciBxdWVlbi4="
+ },
+ { "Killer bunnies can be tamed with carrots only.",
+ "S2lsbGVyIGJ1bm5pZXMgY2FuIGJlIHRhbWVkIHdpdGggY2Fycm90cyBvbmx5Lg=="
+ },
+ { "Latest news? Put `rec.games.roguelike.nethack' in your .newsrc!",
+ "TGF0ZXN0IG5ld3M/IFB1dCBgcmVjLmdhbWVzLnJvZ3VlbGlrZS5uZXRoYWNrJyBpbiB5b3VyIC5uZXdzcmMh"
+ },
+ { "Learn how to spell. Play NetHack!",
+ "TGVhcm4gaG93IHRvIHNwZWxsLiBQbGF5IE5ldEhhY2sh"
+ },
+ { "Leprechauns hide their gold in a secret room.",
+ "TGVwcmVjaGF1bnMgaGlkZSB0aGVpciBnb2xkIGluIGEgc2VjcmV0IHJvb20u"
+ },
+ { "Let your fingers do the walking on the yulkjhnb keys.",
+ "TGV0IHlvdXIgZmluZ2VycyBkbyB0aGUgd2Fsa2luZyBvbiB0aGUgeXVsa2pobmIga2V5cy4="
+ },
+ { "Let's face it: this time you're not going to win.",
+ "TGV0J3MgZmFjZSBpdDogdGhpcyB0aW1lIHlvdSdyZSBub3QgZ29pbmcgdG8gd2luLg=="
+ },
+ { "Let's have a party, drink a lot of booze.",
+ "TGV0J3MgaGF2ZSBhIHBhcnR5LCBkcmluayBhIGxvdCBvZiBib296ZS4="
+ },
+ { "Liquor sellers do not drink; they hate to see you twice.",
+ "TGlxdW9yIHNlbGxlcnMgZG8gbm90IGRyaW5rOyB0aGV5IGhhdGUgdG8gc2VlIHlvdSB0d2ljZS4="
+ },
+ { "Lunar eclipse tonight. May as well quit now!",
+ "THVuYXIgZWNsaXBzZSB0b25pZ2h0LiBNYXkgYXMgd2VsbCBxdWl0IG5vdyE="
+ },
+ { "Meeting your own ghost decreases your luck considerably!",
+ "TWVldGluZyB5b3VyIG93biBnaG9zdCBkZWNyZWFzZXMgeW91ciBsdWNrIGNvbnNpZGVyYWJseSE="
+ },
+ { "Money to invest? Take it to the local branch of the Magic Memory Vault!",
+ "TW9uZXkgdG8gaW52ZXN0PyBUYWtlIGl0IHRvIHRoZSBsb2NhbCBicmFuY2ggb2YgdGhlIE1hZ2ljIE1lbW9yeSBWYXVsdCE="
+ },
+ { "Monsters come from nowhere to hit you everywhere.",
+ "TW9uc3RlcnMgY29tZSBmcm9tIG5vd2hlcmUgdG8gaGl0IHlvdSBldmVyeXdoZXJlLg=="
+ },
+ { "Monsters sleep because you are boring, not because they ever get tired.",
+ "TW9uc3RlcnMgc2xlZXAgYmVjYXVzZSB5b3UgYXJlIGJvcmluZywgbm90IGJlY2F1c2UgdGhleSBldmVyIGdldCB0aXJlZC4="
+ },
+ { "Most monsters prefer minced meat. That's why they are hitting you!",
+ "TW9zdCBtb25zdGVycyBwcmVmZXIgbWluY2VkIG1lYXQuIFRoYXQncyB3aHkgdGhleSBhcmUgaGl0dGluZyB5b3Uh"
+ },
+ { "Most of the bugs in NetHack are on the floor.",
+ "TW9zdCBvZiB0aGUgYnVncyBpbiBOZXRIYWNrIGFyZSBvbiB0aGUgZmxvb3Iu"
+ },
+ { "Much ado Nothing Happens.",
+ "TXVjaCBhZG8gTm90aGluZyBIYXBwZW5zLg=="
+ },
+ { "Multi-player NetHack is a myth.",
+ "TXVsdGktcGxheWVyIE5ldEhhY2sgaXMgYSBteXRoLg=="
+ },
+ { "NetHack is addictive. Too late, you're already hooked.",
+ "TmV0SGFjayBpcyBhZGRpY3RpdmUuIFRvbyBsYXRlLCB5b3UncmUgYWxyZWFkeSBob29rZWQu"
+ },
+ { "Never ask a shopkeeper for a price list.",
+ "TmV2ZXIgYXNrIGEgc2hvcGtlZXBlciBmb3IgYSBwcmljZSBsaXN0Lg=="
+ },
+ { "Never burn a tree, unless you like getting whacked with a +5 shovel.",
+ "TmV2ZXIgYnVybiBhIHRyZWUsIHVubGVzcyB5b3UgbGlrZSBnZXR0aW5nIHdoYWNrZWQgd2l0aCBhICs1IHNob3ZlbC4="
+ },
+ { "Never eat with glowing hands!",
+ "TmV2ZXIgZWF0IHdpdGggZ2xvd2luZyBoYW5kcyE="
+ },
+ { "Never mind the monsters hitting you: they just replace the charwomen.",
+ "TmV2ZXIgbWluZCB0aGUgbW9uc3RlcnMgaGl0dGluZyB5b3U6IHRoZXkganVzdCByZXBsYWNlIHRoZSBjaGFyd29tZW4u"
+ },
+ { "Never play leapfrog with a unicorn.",
+ "TmV2ZXIgcGxheSBsZWFwZnJvZyB3aXRoIGEgdW5pY29ybi4="
+ },
+ { "Never step on a cursed engraving.",
+ "TmV2ZXIgc3RlcCBvbiBhIGN1cnNlZCBlbmdyYXZpbmcu"
+ },
+ { "Never swim with a camera: there's nothing to take pictures of.",
+ "TmV2ZXIgc3dpbSB3aXRoIGEgY2FtZXJhOiB0aGVyZSdzIG5vdGhpbmcgdG8gdGFrZSBwaWN0dXJlcyBvZi4="
+ },
+ { "Never teach your pet rust monster to fetch.",
+ "TmV2ZXIgdGVhY2ggeW91ciBwZXQgcnVzdCBtb25zdGVyIHRvIGZldGNoLg=="
+ },
+ { "Never trust a random generator in magic fields.",
+ "TmV2ZXIgdHJ1c3QgYSByYW5kb20gZ2VuZXJhdG9yIGluIG1hZ2ljIGZpZWxkcy4="
+ },
+ { "Never use a wand of death.",
+ "TmV2ZXIgdXNlIGEgd2FuZCBvZiBkZWF0aC4="
+ },
+ { "No level contains two shops. The maze is no level. So...",
+ "Tm8gbGV2ZWwgY29udGFpbnMgdHdvIHNob3BzLiBUaGUgbWF6ZSBpcyBubyBsZXZlbC4gU28uLi4="
+ },
+ { "No part of this fortune may be reproduced, stored in a retrieval system, ...",
+ "Tm8gcGFydCBvZiB0aGlzIGZvcnR1bmUgbWF5IGJlIHJlcHJvZHVjZWQsIHN0b3JlZCBpbiBhIHJldHJpZXZhbCBzeXN0ZW0sIC4uLg=="
+ },
+ { "Not all rumors are as misleading as this one.",
+ "Tm90IGFsbCBydW1vcnMgYXJlIGFzIG1pc2xlYWRpbmcgYXMgdGhpcyBvbmUu"
+ },
+ { "Nymphs and nurses like beautiful rings.",
+ "TnltcGhzIGFuZCBudXJzZXMgbGlrZSBiZWF1dGlmdWwgcmluZ3Mu"
+ },
+ { "Nymphs are blondes. Are you a gentleman?",
+ "TnltcGhzIGFyZSBibG9uZGVzLiBBcmUgeW91IGEgZ2VudGxlbWFuPw=="
+ },
+ { "Offering a unicorn a worthless piece of glass might prove to be fatal!",
+ "T2ZmZXJpbmcgYSB1bmljb3JuIGEgd29ydGhsZXNzIHBpZWNlIG9mIGdsYXNzIG1pZ2h0IHByb3ZlIHRvIGJlIGZhdGFsIQ=="
+ },
+ { "Old hackers never die: young ones do.",
+ "T2xkIGhhY2tlcnMgbmV2ZXIgZGllOiB5b3VuZyBvbmVzIGRvLg=="
+ },
+ { "One has to leave shops before closing time.",
+ "T25lIGhhcyB0byBsZWF2ZSBzaG9wcyBiZWZvcmUgY2xvc2luZyB0aW1lLg=="
+ },
+ { "One homunculus a day keeps the doctor away.",
+ "T25lIGhvbXVuY3VsdXMgYSBkYXkga2VlcHMgdGhlIGRvY3RvciBhd2F5Lg=="
+ },
+ { "One level further down somebody is getting killed, right now.",
+ "T25lIGxldmVsIGZ1cnRoZXIgZG93biBzb21lYm9keSBpcyBnZXR0aW5nIGtpbGxlZCwgcmlnaHQgbm93Lg=="
+ },
+ { "Only a wizard can use a magic whistle.",
+ "T25seSBhIHdpemFyZCBjYW4gdXNlIGEgbWFnaWMgd2hpc3RsZS4="
+ },
+ { "Only adventurers of evil alignment think of killing their dog.",
+ "T25seSBhZHZlbnR1cmVycyBvZiBldmlsIGFsaWdubWVudCB0aGluayBvZiBraWxsaW5nIHRoZWlyIGRvZy4="
+ },
+ { "Only chaotic evils kill sleeping monsters.",
+ "T25seSBjaGFvdGljIGV2aWxzIGtpbGwgc2xlZXBpbmcgbW9uc3RlcnMu"
+ },
+ { "Only real trappers escape traps.",
+ "T25seSByZWFsIHRyYXBwZXJzIGVzY2FwZSB0cmFwcy4="
+ },
+ { "Only real wizards can write scrolls.",
+ "T25seSByZWFsIHdpemFyZHMgY2FuIHdyaXRlIHNjcm9sbHMu"
+ },
+ { "Operation OVERKILL has started now.",
+ "T3BlcmF0aW9uIE9WRVJLSUxMIGhhcyBzdGFydGVkIG5vdy4="
+ },
+ { "PLEASE ignore previous rumor.",
+ "UExFQVNFIGlnbm9yZSBwcmV2aW91cyBydW1vci4="
+ },
+ { "Polymorph into an ettin; meet your opponents face to face to face.",
+ "UG9seW1vcnBoIGludG8gYW4gZXR0aW47IG1lZXQgeW91ciBvcHBvbmVudHMgZmFjZSB0byBmYWNlIHRvIGZhY2Uu"
+ },
+ { "Praying will frighten demons.",
+ "UHJheWluZyB3aWxsIGZyaWdodGVuIGRlbW9ucy4="
+ },
+ { "Row (3x) that boat gently down the stream, Charon (4x), death is but a dream.",
+ "Um93ICgzeCkgdGhhdCBib2F0IGdlbnRseSBkb3duIHRoZSBzdHJlYW0sIENoYXJvbiAoNHgpLCBkZWF0aCBpcyBidXQgYSBkcmVhbS4="
+ },
+ { "Running is good for your legs.",
+ "UnVubmluZyBpcyBnb29kIGZvciB5b3VyIGxlZ3Mu"
+ },
+ { "Screw up your courage! You've screwed up everything else.",
+ "U2NyZXcgdXAgeW91ciBjb3VyYWdlISBZb3UndmUgc2NyZXdlZCB1cCBldmVyeXRoaW5nIGVsc2Uu"
+ },
+ { "Seepage? Leaky pipes? Rising damp? Summon the plumber!",
+ "U2VlcGFnZT8gTGVha3kgcGlwZXM/IFJpc2luZyBkYW1wPyBTdW1tb24gdGhlIHBsdW1iZXIh"
+ },
+ { "Segmentation fault (core dumped).",
+ "U2VnbWVudGF0aW9uIGZhdWx0IChjb3JlIGR1bXBlZCku"
+ },
+ { "Shopkeepers sometimes die from old age.",
+ "U2hvcGtlZXBlcnMgc29tZXRpbWVzIGRpZSBmcm9tIG9sZCBhZ2Uu"
+ },
+ { "Some mazes (especially small ones) have no solutions, says man 6 maze.",
+ "U29tZSBtYXplcyAoZXNwZWNpYWxseSBzbWFsbCBvbmVzKSBoYXZlIG5vIHNvbHV0aW9ucywgc2F5cyBtYW4gNiBtYXplLg=="
+ },
+ { "Some questions the Sphynx asks just *don't* have any answers.",
+ "U29tZSBxdWVzdGlvbnMgdGhlIFNwaHlueCBhc2tzIGp1c3QgKmRvbid0KiBoYXZlIGFueSBhbnN3ZXJzLg=="
+ },
+ { "Sometimes \"mu\" is the answer.",
+ "U29tZXRpbWVzICJtdSIgaXMgdGhlIGFuc3dlci4="
+ },
+ { "Sorry, no fortune this time. Better luck next cookie!",
+ "U29ycnksIG5vIGZvcnR1bmUgdGhpcyB0aW1lLiBCZXR0ZXIgbHVjayBuZXh0IGNvb2tpZSE="
+ },
+ { "Spare your scrolls of make-edible until it's really necessary!",
+ "U3BhcmUgeW91ciBzY3JvbGxzIG9mIG1ha2UtZWRpYmxlIHVudGlsIGl0J3MgcmVhbGx5IG5lY2Vzc2FyeSE="
+ },
+ { "Suddenly, the dungeon will collapse...",
+ "U3VkZGVubHksIHRoZSBkdW5nZW9uIHdpbGwgY29sbGFwc2UuLi4="
+ },
+ { "Taming a mail daemon may cause a system security violation.",
+ "VGFtaW5nIGEgbWFpbCBkYWVtb24gbWF5IGNhdXNlIGEgc3lzdGVtIHNlY3VyaXR5IHZpb2xhdGlvbi4="
+ },
+ { "The crowd was so tough, the Stooges won't play the Dungeon anymore, nyuk nyuk.",
+ "VGhlIGNyb3dkIHdhcyBzbyB0b3VnaCwgdGhlIFN0b29nZXMgd29uJ3QgcGxheSB0aGUgRHVuZ2VvbiBhbnltb3JlLCBueXVrIG55dWsu"
+ },
+ { "The leprechauns hide their treasure in a small hidden room.",
+ "VGhlIGxlcHJlY2hhdW5zIGhpZGUgdGhlaXIgdHJlYXN1cmUgaW4gYSBzbWFsbCBoaWRkZW4gcm9vbS4="
+ },
+ { "The longer the wand the better.",
+ "VGhlIGxvbmdlciB0aGUgd2FuZCB0aGUgYmV0dGVyLg=="
+ },
+ { "The magic word is \"XYZZY\".",
+ "VGhlIG1hZ2ljIHdvcmQgaXMgIlhZWlpZIi4="
+ },
+ { "The meek shall inherit your bones files.",
+ "VGhlIG1lZWsgc2hhbGwgaW5oZXJpdCB5b3VyIGJvbmVzIGZpbGVzLg=="
+ },
+ { "The mines are dark and deep, and I have levels to go before I sleep.",
+ "VGhlIG1pbmVzIGFyZSBkYXJrIGFuZCBkZWVwLCBhbmQgSSBoYXZlIGxldmVscyB0byBnbyBiZWZvcmUgSSBzbGVlcC4="
+ },
+ { "The use of dynamite is dangerous.",
+ "VGhlIHVzZSBvZiBkeW5hbWl0ZSBpcyBkYW5nZXJvdXMu"
+ },
+ { "There are no worms in the UNIX version.",
+ "VGhlcmUgYXJlIG5vIHdvcm1zIGluIHRoZSBVTklYIHZlcnNpb24u"
+ },
+ { "There is a trap on this level!",
+ "VGhlcmUgaXMgYSB0cmFwIG9uIHRoaXMgbGV2ZWwh"
+ },
+ { "They say that Demogorgon, Asmodeus, Orcus, Yeenoghu & Juiblex is no law firm.",
+ "VGhleSBzYXkgdGhhdCBEZW1vZ29yZ29uLCBBc21vZGV1cywgT3JjdXMsIFllZW5vZ2h1ICYgSnVpYmxleCBpcyBubyBsYXcgZmlybS4="
+ },
+ { "They say that Geryon has an evil twin, beware!",
+ "VGhleSBzYXkgdGhhdCBHZXJ5b24gaGFzIGFuIGV2aWwgdHdpbiwgYmV3YXJlIQ=="
+ },
+ { "They say that Medusa would make a terrible pet.",
+ "VGhleSBzYXkgdGhhdCBNZWR1c2Egd291bGQgbWFrZSBhIHRlcnJpYmxlIHBldC4="
+ },
+ { "They say that NetHack bugs are Seldon planned.",
+ "VGhleSBzYXkgdGhhdCBOZXRIYWNrIGJ1Z3MgYXJlIFNlbGRvbiBwbGFubmVkLg=="
+ },
+ { "They say that NetHack comes in 256 flavors.",
+ "VGhleSBzYXkgdGhhdCBOZXRIYWNrIGNvbWVzIGluIDI1NiBmbGF2b3JzLg=="
+ },
+ { "They say that NetHack is just a computer game.",
+ "VGhleSBzYXkgdGhhdCBOZXRIYWNrIGlzIGp1c3QgYSBjb21wdXRlciBnYW1lLg=="
+ },
+ { "They say that NetHack is more than just a computer game.",
+ "VGhleSBzYXkgdGhhdCBOZXRIYWNrIGlzIG1vcmUgdGhhbiBqdXN0IGEgY29tcHV0ZXIgZ2FtZS4="
+ },
+ { "They say that NetHack is never what it used to be.",
+ "VGhleSBzYXkgdGhhdCBOZXRIYWNrIGlzIG5ldmVyIHdoYXQgaXQgdXNlZCB0byBiZS4="
+ },
+ { "They say that a baby dragon is too small to hurt or help you.",
+ "VGhleSBzYXkgdGhhdCBhIGJhYnkgZHJhZ29uIGlzIHRvbyBzbWFsbCB0byBodXJ0IG9yIGhlbHAgeW91Lg=="
+ },
+ { "They say that a black pudding is simply a brown pudding gone bad.",
+ "VGhleSBzYXkgdGhhdCBhIGJsYWNrIHB1ZGRpbmcgaXMgc2ltcGx5IGEgYnJvd24gcHVkZGluZyBnb25lIGJhZC4="
+ },
+ { "They say that a black sheep has 3 bags full of wool.",
+ "VGhleSBzYXkgdGhhdCBhIGJsYWNrIHNoZWVwIGhhcyAzIGJhZ3MgZnVsbCBvZiB3b29sLg=="
+ },
+ { "They say that a blank scroll is like a blank check.",
+ "VGhleSBzYXkgdGhhdCBhIGJsYW5rIHNjcm9sbCBpcyBsaWtlIGEgYmxhbmsgY2hlY2su"
+ },
+ { "They say that a cat named Morris has nine lives.",
+ "VGhleSBzYXkgdGhhdCBhIGNhdCBuYW1lZCBNb3JyaXMgaGFzIG5pbmUgbGl2ZXMu"
+ },
+ { "They say that a desperate shopper might pay any price in a shop.",
+ "VGhleSBzYXkgdGhhdCBhIGRlc3BlcmF0ZSBzaG9wcGVyIG1pZ2h0IHBheSBhbnkgcHJpY2UgaW4gYSBzaG9wLg=="
+ },
+ { "They say that a diamond dog is everybody's best friend.",
+ "VGhleSBzYXkgdGhhdCBhIGRpYW1vbmQgZG9nIGlzIGV2ZXJ5Ym9keSdzIGJlc3QgZnJpZW5kLg=="
+ },
+ { "They say that a dwarf lord can carry a pick-axe because his armor is light.",
+ "VGhleSBzYXkgdGhhdCBhIGR3YXJmIGxvcmQgY2FuIGNhcnJ5IGEgcGljay1heGUgYmVjYXVzZSBoaXMgYXJtb3IgaXMgbGlnaHQu"
+ },
+ { "They say that a floating eye can defeat Medusa.",
+ "VGhleSBzYXkgdGhhdCBhIGZsb2F0aW5nIGV5ZSBjYW4gZGVmZWF0IE1lZHVzYS4="
+ },
+ { "They say that a fortune only has 1 line and you can't read between it.",
+ "VGhleSBzYXkgdGhhdCBhIGZvcnR1bmUgb25seSBoYXMgMSBsaW5lIGFuZCB5b3UgY2FuJ3QgcmVhZCBiZXR3ZWVuIGl0Lg=="
+ },
+ { "They say that a fortune only has 1 line, but you can read between it.",
+ "VGhleSBzYXkgdGhhdCBhIGZvcnR1bmUgb25seSBoYXMgMSBsaW5lLCBidXQgeW91IGNhbiByZWFkIGJldHdlZW4gaXQu"
+ },
+ { "They say that a fountain looks nothing like a regularly erupting geyser.",
+ "VGhleSBzYXkgdGhhdCBhIGZvdW50YWluIGxvb2tzIG5vdGhpbmcgbGlrZSBhIHJlZ3VsYXJseSBlcnVwdGluZyBnZXlzZXIu"
+ },
+ { "They say that a gold doubloon is worth more than its weight in gold.",
+ "VGhleSBzYXkgdGhhdCBhIGdvbGQgZG91Ymxvb24gaXMgd29ydGggbW9yZSB0aGFuIGl0cyB3ZWlnaHQgaW4gZ29sZC4="
+ },
+ { "They say that a grid bug won't pay a shopkeeper for zapping you in a shop.",
+ "VGhleSBzYXkgdGhhdCBhIGdyaWQgYnVnIHdvbid0IHBheSBhIHNob3BrZWVwZXIgZm9yIHphcHBpbmcgeW91IGluIGEgc2hvcC4="
+ },
+ { "They say that a gypsy could tell your fortune for a price.",
+ "VGhleSBzYXkgdGhhdCBhIGd5cHN5IGNvdWxkIHRlbGwgeW91ciBmb3J0dW5lIGZvciBhIHByaWNlLg=="
+ },
+ { "They say that a hacker named Alice once level teleported by using a mirror.",
+ "VGhleSBzYXkgdGhhdCBhIGhhY2tlciBuYW1lZCBBbGljZSBvbmNlIGxldmVsIHRlbGVwb3J0ZWQgYnkgdXNpbmcgYSBtaXJyb3Iu"
+ },
+ { "They say that a hacker named David once slew a giant with a sling and a rock.",
+ "VGhleSBzYXkgdGhhdCBhIGhhY2tlciBuYW1lZCBEYXZpZCBvbmNlIHNsZXcgYSBnaWFudCB3aXRoIGEgc2xpbmcgYW5kIGEgcm9jay4="
+ },
+ { "They say that a hacker named Dorothy once rode a fog cloud to Oz.",
+ "VGhleSBzYXkgdGhhdCBhIGhhY2tlciBuYW1lZCBEb3JvdGh5IG9uY2Ugcm9kZSBhIGZvZyBjbG91ZCB0byBPei4="
+ },
+ { "They say that a hacker named Mary once lost a white sheep in the mazes.",
+ "VGhleSBzYXkgdGhhdCBhIGhhY2tlciBuYW1lZCBNYXJ5IG9uY2UgbG9zdCBhIHdoaXRlIHNoZWVwIGluIHRoZSBtYXplcy4="
+ },
+ { "They say that a helm of brilliance is not to be taken lightly.",
+ "VGhleSBzYXkgdGhhdCBhIGhlbG0gb2YgYnJpbGxpYW5jZSBpcyBub3QgdG8gYmUgdGFrZW4gbGlnaHRseS4="
+ },
+ { "They say that a hot dog and a hell hound are the same thing.",
+ "VGhleSBzYXkgdGhhdCBhIGhvdCBkb2cgYW5kIGEgaGVsbCBob3VuZCBhcmUgdGhlIHNhbWUgdGhpbmcu"
+ },
+ { "They say that a lamp named Aladdin's Lamp contains a djinni with 3 wishes.",
+ "VGhleSBzYXkgdGhhdCBhIGxhbXAgbmFtZWQgQWxhZGRpbidzIExhbXAgY29udGFpbnMgYSBkamlubmkgd2l0aCAzIHdpc2hlcy4="
+ },
+ { "They say that a large dog named Lassie will lead you to the amulet.",
+ "VGhleSBzYXkgdGhhdCBhIGxhcmdlIGRvZyBuYW1lZCBMYXNzaWUgd2lsbCBsZWFkIHlvdSB0byB0aGUgYW11bGV0Lg=="
+ },
+ { "They say that a long sword is not a light sword.",
+ "VGhleSBzYXkgdGhhdCBhIGxvbmcgc3dvcmQgaXMgbm90IGEgbGlnaHQgc3dvcmQu"
+ },
+ { "They say that a manes won't mince words with you.",
+ "VGhleSBzYXkgdGhhdCBhIG1hbmVzIHdvbid0IG1pbmNlIHdvcmRzIHdpdGggeW91Lg=="
+ },
+ { "They say that a mind is a terrible thing to waste.",
+ "VGhleSBzYXkgdGhhdCBhIG1pbmQgaXMgYSB0ZXJyaWJsZSB0aGluZyB0byB3YXN0ZS4="
+ },
+ { "They say that a plain nymph will only wear a wire ring in one ear.",
+ "VGhleSBzYXkgdGhhdCBhIHBsYWluIG55bXBoIHdpbGwgb25seSB3ZWFyIGEgd2lyZSByaW5nIGluIG9uZSBlYXIu"
+ },
+ { "They say that a plumed hat could be a previously used crested helmet.",
+ "VGhleSBzYXkgdGhhdCBhIHBsdW1lZCBoYXQgY291bGQgYmUgYSBwcmV2aW91c2x5IHVzZWQgY3Jlc3RlZCBoZWxtZXQu"
+ },
+ { "They say that a potion of oil is difficult to grasp.",
+ "VGhleSBzYXkgdGhhdCBhIHBvdGlvbiBvZiBvaWwgaXMgZGlmZmljdWx0IHRvIGdyYXNwLg=="
+ },
+ { "They say that a potion of yogurt is a cancelled potion of sickness.",
+ "VGhleSBzYXkgdGhhdCBhIHBvdGlvbiBvZiB5b2d1cnQgaXMgYSBjYW5jZWxsZWQgcG90aW9uIG9mIHNpY2tuZXNzLg=="
+ },
+ { "They say that a purple worm is not a baby purple dragon.",
+ "VGhleSBzYXkgdGhhdCBhIHB1cnBsZSB3b3JtIGlzIG5vdCBhIGJhYnkgcHVycGxlIGRyYWdvbi4="
+ },
+ { "They say that a quivering blob tastes different than a gelatinous cube.",
+ "VGhleSBzYXkgdGhhdCBhIHF1aXZlcmluZyBibG9iIHRhc3RlcyBkaWZmZXJlbnQgdGhhbiBhIGdlbGF0aW5vdXMgY3ViZS4="
+ },
+ { "They say that a runed broadsword named Stormbringer attracts vortices.",
+ "VGhleSBzYXkgdGhhdCBhIHJ1bmVkIGJyb2Fkc3dvcmQgbmFtZWQgU3Rvcm1icmluZ2VyIGF0dHJhY3RzIHZvcnRpY2VzLg=="
+ },
+ { "They say that a scroll of summoning has other names.",
+ "VGhleSBzYXkgdGhhdCBhIHNjcm9sbCBvZiBzdW1tb25pbmcgaGFzIG90aGVyIG5hbWVzLg=="
+ },
+ { "They say that a shaman can bestow blessings but usually doesn't.",
+ "VGhleSBzYXkgdGhhdCBhIHNoYW1hbiBjYW4gYmVzdG93IGJsZXNzaW5ncyBidXQgdXN1YWxseSBkb2Vzbid0Lg=="
+ },
+ { "They say that a shaman will bless you for an eye of newt and wing of bat.",
+ "VGhleSBzYXkgdGhhdCBhIHNoYW1hbiB3aWxsIGJsZXNzIHlvdSBmb3IgYW4gZXllIG9mIG5ld3QgYW5kIHdpbmcgb2YgYmF0Lg=="
+ },
+ { "They say that a shimmering gold shield is not a polished silver shield.",
+ "VGhleSBzYXkgdGhhdCBhIHNoaW1tZXJpbmcgZ29sZCBzaGllbGQgaXMgbm90IGEgcG9saXNoZWQgc2lsdmVyIHNoaWVsZC4="
+ },
+ { "They say that a spear will hit a neo-otyugh. (Do YOU know what that is?)",
+ "VGhleSBzYXkgdGhhdCBhIHNwZWFyIHdpbGwgaGl0IGEgbmVvLW90eXVnaC4gKERvIFlPVSBrbm93IHdoYXQgdGhhdCBpcz8p"
+ },
+ { "They say that a spotted dragon is the ultimate shape changer.",
+ "VGhleSBzYXkgdGhhdCBhIHNwb3R0ZWQgZHJhZ29uIGlzIHRoZSB1bHRpbWF0ZSBzaGFwZSBjaGFuZ2VyLg=="
+ },
+ { "They say that a stethoscope is no good if you can only hear your heartbeat.",
+ "VGhleSBzYXkgdGhhdCBhIHN0ZXRob3Njb3BlIGlzIG5vIGdvb2QgaWYgeW91IGNhbiBvbmx5IGhlYXIgeW91ciBoZWFydGJlYXQu"
+ },
+ { "They say that a succubus named Suzy will sometimes warn you of danger.",
+ "VGhleSBzYXkgdGhhdCBhIHN1Y2N1YnVzIG5hbWVkIFN1enkgd2lsbCBzb21ldGltZXMgd2FybiB5b3Ugb2YgZGFuZ2VyLg=="
+ },
+ { "They say that a wand of cancellation is not like a wand of polymorph.",
+ "VGhleSBzYXkgdGhhdCBhIHdhbmQgb2YgY2FuY2VsbGF0aW9uIGlzIG5vdCBsaWtlIGEgd2FuZCBvZiBwb2x5bW9ycGgu"
+ },
+ { "They say that a wood golem named Pinocchio would be easy to control.",
+ "VGhleSBzYXkgdGhhdCBhIHdvb2QgZ29sZW0gbmFtZWQgUGlub2NjaGlvIHdvdWxkIGJlIGVhc3kgdG8gY29udHJvbC4="
+ },
+ { "They say that after killing a dragon it's time for a change of scenery.",
+ "VGhleSBzYXkgdGhhdCBhZnRlciBraWxsaW5nIGEgZHJhZ29uIGl0J3MgdGltZSBmb3IgYSBjaGFuZ2Ugb2Ygc2NlbmVyeS4="
+ },
+ { "They say that an amulet of strangulation is worse than ring around the collar.",
+ "VGhleSBzYXkgdGhhdCBhbiBhbXVsZXQgb2Ygc3RyYW5ndWxhdGlvbiBpcyB3b3JzZSB0aGFuIHJpbmcgYXJvdW5kIHRoZSBjb2xsYXIu"
+ },
+ { "They say that an attic is the best place to hide your toys.",
+ "VGhleSBzYXkgdGhhdCBhbiBhdHRpYyBpcyB0aGUgYmVzdCBwbGFjZSB0byBoaWRlIHlvdXIgdG95cy4="
+ },
+ { "They say that an axe named Cleaver once belonged to a hacker named Beaver.",
+ "VGhleSBzYXkgdGhhdCBhbiBheGUgbmFtZWQgQ2xlYXZlciBvbmNlIGJlbG9uZ2VkIHRvIGEgaGFja2VyIG5hbWVkIEJlYXZlci4="
+ },
+ { "They say that an eye of newt and a wing of bat are double the trouble.",
+ "VGhleSBzYXkgdGhhdCBhbiBleWUgb2YgbmV3dCBhbmQgYSB3aW5nIG9mIGJhdCBhcmUgZG91YmxlIHRoZSB0cm91YmxlLg=="
+ },
+ { "They say that an incubus named Izzy sometimes makes women feel sensitive.",
+ "VGhleSBzYXkgdGhhdCBhbiBpbmN1YnVzIG5hbWVkIEl6enkgc29tZXRpbWVzIG1ha2VzIHdvbWVuIGZlZWwgc2Vuc2l0aXZlLg=="
+ },
+ { "They say that an opulent throne room is rarely a place to wish you'd be in.",
+ "VGhleSBzYXkgdGhhdCBhbiBvcHVsZW50IHRocm9uZSByb29tIGlzIHJhcmVseSBhIHBsYWNlIHRvIHdpc2ggeW91J2QgYmUgaW4u"
+ },
+ { "They say that an unlucky hacker once had a nose bleed at an altar and died.",
+ "VGhleSBzYXkgdGhhdCBhbiB1bmx1Y2t5IGhhY2tlciBvbmNlIGhhZCBhIG5vc2UgYmxlZWQgYXQgYW4gYWx0YXIgYW5kIGRpZWQu"
+ },
+ { "They say that and they say this but they never say never, never!",
+ "VGhleSBzYXkgdGhhdCBhbmQgdGhleSBzYXkgdGhpcyBidXQgdGhleSBuZXZlciBzYXkgbmV2ZXIsIG5ldmVyIQ=="
+ },
+ { "They say that any quantum mechanic knows that speed kills.",
+ "VGhleSBzYXkgdGhhdCBhbnkgcXVhbnR1bSBtZWNoYW5pYyBrbm93cyB0aGF0IHNwZWVkIGtpbGxzLg=="
+ },
+ { "They say that applying a unicorn horn means you've missed the point.",
+ "VGhleSBzYXkgdGhhdCBhcHBseWluZyBhIHVuaWNvcm4gaG9ybiBtZWFucyB5b3UndmUgbWlzc2VkIHRoZSBwb2ludC4="
+ },
+ { "They say that blue stones are radioactive, beware.",
+ "VGhleSBzYXkgdGhhdCBibHVlIHN0b25lcyBhcmUgcmFkaW9hY3RpdmUsIGJld2FyZS4="
+ },
+ { "They say that building a dungeon is a team effort.",
+ "VGhleSBzYXkgdGhhdCBidWlsZGluZyBhIGR1bmdlb24gaXMgYSB0ZWFtIGVmZm9ydC4="
+ },
+ { "They say that chaotic characters never get a kick out of altars.",
+ "VGhleSBzYXkgdGhhdCBjaGFvdGljIGNoYXJhY3RlcnMgbmV2ZXIgZ2V0IGEga2ljayBvdXQgb2YgYWx0YXJzLg=="
+ },
+ { "They say that collapsing a dungeon often creates a panic.",
+ "VGhleSBzYXkgdGhhdCBjb2xsYXBzaW5nIGEgZHVuZ2VvbiBvZnRlbiBjcmVhdGVzIGEgcGFuaWMu"
+ },
+ { "They say that counting your eggs before they hatch shows that you care.",
+ "VGhleSBzYXkgdGhhdCBjb3VudGluZyB5b3VyIGVnZ3MgYmVmb3JlIHRoZXkgaGF0Y2ggc2hvd3MgdGhhdCB5b3UgY2FyZS4="
+ },
+ { "They say that dipping a bag of tricks in a fountain won't make it an icebox.",
+ "VGhleSBzYXkgdGhhdCBkaXBwaW5nIGEgYmFnIG9mIHRyaWNrcyBpbiBhIGZvdW50YWluIHdvbid0IG1ha2UgaXQgYW4gaWNlYm94Lg=="
+ },
+ { "They say that dipping an eel and brown mold in hot water makes bouillabaisse.",
+ "VGhleSBzYXkgdGhhdCBkaXBwaW5nIGFuIGVlbCBhbmQgYnJvd24gbW9sZCBpbiBob3Qgd2F0ZXIgbWFrZXMgYm91aWxsYWJhaXNzZS4="
+ },
+ { "They say that donating a doubloon is extremely pious charity.",
+ "VGhleSBzYXkgdGhhdCBkb25hdGluZyBhIGRvdWJsb29uIGlzIGV4dHJlbWVseSBwaW91cyBjaGFyaXR5Lg=="
+ },
+ { "They say that eating royal jelly attracts grizzly owlbears.",
+ "VGhleSBzYXkgdGhhdCBlYXRpbmcgcm95YWwgamVsbHkgYXR0cmFjdHMgZ3JpenpseSBvd2xiZWFycy4="
+ },
+ { "They say that eggs, pancakes and juice are just a mundane breakfast.",
+ "VGhleSBzYXkgdGhhdCBlZ2dzLCBwYW5jYWtlcyBhbmQganVpY2UgYXJlIGp1c3QgYSBtdW5kYW5lIGJyZWFrZmFzdC4="
+ },
+ { "They say that everyone knows why Medusa stands alone in the dark.",
+ "VGhleSBzYXkgdGhhdCBldmVyeW9uZSBrbm93cyB3aHkgTWVkdXNhIHN0YW5kcyBhbG9uZSBpbiB0aGUgZGFyay4="
+ },
+ { "They say that everyone wanted rec.games.hack to undergo a name change.",
+ "VGhleSBzYXkgdGhhdCBldmVyeW9uZSB3YW50ZWQgcmVjLmdhbWVzLmhhY2sgdG8gdW5kZXJnbyBhIG5hbWUgY2hhbmdlLg=="
+ },
+ { "They say that finding a winning strategy is a deliberate move on your part.",
+ "VGhleSBzYXkgdGhhdCBmaW5kaW5nIGEgd2lubmluZyBzdHJhdGVneSBpcyBhIGRlbGliZXJhdGUgbW92ZSBvbiB5b3VyIHBhcnQu"
+ },
+ { "They say that finding worthless glass is worth something.",
+ "VGhleSBzYXkgdGhhdCBmaW5kaW5nIHdvcnRobGVzcyBnbGFzcyBpcyB3b3J0aCBzb21ldGhpbmcu"
+ },
+ { "They say that fortune cookies are food for thought.",
+ "VGhleSBzYXkgdGhhdCBmb3J0dW5lIGNvb2tpZXMgYXJlIGZvb2QgZm9yIHRob3VnaHQu"
+ },
+ { "They say that gold is only wasted on a pet dragon.",
+ "VGhleSBzYXkgdGhhdCBnb2xkIGlzIG9ubHkgd2FzdGVkIG9uIGEgcGV0IGRyYWdvbi4="
+ },
+ { "They say that good things come to those that wait.",
+ "VGhleSBzYXkgdGhhdCBnb29kIHRoaW5ncyBjb21lIHRvIHRob3NlIHRoYXQgd2FpdC4="
+ },
+ { "They say that greased objects will slip out of monsters' hands.",
+ "VGhleSBzYXkgdGhhdCBncmVhc2VkIG9iamVjdHMgd2lsbCBzbGlwIG91dCBvZiBtb25zdGVycycgaGFuZHMu"
+ },
+ { "They say that if you can't spell then you'll wish you had a spell book.",
+ "VGhleSBzYXkgdGhhdCBpZiB5b3UgY2FuJ3Qgc3BlbGwgdGhlbiB5b3UnbGwgd2lzaCB5b3UgaGFkIGEgc3BlbGwgYm9vay4="
+ },
+ { "They say that if you live by the sword, you'll die by the sword.",
+ "VGhleSBzYXkgdGhhdCBpZiB5b3UgbGl2ZSBieSB0aGUgc3dvcmQsIHlvdSdsbCBkaWUgYnkgdGhlIHN3b3JkLg=="
+ },
+ { "They say that if you play like a monster you'll have a better game.",
+ "VGhleSBzYXkgdGhhdCBpZiB5b3UgcGxheSBsaWtlIGEgbW9uc3RlciB5b3UnbGwgaGF2ZSBhIGJldHRlciBnYW1lLg=="
+ },
+ { "They say that if you sleep with a demon you might awake with a headache.",
+ "VGhleSBzYXkgdGhhdCBpZiB5b3Ugc2xlZXAgd2l0aCBhIGRlbW9uIHlvdSBtaWdodCBhd2FrZSB3aXRoIGEgaGVhZGFjaGUu"
+ },
+ { "They say that if you step on a crack you could break your mother's back.",
+ "VGhleSBzYXkgdGhhdCBpZiB5b3Ugc3RlcCBvbiBhIGNyYWNrIHlvdSBjb3VsZCBicmVhayB5b3VyIG1vdGhlcidzIGJhY2su"
+ },
+ { "They say that if you're invisible you can still be heard!",
+ "VGhleSBzYXkgdGhhdCBpZiB5b3UncmUgaW52aXNpYmxlIHlvdSBjYW4gc3RpbGwgYmUgaGVhcmQh"
+ },
+ { "They say that if you're lucky you can feel the runes on a scroll.",
+ "VGhleSBzYXkgdGhhdCBpZiB5b3UncmUgbHVja3kgeW91IGNhbiBmZWVsIHRoZSBydW5lcyBvbiBhIHNjcm9sbC4="
+ },
+ { "They say that in the big picture gold is only small change.",
+ "VGhleSBzYXkgdGhhdCBpbiB0aGUgYmlnIHBpY3R1cmUgZ29sZCBpcyBvbmx5IHNtYWxsIGNoYW5nZS4="
+ },
+ { "They say that in the dungeon it's not what you know that really matters.",
+ "VGhleSBzYXkgdGhhdCBpbiB0aGUgZHVuZ2VvbiBpdCdzIG5vdCB3aGF0IHlvdSBrbm93IHRoYXQgcmVhbGx5IG1hdHRlcnMu"
+ },
+ { "They say that in the dungeon moon rocks are really dilithium crystals.",
+ "VGhleSBzYXkgdGhhdCBpbiB0aGUgZHVuZ2VvbiBtb29uIHJvY2tzIGFyZSByZWFsbHkgZGlsaXRoaXVtIGNyeXN0YWxzLg=="
+ },
+ { "They say that in the dungeon the boorish customer is never right.",
+ "VGhleSBzYXkgdGhhdCBpbiB0aGUgZHVuZ2VvbiB0aGUgYm9vcmlzaCBjdXN0b21lciBpcyBuZXZlciByaWdodC4="
+ },
+ { "They say that in the dungeon you don't need a watch to tell time.",
+ "VGhleSBzYXkgdGhhdCBpbiB0aGUgZHVuZ2VvbiB5b3UgZG9uJ3QgbmVlZCBhIHdhdGNoIHRvIHRlbGwgdGltZS4="
+ },
+ { "They say that in the dungeon you need something old, new, burrowed and blue.",
+ "VGhleSBzYXkgdGhhdCBpbiB0aGUgZHVuZ2VvbiB5b3UgbmVlZCBzb21ldGhpbmcgb2xkLCBuZXcsIGJ1cnJvd2VkIGFuZCBibHVlLg=="
+ },
+ { "They say that in the dungeon you should always count your blessings.",
+ "VGhleSBzYXkgdGhhdCBpbiB0aGUgZHVuZ2VvbiB5b3Ugc2hvdWxkIGFsd2F5cyBjb3VudCB5b3VyIGJsZXNzaW5ncy4="
+ },
+ { "They say that iron golem plate mail isn't worth wishing for.",
+ "VGhleSBzYXkgdGhhdCBpcm9uIGdvbGVtIHBsYXRlIG1haWwgaXNuJ3Qgd29ydGggd2lzaGluZyBmb3Iu"
+ },
+ { "They say that it takes four quarterstaffs to make one staff.",
+ "VGhleSBzYXkgdGhhdCBpdCB0YWtlcyBmb3VyIHF1YXJ0ZXJzdGFmZnMgdG8gbWFrZSBvbmUgc3RhZmYu"
+ },
+ { "They say that it's not over till the fat ladies sing.",
+ "VGhleSBzYXkgdGhhdCBpdCdzIG5vdCBvdmVyIHRpbGwgdGhlIGZhdCBsYWRpZXMgc2luZy4="
+ },
+ { "They say that it's not over till the fat lady shouts `Off with its head'.",
+ "VGhleSBzYXkgdGhhdCBpdCdzIG5vdCBvdmVyIHRpbGwgdGhlIGZhdCBsYWR5IHNob3V0cyBgT2ZmIHdpdGggaXRzIGhlYWQnLg=="
+ },
+ { "They say that kicking a heavy statue is really a dumb move.",
+ "VGhleSBzYXkgdGhhdCBraWNraW5nIGEgaGVhdnkgc3RhdHVlIGlzIHJlYWxseSBhIGR1bWIgbW92ZS4="
+ },
+ { "They say that kicking a valuable gem doesn't seem to make sense.",
+ "VGhleSBzYXkgdGhhdCBraWNraW5nIGEgdmFsdWFibGUgZ2VtIGRvZXNuJ3Qgc2VlbSB0byBtYWtlIHNlbnNlLg=="
+ },
+ { "They say that leprechauns know Latin and you should too.",
+ "VGhleSBzYXkgdGhhdCBsZXByZWNoYXVucyBrbm93IExhdGluIGFuZCB5b3Ugc2hvdWxkIHRvby4="
+ },
+ { "They say that minotaurs get lost outside of the mazes.",
+ "VGhleSBzYXkgdGhhdCBtaW5vdGF1cnMgZ2V0IGxvc3Qgb3V0c2lkZSBvZiB0aGUgbWF6ZXMu"
+ },
+ { "They say that most trolls are born again.",
+ "VGhleSBzYXkgdGhhdCBtb3N0IHRyb2xscyBhcmUgYm9ybiBhZ2Fpbi4="
+ },
+ { "They say that naming your cat Garfield will make you more attractive.",
+ "VGhleSBzYXkgdGhhdCBuYW1pbmcgeW91ciBjYXQgR2FyZmllbGQgd2lsbCBtYWtlIHlvdSBtb3JlIGF0dHJhY3RpdmUu"
+ },
+ { "They say that no one knows everything about everything in the dungeon.",
+ "VGhleSBzYXkgdGhhdCBubyBvbmUga25vd3MgZXZlcnl0aGluZyBhYm91dCBldmVyeXRoaW5nIGluIHRoZSBkdW5nZW9uLg=="
+ },
+ { "They say that no one plays NetHack just for the fun of it.",
+ "VGhleSBzYXkgdGhhdCBubyBvbmUgcGxheXMgTmV0SGFjayBqdXN0IGZvciB0aGUgZnVuIG9mIGl0Lg=="
+ },
+ { "They say that no one really subscribes to rec.games.roguelike.nethack.",
+ "VGhleSBzYXkgdGhhdCBubyBvbmUgcmVhbGx5IHN1YnNjcmliZXMgdG8gcmVjLmdhbWVzLnJvZ3VlbGlrZS5uZXRoYWNrLg=="
+ },
+ { "They say that no one will admit to starting a rumor.",
+ "VGhleSBzYXkgdGhhdCBubyBvbmUgd2lsbCBhZG1pdCB0byBzdGFydGluZyBhIHJ1bW9yLg=="
+ },
+ { "They say that nurses sometimes carry scalpels and never use them.",
+ "VGhleSBzYXkgdGhhdCBudXJzZXMgc29tZXRpbWVzIGNhcnJ5IHNjYWxwZWxzIGFuZCBuZXZlciB1c2UgdGhlbS4="
+ },
+ { "They say that once you've met one wizard you've met them all.",
+ "VGhleSBzYXkgdGhhdCBvbmNlIHlvdSd2ZSBtZXQgb25lIHdpemFyZCB5b3UndmUgbWV0IHRoZW0gYWxsLg=="
+ },
+ { "They say that one troll is worth 10,000 newts.",
+ "VGhleSBzYXkgdGhhdCBvbmUgdHJvbGwgaXMgd29ydGggMTAsMDAwIG5ld3RzLg=="
+ },
+ { "They say that only David can find the zoo!",
+ "VGhleSBzYXkgdGhhdCBvbmx5IERhdmlkIGNhbiBmaW5kIHRoZSB6b28h"
+ },
+ { "They say that only angels play their harps for their pets.",
+ "VGhleSBzYXkgdGhhdCBvbmx5IGFuZ2VscyBwbGF5IHRoZWlyIGhhcnBzIGZvciB0aGVpciBwZXRzLg=="
+ },
+ { "They say that only big spenders carry gold.",
+ "VGhleSBzYXkgdGhhdCBvbmx5IGJpZyBzcGVuZGVycyBjYXJyeSBnb2xkLg=="
+ },
+ { "They say that orc shamans are healthy, wealthy and wise.",
+ "VGhleSBzYXkgdGhhdCBvcmMgc2hhbWFucyBhcmUgaGVhbHRoeSwgd2VhbHRoeSBhbmQgd2lzZS4="
+ },
+ { "They say that playing NetHack is like walking into a death trap.",
+ "VGhleSBzYXkgdGhhdCBwbGF5aW5nIE5ldEhhY2sgaXMgbGlrZSB3YWxraW5nIGludG8gYSBkZWF0aCB0cmFwLg=="
+ },
+ { "They say that problem breathing is best treated by a proper diet.",
+ "VGhleSBzYXkgdGhhdCBwcm9ibGVtIGJyZWF0aGluZyBpcyBiZXN0IHRyZWF0ZWQgYnkgYSBwcm9wZXIgZGlldC4="
+ },
+ { "They say that quaffing many potions of levitation can give you a headache.",
+ "VGhleSBzYXkgdGhhdCBxdWFmZmluZyBtYW55IHBvdGlvbnMgb2YgbGV2aXRhdGlvbiBjYW4gZ2l2ZSB5b3UgYSBoZWFkYWNoZS4="
+ },
+ { "They say that queen bees get that way by eating royal jelly.",
+ "VGhleSBzYXkgdGhhdCBxdWVlbiBiZWVzIGdldCB0aGF0IHdheSBieSBlYXRpbmcgcm95YWwgamVsbHku"
+ },
+ { "They say that reading a scare monster scroll is the same as saying Elbereth.",
+ "VGhleSBzYXkgdGhhdCByZWFkaW5nIGEgc2NhcmUgbW9uc3RlciBzY3JvbGwgaXMgdGhlIHNhbWUgYXMgc2F5aW5nIEVsYmVyZXRoLg=="
+ },
+ { "They say that real hackers always are controlled.",
+ "VGhleSBzYXkgdGhhdCByZWFsIGhhY2tlcnMgYWx3YXlzIGFyZSBjb250cm9sbGVkLg=="
+ },
+ { "They say that real hackers never sleep.",
+ "VGhleSBzYXkgdGhhdCByZWFsIGhhY2tlcnMgbmV2ZXIgc2xlZXAu"
+ },
+ { "They say that shopkeepers are insured by Croesus himself!",
+ "VGhleSBzYXkgdGhhdCBzaG9wa2VlcGVycyBhcmUgaW5zdXJlZCBieSBDcm9lc3VzIGhpbXNlbGYh"
+ },
+ { "They say that shopkeepers never carry more than 20 gold pieces, at night.",
+ "VGhleSBzYXkgdGhhdCBzaG9wa2VlcGVycyBuZXZlciBjYXJyeSBtb3JlIHRoYW4gMjAgZ29sZCBwaWVjZXMsIGF0IG5pZ2h0Lg=="
+ },
+ { "They say that shopkeepers never sell blessed potions of invisibility.",
+ "VGhleSBzYXkgdGhhdCBzaG9wa2VlcGVycyBuZXZlciBzZWxsIGJsZXNzZWQgcG90aW9ucyBvZiBpbnZpc2liaWxpdHku"
+ },
+ { "They say that soldiers wear kid gloves and silly helmets.",
+ "VGhleSBzYXkgdGhhdCBzb2xkaWVycyB3ZWFyIGtpZCBnbG92ZXMgYW5kIHNpbGx5IGhlbG1ldHMu"
+ },
+ { "They say that some Kops are on the take.",
+ "VGhleSBzYXkgdGhhdCBzb21lIEtvcHMgYXJlIG9uIHRoZSB0YWtlLg=="
+ },
+ { "They say that some guards' palms can be greased.",
+ "VGhleSBzYXkgdGhhdCBzb21lIGd1YXJkcycgcGFsbXMgY2FuIGJlIGdyZWFzZWQu"
+ },
+ { "They say that some monsters may kiss your boots to stop your drum playing.",
+ "VGhleSBzYXkgdGhhdCBzb21lIG1vbnN0ZXJzIG1heSBraXNzIHlvdXIgYm9vdHMgdG8gc3RvcCB5b3VyIGRydW0gcGxheWluZy4="
+ },
+ { "They say that sometimes you can be the hit of the party when playing a horn.",
+ "VGhleSBzYXkgdGhhdCBzb21ldGltZXMgeW91IGNhbiBiZSB0aGUgaGl0IG9mIHRoZSBwYXJ0eSB3aGVuIHBsYXlpbmcgYSBob3JuLg=="
+ },
+ { "They say that the NetHack gods generally welcome your sacrifices.",
+ "VGhleSBzYXkgdGhhdCB0aGUgTmV0SGFjayBnb2RzIGdlbmVyYWxseSB3ZWxjb21lIHlvdXIgc2FjcmlmaWNlcy4="
+ },
+ { "They say that the Three Rings are named Vilya, Nenya and Narya.",
+ "VGhleSBzYXkgdGhhdCB0aGUgVGhyZWUgUmluZ3MgYXJlIG5hbWVkIFZpbHlhLCBOZW55YSBhbmQgTmFyeWEu"
+ },
+ { "They say that the Wizard of Yendor has a death wish.",
+ "VGhleSBzYXkgdGhhdCB0aGUgV2l6YXJkIG9mIFllbmRvciBoYXMgYSBkZWF0aCB3aXNoLg=="
+ },
+ { "They say that the `hair of the dog' is sometimes an effective remedy.",
+ "VGhleSBzYXkgdGhhdCB0aGUgYGhhaXIgb2YgdGhlIGRvZycgaXMgc29tZXRpbWVzIGFuIGVmZmVjdGl2ZSByZW1lZHku"
+ },
+ { "They say that the best time to save your game is now before its too late.",
+ "VGhleSBzYXkgdGhhdCB0aGUgYmVzdCB0aW1lIHRvIHNhdmUgeW91ciBnYW1lIGlzIG5vdyBiZWZvcmUgaXRzIHRvbyBsYXRlLg=="
+ },
+ { "They say that the biggest obstacle in NetHack is your mind.",
+ "VGhleSBzYXkgdGhhdCB0aGUgYmlnZ2VzdCBvYnN0YWNsZSBpbiBOZXRIYWNrIGlzIHlvdXIgbWluZC4="
+ },
+ { "They say that the gods are angry when they hit you with objects.",
+ "VGhleSBzYXkgdGhhdCB0aGUgZ29kcyBhcmUgYW5ncnkgd2hlbiB0aGV5IGhpdCB5b3Ugd2l0aCBvYmplY3RzLg=="
+ },
+ { "They say that the priesthood are specially favored by the gods.",
+ "VGhleSBzYXkgdGhhdCB0aGUgcHJpZXN0aG9vZCBhcmUgc3BlY2lhbGx5IGZhdm9yZWQgYnkgdGhlIGdvZHMu"
+ },
+ { "They say that the way to make a unicorn happy is to give it what it wants.",
+ "VGhleSBzYXkgdGhhdCB0aGUgd2F5IHRvIG1ha2UgYSB1bmljb3JuIGhhcHB5IGlzIHRvIGdpdmUgaXQgd2hhdCBpdCB3YW50cy4="
+ },
+ { "They say that there are no black or white stones, only gray.",
+ "VGhleSBzYXkgdGhhdCB0aGVyZSBhcmUgbm8gYmxhY2sgb3Igd2hpdGUgc3RvbmVzLCBvbmx5IGdyYXku"
+ },
+ { "They say that there are no skeletons hence there are no skeleton keys.",
+ "VGhleSBzYXkgdGhhdCB0aGVyZSBhcmUgbm8gc2tlbGV0b25zIGhlbmNlIHRoZXJlIGFyZSBubyBza2VsZXRvbiBrZXlzLg=="
+ },
+ { "They say that there is a clever rogue in every hacker just dying to escape.",
+ "VGhleSBzYXkgdGhhdCB0aGVyZSBpcyBhIGNsZXZlciByb2d1ZSBpbiBldmVyeSBoYWNrZXIganVzdCBkeWluZyB0byBlc2NhcGUu"
+ },
+ { "They say that there is no such thing as free advice.",
+ "VGhleSBzYXkgdGhhdCB0aGVyZSBpcyBubyBzdWNoIHRoaW5nIGFzIGZyZWUgYWR2aWNlLg=="
+ },
+ { "They say that there is only one way to win at NetHack.",
+ "VGhleSBzYXkgdGhhdCB0aGVyZSBpcyBvbmx5IG9uZSB3YXkgdG8gd2luIGF0IE5ldEhhY2su"
+ },
+ { "They say that there once was a fearsome chaotic samurai named Luk No.",
+ "VGhleSBzYXkgdGhhdCB0aGVyZSBvbmNlIHdhcyBhIGZlYXJzb21lIGNoYW90aWMgc2FtdXJhaSBuYW1lZCBMdWsgTm8u"
+ },
+ { "They say that there was a time when cursed holy water wasn't water.",
+ "VGhleSBzYXkgdGhhdCB0aGVyZSB3YXMgYSB0aW1lIHdoZW4gY3Vyc2VkIGhvbHkgd2F0ZXIgd2Fzbid0IHdhdGVyLg=="
+ },
+ { "They say that there's no point in crying over a gray ooze.",
+ "VGhleSBzYXkgdGhhdCB0aGVyZSdzIG5vIHBvaW50IGluIGNyeWluZyBvdmVyIGEgZ3JheSBvb3plLg=="
+ },
+ { "They say that there's only hope left after you've opened Pandora's box.",
+ "VGhleSBzYXkgdGhhdCB0aGVyZSdzIG9ubHkgaG9wZSBsZWZ0IGFmdGVyIHlvdSd2ZSBvcGVuZWQgUGFuZG9yYSdzIGJveC4="
+ },
+ { "They say that trapdoors should always be marked `Caution: Trap Door'.",
+ "VGhleSBzYXkgdGhhdCB0cmFwZG9vcnMgc2hvdWxkIGFsd2F5cyBiZSBtYXJrZWQgYENhdXRpb246IFRyYXAgRG9vcicu"
+ },
+ { "They say that using an amulet of change isn't a difficult operation.",
+ "VGhleSBzYXkgdGhhdCB1c2luZyBhbiBhbXVsZXQgb2YgY2hhbmdlIGlzbid0IGEgZGlmZmljdWx0IG9wZXJhdGlvbi4="
+ },
+ { "They say that water walking boots are better if you are fast like Hermes.",
+ "VGhleSBzYXkgdGhhdCB3YXRlciB3YWxraW5nIGJvb3RzIGFyZSBiZXR0ZXIgaWYgeW91IGFyZSBmYXN0IGxpa2UgSGVybWVzLg=="
+ },
+ { "They say that when you wear a circular amulet you might resemble a troll.",
+ "VGhleSBzYXkgdGhhdCB3aGVuIHlvdSB3ZWFyIGEgY2lyY3VsYXIgYW11bGV0IHlvdSBtaWdodCByZXNlbWJsZSBhIHRyb2xsLg=="
+ },
+ { "They say that when you're hungry you can get a pizza in 30 moves or it's free.",
+ "VGhleSBzYXkgdGhhdCB3aGVuIHlvdSdyZSBodW5ncnkgeW91IGNhbiBnZXQgYSBwaXp6YSBpbiAzMCBtb3ZlcyBvciBpdCdzIGZyZWUu"
+ },
+ { "They say that when your god is angry you should try another one.",
+ "VGhleSBzYXkgdGhhdCB3aGVuIHlvdXIgZ29kIGlzIGFuZ3J5IHlvdSBzaG91bGQgdHJ5IGFub3RoZXIgb25lLg=="
+ },
+ { "They say that wielding a unicorn horn takes strength.",
+ "VGhleSBzYXkgdGhhdCB3aWVsZGluZyBhIHVuaWNvcm4gaG9ybiB0YWtlcyBzdHJlbmd0aC4="
+ },
+ { "They say that with speed boots you never worry about hit and run accidents.",
+ "VGhleSBzYXkgdGhhdCB3aXRoIHNwZWVkIGJvb3RzIHlvdSBuZXZlciB3b3JyeSBhYm91dCBoaXQgYW5kIHJ1biBhY2NpZGVudHMu"
+ },
+ { "They say that you can defeat a killer bee with a unicorn horn.",
+ "VGhleSBzYXkgdGhhdCB5b3UgY2FuIGRlZmVhdCBhIGtpbGxlciBiZWUgd2l0aCBhIHVuaWNvcm4gaG9ybi4="
+ },
+ { "They say that you can only cross the River Styx in Charon's boat.",
+ "VGhleSBzYXkgdGhhdCB5b3UgY2FuIG9ubHkgY3Jvc3MgdGhlIFJpdmVyIFN0eXggaW4gQ2hhcm9uJ3MgYm9hdC4="
+ },
+ { "They say that you can only kill a lich once and then you'd better be careful.",
+ "VGhleSBzYXkgdGhhdCB5b3UgY2FuIG9ubHkga2lsbCBhIGxpY2ggb25jZSBhbmQgdGhlbiB5b3UnZCBiZXR0ZXIgYmUgY2FyZWZ1bC4="
+ },
+ { "They say that you can only wish for things you've already had.",
+ "VGhleSBzYXkgdGhhdCB5b3UgY2FuIG9ubHkgd2lzaCBmb3IgdGhpbmdzIHlvdSd2ZSBhbHJlYWR5IGhhZC4="
+ },
+ { "They say that you can train a cat by talking gently to it.",
+ "VGhleSBzYXkgdGhhdCB5b3UgY2FuIHRyYWluIGEgY2F0IGJ5IHRhbGtpbmcgZ2VudGx5IHRvIGl0Lg=="
+ },
+ { "They say that you can train a dog by talking firmly to it.",
+ "VGhleSBzYXkgdGhhdCB5b3UgY2FuIHRyYWluIGEgZG9nIGJ5IHRhbGtpbmcgZmlybWx5IHRvIGl0Lg=="
+ },
+ { "They say that you can trust your gold with the king.",
+ "VGhleSBzYXkgdGhhdCB5b3UgY2FuIHRydXN0IHlvdXIgZ29sZCB3aXRoIHRoZSBraW5nLg=="
+ },
+ { "They say that you can't wipe your greasy bare hands on a blank scroll.",
+ "VGhleSBzYXkgdGhhdCB5b3UgY2FuJ3Qgd2lwZSB5b3VyIGdyZWFzeSBiYXJlIGhhbmRzIG9uIGEgYmxhbmsgc2Nyb2xsLg=="
+ },
+ { "They say that you cannot trust scrolls of rumor.",
+ "VGhleSBzYXkgdGhhdCB5b3UgY2Fubm90IHRydXN0IHNjcm9sbHMgb2YgcnVtb3Iu"
+ },
+ { "They say that you could fall head over heels for an energy vortex.",
+ "VGhleSBzYXkgdGhhdCB5b3UgY291bGQgZmFsbCBoZWFkIG92ZXIgaGVlbHMgZm9yIGFuIGVuZXJneSB2b3J0ZXgu"
+ },
+ { "They say that you need a key in order to open locked doors.",
+ "VGhleSBzYXkgdGhhdCB5b3UgbmVlZCBhIGtleSBpbiBvcmRlciB0byBvcGVuIGxvY2tlZCBkb29ycy4="
+ },
+ { "They say that you need a mirror to notice a mimic in an antique shop.",
+ "VGhleSBzYXkgdGhhdCB5b3UgbmVlZCBhIG1pcnJvciB0byBub3RpY2UgYSBtaW1pYyBpbiBhbiBhbnRpcXVlIHNob3Au"
+ },
+ { "They say that you really can use a pick-axe unless you really can't.",
+ "VGhleSBzYXkgdGhhdCB5b3UgcmVhbGx5IGNhbiB1c2UgYSBwaWNrLWF4ZSB1bmxlc3MgeW91IHJlYWxseSBjYW4ndC4="
+ },
+ { "They say that you should always store your tools in the cellar.",
+ "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIGFsd2F5cyBzdG9yZSB5b3VyIHRvb2xzIGluIHRoZSBjZWxsYXIu"
+ },
+ { "They say that you should be careful while climbing the ladder to success.",
+ "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIGJlIGNhcmVmdWwgd2hpbGUgY2xpbWJpbmcgdGhlIGxhZGRlciB0byBzdWNjZXNzLg=="
+ },
+ { "They say that you should call your armor `rustproof'.",
+ "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIGNhbGwgeW91ciBhcm1vciBgcnVzdHByb29mJy4="
+ },
+ { "They say that you should name your dog Spuds to have a cool pet.",
+ "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIG5hbWUgeW91ciBkb2cgU3B1ZHMgdG8gaGF2ZSBhIGNvb2wgcGV0Lg=="
+ },
+ { "They say that you should name your weapon after your first monster kill.",
+ "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIG5hbWUgeW91ciB3ZWFwb24gYWZ0ZXIgeW91ciBmaXJzdCBtb25zdGVyIGtpbGwu"
+ },
+ { "They say that you should never introduce a rope golem to a succubus.",
+ "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIG5ldmVyIGludHJvZHVjZSBhIHJvcGUgZ29sZW0gdG8gYSBzdWNjdWJ1cy4="
+ },
+ { "They say that you should never sleep near invisible ring wraiths.",
+ "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIG5ldmVyIHNsZWVwIG5lYXIgaW52aXNpYmxlIHJpbmcgd3JhaXRocy4="
+ },
+ { "They say that you should never try to leave the dungeon with a bag of gems.",
+ "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIG5ldmVyIHRyeSB0byBsZWF2ZSB0aGUgZHVuZ2VvbiB3aXRoIGEgYmFnIG9mIGdlbXMu"
+ },
+ { "They say that you should remove your armor before sitting on a throne.",
+ "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIHJlbW92ZSB5b3VyIGFybW9yIGJlZm9yZSBzaXR0aW5nIG9uIGEgdGhyb25lLg=="
+ },
+ { "This fortune cookie is copy protected.",
+ "VGhpcyBmb3J0dW5lIGNvb2tpZSBpcyBjb3B5IHByb3RlY3RlZC4="
+ },
+ { "This fortune cookie is the property of Fortune Cookies, Inc.",
+ "VGhpcyBmb3J0dW5lIGNvb2tpZSBpcyB0aGUgcHJvcGVydHkgb2YgRm9ydHVuZSBDb29raWVzLCBJbmMu"
+ },
+ { "Tired? Try a scroll of charging on yourself.",
+ "VGlyZWQ/IFRyeSBhIHNjcm9sbCBvZiBjaGFyZ2luZyBvbiB5b3Vyc2VsZi4="
+ },
+ { "To achieve the next higher rating, you need 3 more points.",
+ "VG8gYWNoaWV2ZSB0aGUgbmV4dCBoaWdoZXIgcmF0aW5nLCB5b3UgbmVlZCAzIG1vcmUgcG9pbnRzLg=="
+ },
+ { "To reach heaven, escape the dungeon while wearing a ring of levitation.",
+ "VG8gcmVhY2ggaGVhdmVuLCBlc2NhcGUgdGhlIGR1bmdlb24gd2hpbGUgd2VhcmluZyBhIHJpbmcgb2YgbGV2aXRhdGlvbi4="
+ },
+ { "Tourists wear shirts loud enough to wake the dead.",
+ "VG91cmlzdHMgd2VhciBzaGlydHMgbG91ZCBlbm91Z2ggdG8gd2FrZSB0aGUgZGVhZC4="
+ },
+ { "Try calling your katana Moulinette.",
+ "VHJ5IGNhbGxpbmcgeW91ciBrYXRhbmEgTW91bGluZXR0ZS4="
+ },
+ { "Ulch! That meat was painted!",
+ "VWxjaCEgVGhhdCBtZWF0IHdhcyBwYWludGVkIQ=="
+ },
+ { "Unfortunately, this message was left intentionally blank.",
+ "VW5mb3J0dW5hdGVseSwgdGhpcyBtZXNzYWdlIHdhcyBsZWZ0IGludGVudGlvbmFsbHkgYmxhbmsu"
+ },
+ { "Using a morning star in the evening has no effect.",
+ "VXNpbmcgYSBtb3JuaW5nIHN0YXIgaW4gdGhlIGV2ZW5pbmcgaGFzIG5vIGVmZmVjdC4="
+ },
+ { "Want a hint? Zap a wand of make invisible on your weapon!",
+ "V2FudCBhIGhpbnQ/IFphcCBhIHdhbmQgb2YgbWFrZSBpbnZpc2libGUgb24geW91ciB3ZWFwb24h"
+ },
+ { "Want to ascend in a hurry? Apply at Gizmonic Institute.",
+ "V2FudCB0byBhc2NlbmQgaW4gYSBodXJyeT8gQXBwbHkgYXQgR2l6bW9uaWMgSW5zdGl0dXRlLg=="
+ },
+ { "Wanted: shopkeepers. Send a scroll of mail to Mage of Yendor/Level 35/Dungeon.",
+ "V2FudGVkOiBzaG9wa2VlcGVycy4gU2VuZCBhIHNjcm9sbCBvZiBtYWlsIHRvIE1hZ2Ugb2YgWWVuZG9yL0xldmVsIDM1L0R1bmdlb24u"
+ },
+ { "Warning: fortune reading can be hazardous to your health.",
+ "V2FybmluZzogZm9ydHVuZSByZWFkaW5nIGNhbiBiZSBoYXphcmRvdXMgdG8geW91ciBoZWFsdGgu"
+ },
+ { "We have new ways of detecting treachery...",
+ "V2UgaGF2ZSBuZXcgd2F5cyBvZiBkZXRlY3RpbmcgdHJlYWNoZXJ5Li4u"
+ },
+ { "Wet towels make great weapons!",
+ "V2V0IHRvd2VscyBtYWtlIGdyZWF0IHdlYXBvbnMh"
+ },
+ { "What a pity, you cannot read it!",
+ "V2hhdCBhIHBpdHksIHlvdSBjYW5ub3QgcmVhZCBpdCE="
+ },
+ { "When a piercer drops in on you, you will be tempted to hit the ceiling!",
+ "V2hlbiBhIHBpZXJjZXIgZHJvcHMgaW4gb24geW91LCB5b3Ugd2lsbCBiZSB0ZW1wdGVkIHRvIGhpdCB0aGUgY2VpbGluZyE="
+ },
+ { "When in a maze follow the right wall and you will never get lost.",
+ "V2hlbiBpbiBhIG1hemUgZm9sbG93IHRoZSByaWdodCB3YWxsIGFuZCB5b3Ugd2lsbCBuZXZlciBnZXQgbG9zdC4="
+ },
+ { "When you have a key, you don't have to wait for the guard.",
+ "V2hlbiB5b3UgaGF2ZSBhIGtleSwgeW91IGRvbid0IGhhdmUgdG8gd2FpdCBmb3IgdGhlIGd1YXJkLg=="
+ },
+ { "Why are you wasting time reading fortunes?",
+ "V2h5IGFyZSB5b3Ugd2FzdGluZyB0aW1lIHJlYWRpbmcgZm9ydHVuZXM/"
+ },
+ { "Wish for a master key and open the Magic Memory Vault!",
+ "V2lzaCBmb3IgYSBtYXN0ZXIga2V5IGFuZCBvcGVuIHRoZSBNYWdpYyBNZW1vcnkgVmF1bHQh"
+ },
+ { "Wizard expects every monster to do its duty.",
+ "V2l6YXJkIGV4cGVjdHMgZXZlcnkgbW9uc3RlciB0byBkbyBpdHMgZHV0eS4="
+ },
+ { "Wow! You could've had a potion of fruit juice!",
+ "V293ISBZb3UgY291bGQndmUgaGFkIGEgcG90aW9uIG9mIGZydWl0IGp1aWNlIQ=="
+ },
+ { "Yet Another Silly Message (YASM).",
+ "WWV0IEFub3RoZXIgU2lsbHkgTWVzc2FnZSAoWUFTTSku"
+ },
+ { "You are destined to be misled by a fortune.",
+ "WW91IGFyZSBkZXN0aW5lZCB0byBiZSBtaXNsZWQgYnkgYSBmb3J0dW5lLg=="
+ },
+ { "You can get a genuine Amulet of Yendor by doing the following: --More--",
+ "WW91IGNhbiBnZXQgYSBnZW51aW5lIEFtdWxldCBvZiBZZW5kb3IgYnkgZG9pbmcgdGhlIGZvbGxvd2luZzogLS1Nb3JlLS0="
+ },
+ { "You can protect yourself from black dragons by doing the following: --More--",
+ "WW91IGNhbiBwcm90ZWN0IHlvdXJzZWxmIGZyb20gYmxhY2sgZHJhZ29ucyBieSBkb2luZyB0aGUgZm9sbG93aW5nOiAtLU1vcmUtLQ=="
+ },
+ { "You can't get by the snake.",
+ "WW91IGNhbid0IGdldCBieSB0aGUgc25ha2Uu"
+ },
+ { "You feel like someone is pulling your leg.",
+ "WW91IGZlZWwgbGlrZSBzb21lb25lIGlzIHB1bGxpbmcgeW91ciBsZWcu"
+ },
+ { "You have to outwit the Sphynx or pay her.",
+ "WW91IGhhdmUgdG8gb3V0d2l0IHRoZSBTcGh5bnggb3IgcGF5IGhlci4="
+ },
+ { "You hear the fortune cookie's hissing!",
+ "WW91IGhlYXIgdGhlIGZvcnR1bmUgY29va2llJ3MgaGlzc2luZyE="
+ },
+ { "You may get rich selling letters, but beware of being blackmailed!",
+ "WW91IG1heSBnZXQgcmljaCBzZWxsaW5nIGxldHRlcnMsIGJ1dCBiZXdhcmUgb2YgYmVpbmcgYmxhY2ttYWlsZWQh"
+ },
+ { "You offend Shai-Hulud by sheathing your crysknife without having drawn blood.",
+ "WW91IG9mZmVuZCBTaGFpLUh1bHVkIGJ5IHNoZWF0aGluZyB5b3VyIGNyeXNrbmlmZSB3aXRob3V0IGhhdmluZyBkcmF3biBibG9vZC4="
+ },
+ { "You swallowed the fortune!",
+ "WW91IHN3YWxsb3dlZCB0aGUgZm9ydHVuZSE="
+ },
+ { "You want to regain strength? Two levels ahead is a guesthouse!",
+ "WW91IHdhbnQgdG8gcmVnYWluIHN0cmVuZ3RoPyBUd28gbGV2ZWxzIGFoZWFkIGlzIGEgZ3Vlc3Rob3VzZSE="
+ },
+ { "You will encounter a tall, dark, and gruesome creature...",
+ "WW91IHdpbGwgZW5jb3VudGVyIGEgdGFsbCwgZGFyaywgYW5kIGdydWVzb21lIGNyZWF0dXJlLi4u"
+ },
+
+ { "The End", "VGhlIEVuZA==" }
+};
+
+/* PL_Base64Encode, random strings */
+PRBool test_004(void)
+{
+ int i;
+ char result[ 4096 ];
+
+ printf("Test 004 (PL_Base64Encode, random strings) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 plen = PL_strlen(array[i].plaintext);
+ PRUint32 clen = ((plen + 2)/3)*4;
+
+ char *rv = PL_Base64Encode(array[i].plaintext, plen, result);
+
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d): return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp(result, array[i].cyphertext, clen) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%.*s.\"\n",
+ i, array[i].plaintext, array[i].cyphertext, clen, result);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Encode, single characters, malloc */
+PRBool test_005(void)
+{
+ PRUint32 a, b;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char *rv;
+
+ printf("Test 005 (PL_Base64Encode, single characters, malloc) ..."); fflush(stdout);
+
+ plain[1] = plain[2] = plain[3] = (unsigned char)0;
+ cypher[2] = cypher[3] = (unsigned char)'=';
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (unsigned char)(a * 4 + b);
+ cypher[1] = base[(b * 16)];
+
+ rv = PL_Base64Encode((char *)plain, 1, (char *)0);
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d, %d): no return value\n", a, b);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp((char *)cypher, rv) )
+ {
+ printf("FAIL\n\t(%d, %d): expected \"%s,\" got \"%s.\"\n",
+ a, b, cypher, rv);
+ PR_DELETE(rv);
+ return PR_FALSE;
+ }
+
+ PR_DELETE(rv);
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Encode, double characters, malloc */
+PRBool test_006(void)
+{
+ PRUint32 a, b, c, d;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char *rv;
+
+ printf("Test 006 (PL_Base64Encode, double characters, malloc) ..."); fflush(stdout);
+
+ plain[2] = plain[3] = (unsigned char)0;
+ cypher[3] = (unsigned char)'=';
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (a*4) + b;
+ for( c = 0; c < 16; c++ )
+ {
+ cypher[1] = base[b*16 + c];
+ for( d = 0; d < 16; d++ )
+ {
+ plain[1] = c*16 + d;
+ cypher[2] = base[d*4];
+
+ rv = PL_Base64Encode((char *)plain, 2, (char *)0);
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): no return value\n", a, b, c, d);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp((char *)cypher, rv) )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): expected \"%s,\" got \"%s.\"\n",
+ a, b, c, d, cypher, rv);
+ PR_DELETE(rv);
+ return PR_FALSE;
+ }
+
+ PR_DELETE(rv);
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Encode, triple characters, malloc */
+PRBool test_007(void)
+{
+ PRUint32 a, b, c, d, e, f;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char *rv;
+
+ printf("Test 007 (PL_Base64Encode, triple characters, malloc) ..."); fflush(stdout);
+
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (a*4) + b;
+ for( c = 0; c < 16; c++ )
+ {
+ cypher[1] = base[b*16 + c];
+ for( d = 0; d < 16; d++ )
+ {
+ plain[1] = c*16 + d;
+ for( e = 0; e < 4; e++ )
+ {
+ cypher[2] = base[d*4 + e];
+ for( f = 0; f < 64; f++ )
+ {
+ plain[2] = e * 64 + f;
+ cypher[3] = base[f];
+
+ rv = PL_Base64Encode((char *)plain, 3, (char *)0);
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): no return value\n", a, b, c, d, e, f);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp((char *)cypher, rv) )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): expected \"%s,\" got \"%.4s.\"\n",
+ a, b, c, d, e, f, cypher, rv);
+ PR_DELETE(rv);
+ return PR_FALSE;
+ }
+
+ PR_DELETE(rv);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Encode, random strings, malloc */
+PRBool test_008(void)
+{
+ int i;
+
+ printf("Test 008 (PL_Base64Encode, random strings, malloc) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 plen = PL_strlen(array[i].plaintext);
+ PRUint32 clen = ((plen + 2)/3)*4;
+
+ char *rv = PL_Base64Encode(array[i].plaintext, plen, (char *)0);
+
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d): no return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp(rv, array[i].cyphertext) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%s.\"\n",
+ i, array[i].plaintext, array[i].cyphertext, rv);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, single characters */
+PRBool test_009(void)
+{
+ PRUint32 a, b;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char result[ 8 ];
+ char *rv;
+
+ printf("Test 009 (PL_Base64Decode, single characters, equals) ..."); fflush(stdout);
+
+ plain[1] = plain[2] = plain[3] = (unsigned char)0;
+ cypher[2] = cypher[3] = (unsigned char)'=';
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (unsigned char)(a * 4 + b);
+ cypher[1] = base[(b * 16)];
+
+ rv = PL_Base64Decode((char *)cypher, 4, result);
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d, %d): return value\n", a, b);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp((char *)plain, result, 1) )
+ {
+ printf("FAIL\n\t(%d, %d): expected \"%s,\" got \"%.1s.\"\n",
+ a, b, plain, result);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, single characters */
+PRBool test_010(void)
+{
+ PRUint32 a, b;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char result[ 8 ];
+ char *rv;
+
+ printf("Test 010 (PL_Base64Decode, single characters, no equals) ..."); fflush(stdout);
+
+ plain[1] = plain[2] = plain[3] = (unsigned char)0;
+ cypher[2] = cypher[3] = (unsigned char)0;
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (unsigned char)(a * 4 + b);
+ cypher[1] = base[(b * 16)];
+
+ rv = PL_Base64Decode((char *)cypher, 2, result);
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d, %d): return value\n", a, b);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp((char *)plain, result, 1) )
+ {
+ printf("FAIL\n\t(%d, %d): expected \"%s,\" got \"%.1s.\"\n",
+ a, b, plain, result);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, double characters */
+PRBool test_011(void)
+{
+ PRUint32 a, b, c, d;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char result[ 8 ];
+ char *rv;
+
+ printf("Test 011 (PL_Base64Decode, double characters, equals) ..."); fflush(stdout);
+
+ plain[2] = plain[3] = (unsigned char)0;
+ cypher[3] = (unsigned char)'=';
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (a*4) + b;
+ for( c = 0; c < 16; c++ )
+ {
+ cypher[1] = base[b*16 + c];
+ for( d = 0; d < 16; d++ )
+ {
+ plain[1] = c*16 + d;
+ cypher[2] = base[d*4];
+
+ rv = PL_Base64Decode((char *)cypher, 4, result);
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): return value\n", a, b, c, d);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp((char *)plain, result, 2) )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): expected \"%s,\" got \"%.2s.\"\n",
+ a, b, c, d, plain, result);
+ return PR_FALSE;
+ }
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, double characters */
+PRBool test_012(void)
+{
+ PRUint32 a, b, c, d;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char result[ 8 ];
+ char *rv;
+
+ printf("Test 012 (PL_Base64Decode, double characters, no equals) ..."); fflush(stdout);
+
+ plain[2] = plain[3] = (unsigned char)0;
+ cypher[3] = (unsigned char)0;
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (a*4) + b;
+ for( c = 0; c < 16; c++ )
+ {
+ cypher[1] = base[b*16 + c];
+ for( d = 0; d < 16; d++ )
+ {
+ plain[1] = c*16 + d;
+ cypher[2] = base[d*4];
+
+ rv = PL_Base64Decode((char *)cypher, 3, result);
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): return value\n", a, b, c, d);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp((char *)plain, result, 2) )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): expected \"%s,\" got \"%.2s.\"\n",
+ a, b, c, d, cypher, result);
+ return PR_FALSE;
+ }
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, triple characters */
+PRBool test_013(void)
+{
+ PRUint32 a, b, c, d, e, f;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char result[ 8 ];
+ char *rv;
+
+ printf("Test 013 (PL_Base64Decode, triple characters) ..."); fflush(stdout);
+
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (a*4) + b;
+ for( c = 0; c < 16; c++ )
+ {
+ cypher[1] = base[b*16 + c];
+ for( d = 0; d < 16; d++ )
+ {
+ plain[1] = c*16 + d;
+ for( e = 0; e < 4; e++ )
+ {
+ cypher[2] = base[d*4 + e];
+ for( f = 0; f < 64; f++ )
+ {
+ plain[2] = e * 64 + f;
+ cypher[3] = base[f];
+
+ rv = PL_Base64Decode((char *)cypher, 4, result);
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): return value\n", a, b, c, d, e, f);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp((char *)plain, result, 3) )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): expected \"%s,\" got \"%.3s.\"\n",
+ a, b, c, d, e, f, plain, result);
+ return PR_FALSE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, random strings */
+PRBool test_014(void)
+{
+ int i;
+ char result[ 4096 ];
+
+ printf("Test 014 (PL_Base64Decode, random strings, equals) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 clen = PL_strlen(array[i].cyphertext);
+ PRUint32 plen = (clen * 3) / 4;
+
+ char *rv = PL_Base64Decode(array[i].cyphertext, clen, result);
+
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d): return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 == (clen & 3) )
+ {
+ if( '=' == array[i].cyphertext[clen-1] )
+ {
+ if( '=' == array[i].cyphertext[clen-2] )
+ {
+ plen -= 2;
+ }
+ else
+ {
+ plen -= 1;
+ }
+ }
+ }
+
+ if( 0 != PL_strncmp(result, array[i].plaintext, plen) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%.*s.\"\n",
+ i, array[i].cyphertext, array[i].plaintext, plen, result);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, random strings */
+PRBool test_015(void)
+{
+ int i;
+ char buffer[ 4096 ];
+ char result[ 4096 ];
+ char *rv;
+
+ printf("Test 015 (PL_Base64Decode, random strings, no equals) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 clen, plen;
+
+ PL_strcpy(buffer, array[i].cyphertext);
+ clen = PL_strlen(buffer);
+
+ if( 0 == (clen & 3) )
+ {
+ if( '=' == buffer[clen-1] )
+ {
+ if( '=' == buffer[clen-2] )
+ {
+ buffer[clen-2] = buffer[clen-1] = (char)0;
+ clen -= 2;
+ }
+ else
+ {
+ buffer[clen-1] = (char)0;
+ clen -= 1;
+ }
+ }
+ }
+
+ plen = (clen * 3) / 4;
+
+ rv = PL_Base64Decode(buffer, clen, result);
+
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d): return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp(result, array[i].plaintext, plen) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%.*s.\"\n",
+ i, array[i].cyphertext, array[i].plaintext, plen, result);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, single characters, malloc */
+PRBool test_016(void)
+{
+ PRUint32 a, b;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char *rv;
+
+ printf("Test 016 (PL_Base64Decode, single characters, equals, malloc) ..."); fflush(stdout);
+
+ plain[1] = plain[2] = plain[3] = (unsigned char)0;
+ cypher[2] = cypher[3] = (unsigned char)'=';
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (unsigned char)(a * 4 + b);
+ cypher[1] = base[(b * 16)];
+
+ rv = PL_Base64Decode((char *)cypher, 4, (char *)0);
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d, %d): no return value\n", a, b);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp((char *)plain, rv) )
+ {
+ printf("FAIL\n\t(%d, %d): expected \"%s,\" got \"%s.\"\n",
+ a, b, plain, rv);
+ PR_DELETE(rv);
+ return PR_FALSE;
+ }
+
+ PR_DELETE(rv);
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, single characters, malloc */
+PRBool test_017(void)
+{
+ PRUint32 a, b;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char *rv;
+
+ printf("Test 017 (PL_Base64Decode, single characters, no equals, malloc) ..."); fflush(stdout);
+
+ plain[1] = plain[2] = plain[3] = (unsigned char)0;
+ cypher[2] = cypher[3] = (unsigned char)0;
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (unsigned char)(a * 4 + b);
+ cypher[1] = base[(b * 16)];
+
+ rv = PL_Base64Decode((char *)cypher, 2, (char *)0);
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d, %d): no return value\n", a, b);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp((char *)plain, rv) )
+ {
+ printf("FAIL\n\t(%d, %d): expected \"%s,\" got \"%s.\"\n",
+ a, b, plain, rv);
+ PR_DELETE(rv);
+ return PR_FALSE;
+ }
+
+ PR_DELETE(rv);
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, double characters, malloc */
+PRBool test_018(void)
+{
+ PRUint32 a, b, c, d;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char *rv;
+
+ printf("Test 018 (PL_Base64Decode, double characters, equals, malloc) ..."); fflush(stdout);
+
+ plain[2] = plain[3] = (unsigned char)0;
+ cypher[3] = (unsigned char)'=';
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (a*4) + b;
+ for( c = 0; c < 16; c++ )
+ {
+ cypher[1] = base[b*16 + c];
+ for( d = 0; d < 16; d++ )
+ {
+ plain[1] = c*16 + d;
+ cypher[2] = base[d*4];
+
+ rv = PL_Base64Decode((char *)cypher, 4, (char *)0);
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): no return value\n", a, b, c, d);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp((char *)plain, rv) )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): expected \"%s,\" got \"%s.\"\n",
+ a, b, c, d, plain, rv);
+ PR_DELETE(rv);
+ return PR_FALSE;
+ }
+
+ PR_DELETE(rv);
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, double characters, malloc */
+PRBool test_019(void)
+{
+ PRUint32 a, b, c, d;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char *rv;
+
+ printf("Test 019 (PL_Base64Decode, double characters, no equals, malloc) ..."); fflush(stdout);
+
+ plain[2] = plain[3] = (unsigned char)0;
+ cypher[3] = (unsigned char)0;
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (a*4) + b;
+ for( c = 0; c < 16; c++ )
+ {
+ cypher[1] = base[b*16 + c];
+ for( d = 0; d < 16; d++ )
+ {
+ plain[1] = c*16 + d;
+ cypher[2] = base[d*4];
+
+ rv = PL_Base64Decode((char *)cypher, 3, (char *)0);
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): no return value\n", a, b, c, d);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp((char *)plain, rv) )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): expected \"%s,\" got \"%s.\"\n",
+ a, b, c, d, cypher, rv);
+ PR_DELETE(rv);
+ return PR_FALSE;
+ }
+
+ PR_DELETE(rv);
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, triple characters, malloc */
+PRBool test_020(void)
+{
+ PRUint32 a, b, c, d, e, f;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char *rv;
+
+ printf("Test 020 (PL_Base64Decode, triple characters, malloc) ..."); fflush(stdout);
+
+ cypher[4] = (unsigned char)0;
+ plain[3] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (a*4) + b;
+ for( c = 0; c < 16; c++ )
+ {
+ cypher[1] = base[b*16 + c];
+ for( d = 0; d < 16; d++ )
+ {
+ plain[1] = c*16 + d;
+ for( e = 0; e < 4; e++ )
+ {
+ cypher[2] = base[d*4 + e];
+ for( f = 0; f < 64; f++ )
+ {
+ plain[2] = e * 64 + f;
+ cypher[3] = base[f];
+
+ rv = PL_Base64Decode((char *)cypher, 4, (char *)0);
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): no return value\n", a, b, c, d, e, f);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp((char *)plain, rv) )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): expected \"%s,\" got \"%.3s.\"\n",
+ a, b, c, d, e, f, plain, rv);
+ PR_DELETE(rv);
+ return PR_FALSE;
+ }
+
+ PR_DELETE(rv);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, random strings, malloc */
+PRBool test_021(void)
+{
+ int i;
+
+ printf("Test 021 (PL_Base64Decode, random strings, equals, malloc) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 clen = PL_strlen(array[i].cyphertext);
+
+ char *rv = PL_Base64Decode(array[i].cyphertext, clen, (char *)0);
+
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d): no return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp(rv, array[i].plaintext) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%s.\"\n",
+ i, array[i].cyphertext, array[i].plaintext, rv);
+ PR_DELETE(rv);
+ return PR_FALSE;
+ }
+
+ PR_DELETE(rv);
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Encode, random strings, malloc */
+PRBool test_022(void)
+{
+ int i;
+ char buffer[ 4096 ];
+ char *rv;
+
+ printf("Test 022 (PL_Base64Decode, random strings, no equals, malloc) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 clen;
+
+ PL_strcpy(buffer, array[i].cyphertext);
+ clen = PL_strlen(buffer);
+
+ if( 0 == (clen & 3) )
+ {
+ if( '=' == buffer[clen-1] )
+ {
+ if( '=' == buffer[clen-2] )
+ {
+ buffer[clen-2] = buffer[clen-1] = (char)0;
+ clen -= 2;
+ }
+ else
+ {
+ buffer[clen-1] = (char)0;
+ clen -= 1;
+ }
+ }
+ }
+
+ rv = PL_Base64Decode(buffer, clen, (char *)0);
+
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d): no return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp(rv, array[i].plaintext) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%s.\"\n",
+ i, array[i].cyphertext, array[i].plaintext, rv);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Encode, random strings */
+PRBool test_023(void)
+{
+ int i;
+ char result[ 4096 ];
+
+ printf("Test 023 (PL_Base64Encode, random strings, strlen) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 plen = PL_strlen(array[i].plaintext);
+ PRUint32 clen = ((plen + 2)/3)*4;
+
+ char *rv = PL_Base64Encode(array[i].plaintext, 0, result);
+
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d): return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp(result, array[i].cyphertext, clen) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%.*s.\"\n",
+ i, array[i].plaintext, array[i].cyphertext, clen, result);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Encode, random strings, malloc */
+PRBool test_024(void)
+{
+ int i;
+
+ printf("Test 024 (PL_Base64Encode, random strings, malloc, strlen) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 plen = PL_strlen(array[i].plaintext);
+ PRUint32 clen = ((plen + 2)/3)*4;
+
+ char *rv = PL_Base64Encode(array[i].plaintext, 0, (char *)0);
+
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d): no return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp(rv, array[i].cyphertext) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%s.\"\n",
+ i, array[i].plaintext, array[i].cyphertext, rv);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, random strings */
+PRBool test_025(void)
+{
+ int i;
+ char result[ 4096 ];
+
+ printf("Test 025 (PL_Base64Decode, random strings, equals, strlen) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 clen = PL_strlen(array[i].cyphertext);
+ PRUint32 plen = (clen * 3) / 4;
+
+ char *rv = PL_Base64Decode(array[i].cyphertext, 0, result);
+
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d): return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 == (clen & 3) )
+ {
+ if( '=' == array[i].cyphertext[clen-1] )
+ {
+ if( '=' == array[i].cyphertext[clen-2] )
+ {
+ plen -= 2;
+ }
+ else
+ {
+ plen -= 1;
+ }
+ }
+ }
+
+ if( 0 != PL_strncmp(result, array[i].plaintext, plen) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%.*s.\"\n",
+ i, array[i].cyphertext, array[i].plaintext, plen, result);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, random strings */
+PRBool test_026(void)
+{
+ int i;
+ char buffer[ 4096 ];
+ char result[ 4096 ];
+ char *rv;
+
+ printf("Test 026 (PL_Base64Decode, random strings, no equals, strlen) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 clen, plen;
+
+ PL_strcpy(buffer, array[i].cyphertext);
+ clen = PL_strlen(buffer);
+
+ if( 0 == (clen & 3) )
+ {
+ if( '=' == buffer[clen-1] )
+ {
+ if( '=' == buffer[clen-2] )
+ {
+ buffer[clen-2] = buffer[clen-1] = (char)0;
+ clen -= 2;
+ }
+ else
+ {
+ buffer[clen-1] = (char)0;
+ clen -= 1;
+ }
+ }
+ }
+
+ plen = (clen * 3) / 4;
+
+ rv = PL_Base64Decode(buffer, 0, result);
+
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d): return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp(result, array[i].plaintext, plen) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%.*s.\"\n",
+ i, array[i].cyphertext, array[i].plaintext, plen, result);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, random strings, malloc */
+PRBool test_027(void)
+{
+ int i;
+
+ printf("Test 027 (PL_Base64Decode, random strings, equals, malloc, strlen) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 clen = PL_strlen(array[i].cyphertext);
+
+ char *rv = PL_Base64Decode(array[i].cyphertext, 0, (char *)0);
+
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d): no return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp(rv, array[i].plaintext) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%s.\"\n",
+ i, array[i].cyphertext, array[i].plaintext, rv);
+ PR_DELETE(rv);
+ return PR_FALSE;
+ }
+
+ PR_DELETE(rv);
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Encode, random strings, malloc */
+PRBool test_028(void)
+{
+ int i;
+ char buffer[ 4096 ];
+ char *rv;
+
+ printf("Test 028 (PL_Base64Decode, random strings, no equals, malloc, strlen) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 clen;
+
+ PL_strcpy(buffer, array[i].cyphertext);
+ clen = PL_strlen(buffer);
+
+ if( 0 == (clen & 3) )
+ {
+ if( '=' == buffer[clen-1] )
+ {
+ if( '=' == buffer[clen-2] )
+ {
+ buffer[clen-2] = buffer[clen-1] = (char)0;
+ clen -= 2;
+ }
+ else
+ {
+ buffer[clen-1] = (char)0;
+ clen -= 1;
+ }
+ }
+ }
+
+ rv = PL_Base64Decode(buffer, 0, (char *)0);
+
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d): no return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp(rv, array[i].plaintext) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%s.\"\n",
+ i, array[i].cyphertext, array[i].plaintext, rv);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+int
+main
+(
+ int argc,
+ char *argv[]
+)
+{
+ printf("Testing the Portable Library base64 functions:\n");
+ printf("(warning: the \"triple characters\" tests are slow)\n");
+
+ if( 1
+ && test_001()
+ && test_002()
+ && test_003()
+ && test_004()
+ && test_005()
+ && test_006()
+ && test_007()
+ && test_008()
+ && test_009()
+ && test_010()
+ && test_011()
+ && test_012()
+ && test_013()
+ && test_014()
+ && test_015()
+ && test_016()
+ && test_017()
+ && test_018()
+ && test_019()
+ && test_020()
+ && test_021()
+ && test_022()
+ && test_023()
+ && test_024()
+ && test_025()
+ && test_026()
+ && test_027()
+ && test_028()
+ )
+ {
+ printf("Suite passed.\n");
+ return 0;
+ }
+ else
+ {
+ printf("Suite failed.\n");
+ return 1;
+ }
+
+ /*NOTREACHED*/
+}
diff --git a/nsprpub/lib/tests/getopt.c b/nsprpub/lib/tests/getopt.c
new file mode 100644
index 0000000000..dc3ea39fce
--- /dev/null
+++ b/nsprpub/lib/tests/getopt.c
@@ -0,0 +1,45 @@
+/* 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/. */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "nspr.h"
+#include "plgetopt.h"
+
+
+
+static const PLLongOpt optArray[] = {
+ { "longa", 'a', PR_TRUE },
+ { "longb", 'b', PR_TRUE },
+ { "longc", 'c', PR_FALSE },
+ { "longd", 'd' | 0x100, PR_TRUE },
+ { "longe", 'e' | 0x100, PR_FALSE },
+ { NULL, }
+};
+
+int
+main(int argc, char **argv)
+{
+ PLOptState *opt;
+ PLOptStatus ostat;
+
+ opt = PL_CreateLongOptState(argc, argv, "a:b:c", optArray);
+
+ while (PL_OPT_OK == (ostat = PL_GetNextOpt(opt))) {
+ if (opt->option == 0 && opt->longOptIndex < 0) {
+ printf("Positional parameter: \"%s\"\n", opt->value);
+ }
+ else
+ printf("%s option: %x (\'%c\', index %d), argument: \"%s\"\n",
+ (ostat == PL_OPT_BAD) ? "BAD" : "GOOD",
+ opt->longOption, opt->option ? opt->option : ' ',
+ opt->longOptIndex, opt->value);
+
+ }
+ printf("last result was %s\n", (ostat == PL_OPT_BAD) ? "BAD" : "EOL");
+ PL_DestroyOptState(opt);
+ return 0;
+}
diff --git a/nsprpub/lib/tests/string.c b/nsprpub/lib/tests/string.c
new file mode 100644
index 0000000000..7765d12dc1
--- /dev/null
+++ b/nsprpub/lib/tests/string.c
@@ -0,0 +1,3128 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "plstr.h"
+#include "nspr.h"
+
+#include <stdio.h>
+
+/* PL_strlen */
+PRBool test_001(void)
+{
+ static struct
+ {
+ const char *str;
+ PRUint32 len;
+ } array[] =
+ {
+ { (const char *)0, 0 },
+ { "", 0 },
+ { "a", 1 },
+ { "abcdefg", 7 },
+ { "abcdefg\0hijk", 7 }
+ };
+
+ int i;
+
+ printf("Test 001 (PL_strlen) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ if( PL_strlen(array[i].str) != array[i].len )
+ {
+ printf("FAIL (%d: %s->%d, %d)\n", i,
+ array[i].str ? array[i].str : "(null)",
+ PL_strlen(array[i].str), array[i].len);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strnlen */
+PRBool test_002(void)
+{
+ static struct
+ {
+ const char *str;
+ PRUint32 max;
+ PRUint32 len;
+ } array[] =
+ {
+ { (const char *)0, 0, 0 },
+ { (const char *)0, 12, 0 },
+ { "", 0, 0 },
+ { "", 12, 0 },
+ { "a", 0, 0 },
+ { "a", 1, 1 },
+ { "a", 12, 1 },
+ { "abcdefg", 0, 0 },
+ { "abcdefg", 1, 1 },
+ { "abcdefg", 7, 7 },
+ { "abcdefg", 12, 7 },
+ { "abcdefg\0hijk", 0, 0 },
+ { "abcdefg\0hijk", 1, 1 },
+ { "abcdefg\0hijk", 7, 7 },
+ { "abcdefg\0hijk", 12, 7 },
+ };
+
+ int i;
+
+ printf("Test 002 (PL_strnlen) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ if( PL_strnlen(array[i].str, array[i].max) != array[i].len )
+ {
+ printf("FAIL (%d: %s,%d->%d, %d)\n", i,
+ array[i].str ? array[i].str : "(null)", array[i].max,
+ PL_strnlen(array[i].str, array[i].max), array[i].len);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strcpy */
+PRBool test_003(void)
+{
+ static char buffer[ 1024 ];
+
+ static struct
+ {
+ const char *str;
+ char *dest;
+ char *rv;
+ PRBool comp;
+ } array[] =
+ {
+ { (const char *)0, (char *)0, (char *)0, PR_FALSE },
+ { (const char *)0, buffer, (char *)0, PR_FALSE },
+ { "", (char *)0, (char *)0, PR_FALSE },
+ { "", buffer, buffer, PR_TRUE },
+ { "a", (char *)0, (char *)0, PR_FALSE },
+ { "a", buffer, buffer, PR_TRUE },
+ { "abcdefg", (char *)0, (char *)0, PR_FALSE },
+ { "abcdefg", buffer, buffer, PR_TRUE },
+ { "wxyz\0abcdefg", (char *)0, (char *)0, PR_FALSE },
+ { "wxyz\0abcdefg", buffer, buffer, PR_TRUE }
+ };
+
+ int i;
+
+ printf("Test 003 (PL_strcpy) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv;
+ const char *a = array[i].str;
+ const char *b = (const char *)array[i].dest;
+
+ rv = PL_strcpy(array[i].dest, array[i].str);
+ if( array[i].rv != rv )
+ {
+ printf("FAIL %d: (0x%x, %s)->0x%x\n", i, array[i].dest,
+ array[i].str ? array[i].str : "(null)", rv);
+ return PR_FALSE;
+ }
+
+ if( array[i].comp )
+ {
+ while( 1 )
+ {
+ if( *a != *b )
+ {
+ printf("FAIL %d: %s->%.32s\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].dest ? array[i].dest : "(null)");
+ return PR_FALSE;
+ }
+
+ if( (char)0 == *a ) {
+ break;
+ }
+
+ a++;
+ b++;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strncpy */
+PRBool test_004(void)
+{
+ static char buffer[ 1024 ];
+
+ static struct
+ {
+ const char *str;
+ PRUint32 len;
+ char *dest;
+ char *rv;
+ PRBool comp;
+ const char *result;
+ PRBool nulled;
+ } array[] =
+ {
+ { (const char *)0, 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { (const char *)0, 0, buffer, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { (const char *)0, 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { (const char *)0, 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { (const char *)0, 1, buffer, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { (const char *)0, 7, buffer, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "", 0, buffer, buffer, PR_FALSE, (const char *)0, PR_FALSE },
+ { "", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "", 1, buffer, buffer, PR_TRUE, "", PR_TRUE },
+ { "", 7, buffer, buffer, PR_TRUE, "", PR_TRUE },
+ { "a", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "a", 0, buffer, buffer, PR_FALSE, (const char *)0, PR_FALSE },
+ { "a", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "a", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "b", 1, buffer, buffer, PR_TRUE, "b", PR_FALSE },
+ { "c", 7, buffer, buffer, PR_TRUE, "c", PR_TRUE },
+ { "de", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "de", 0, buffer, buffer, PR_FALSE, (const char *)0, PR_FALSE },
+ { "de", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "de", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "fg", 1, buffer, buffer, PR_TRUE, "f", PR_FALSE },
+ { "hi", 7, buffer, buffer, PR_TRUE, "hi", PR_TRUE },
+ { "jklmnopq", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "jklmnopq", 0, buffer, buffer, PR_FALSE, (const char *)0, PR_FALSE },
+ { "jklmnopq", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "jklmnopq", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "rstuvwxy", 1, buffer, buffer, PR_TRUE, "r", PR_FALSE },
+ { "zABCDEFG", 7, buffer, buffer, PR_TRUE, "zABCDEF", PR_FALSE },
+ { "a\0XXX", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "a\0XXX", 0, buffer, buffer, PR_FALSE, (const char *)0, PR_FALSE },
+ { "a\0XXX", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "a\0XXX", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "b\0XXX", 1, buffer, buffer, PR_TRUE, "b", PR_FALSE },
+ { "c\0XXX", 7, buffer, buffer, PR_TRUE, "c", PR_TRUE },
+ { "de\0XXX", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "de\0XXX", 0, buffer, buffer, PR_FALSE, (const char *)0, PR_FALSE },
+ { "de\0XXX", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "de\0XXX", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "fg\0XXX", 1, buffer, buffer, PR_TRUE, "f", PR_FALSE },
+ { "hi\0XXX", 7, buffer, buffer, PR_TRUE, "hi", PR_TRUE },
+ { "jklmnopq\0XXX", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "jklmnopq\0XXX", 0, buffer, buffer, PR_FALSE, (const char *)0, PR_FALSE },
+ { "jklmnopq\0XXX", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "jklmnopq\0XXX", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "rstuvwxy\0XXX", 1, buffer, buffer, PR_TRUE, "r", PR_FALSE },
+ { "zABCDEFG\0XXX", 7, buffer, buffer, PR_TRUE, "zABCDEF", PR_FALSE },
+ };
+
+ int i;
+
+ printf("Test 004 (PL_strncpy) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv;
+ int j;
+
+ for( j = 0; j < sizeof(buffer); j++ ) {
+ buffer[j] = '-';
+ }
+
+ rv = PL_strncpy(array[i].dest, array[i].str, array[i].len);
+ if( array[i].rv != rv )
+ {
+ printf("FAIL %d: (0x%x, %s, %lu)->0x%x\n", i, array[i].dest,
+ array[i].str ? array[i].str : "(null)", array[i].len, rv);
+ return PR_FALSE;
+ }
+
+ if( array[i].comp )
+ {
+ const char *a = array[i].result;
+ const char *b = array[i].dest;
+
+ while( *a )
+ {
+ if( *a != *b )
+ {
+ printf("FAIL %d: %s != %.32s\n", i,
+ array[i].result, array[i].dest);
+ return PR_FALSE;
+ }
+
+ a++;
+ b++;
+ }
+
+ if( array[i].nulled )
+ {
+ if( *b != '\0' )
+ {
+ printf("FAIL %d: not terminated\n", i);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( *b != '-' )
+ {
+ printf("FAIL %d: overstepped\n", i);
+ return PR_FALSE;
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strncpyz */
+PRBool test_005(void)
+{
+ static char buffer[ 1024 ];
+
+ static struct
+ {
+ const char *str;
+ PRUint32 len;
+ char *dest;
+ char *rv;
+ PRBool comp;
+ const char *result;
+ } array[] =
+ {
+ { (const char *)0, 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { (const char *)0, 0, buffer, (char *)0, PR_FALSE, (const char *)0 },
+ { (const char *)0, 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { (const char *)0, 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { (const char *)0, 1, buffer, (char *)0, PR_FALSE, (const char *)0 },
+ { (const char *)0, 7, buffer, (char *)0, PR_FALSE, (const char *)0 },
+ { "", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "", 0, buffer, (char *)0, PR_FALSE, (const char *)0 },
+ { "", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "", 1, buffer, buffer, PR_TRUE, "" },
+ { "", 7, buffer, buffer, PR_TRUE, "" },
+ { "a", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "a", 0, buffer, (char *)0, PR_FALSE, (const char *)0 },
+ { "a", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "a", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "b", 1, buffer, buffer, PR_TRUE, "" },
+ { "c", 7, buffer, buffer, PR_TRUE, "c" },
+ { "de", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "de", 0, buffer, (char *)0, PR_FALSE, (const char *)0 },
+ { "de", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "de", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "fg", 1, buffer, buffer, PR_TRUE, "" },
+ { "hi", 7, buffer, buffer, PR_TRUE, "hi" },
+ { "jklmnopq", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "jklmnopq", 0, buffer, (char *)0, PR_FALSE, (const char *)0 },
+ { "jklmnopq", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "jklmnopq", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "rstuvwxy", 1, buffer, buffer, PR_TRUE, "" },
+ { "zABCDEFG", 7, buffer, buffer, PR_TRUE, "zABCDE" },
+ { "a\0XXX", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "a\0XXX", 0, buffer, (char *)0, PR_FALSE, (const char *)0 },
+ { "a\0XXX", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "a\0XXX", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "b\0XXX", 1, buffer, buffer, PR_TRUE, "" },
+ { "c\0XXX", 7, buffer, buffer, PR_TRUE, "c" },
+ { "de\0XXX", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "de\0XXX", 0, buffer, (char *)0, PR_FALSE, (const char *)0 },
+ { "de\0XXX", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "de\0XXX", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "fg\0XXX", 1, buffer, buffer, PR_TRUE, "" },
+ { "hi\0XXX", 7, buffer, buffer, PR_TRUE, "hi" },
+ { "jklmnopq\0XXX", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "jklmnopq\0XXX", 0, buffer, (char *)0, PR_FALSE, (const char *)0 },
+ { "jklmnopq\0XXX", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "jklmnopq\0XXX", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "rstuvwxy\0XXX", 1, buffer, buffer, PR_TRUE, "" },
+ { "zABCDEFG\0XXX", 7, buffer, buffer, PR_TRUE, "zABCDE" },
+ };
+
+ int i;
+
+ printf("Test 005 (PL_strncpyz) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv;
+ int j;
+
+ for( j = 0; j < sizeof(buffer); j++ ) {
+ buffer[j] = '-';
+ }
+
+ rv = PL_strncpyz(array[i].dest, array[i].str, array[i].len);
+ if( array[i].rv != rv )
+ {
+ printf("FAIL %d: (0x%x, %s, %lu)->0x%x\n", i, array[i].dest,
+ array[i].str ? array[i].str : "(null)", array[i].len, rv);
+ return PR_FALSE;
+ }
+
+ if( array[i].comp )
+ {
+ const char *a = array[i].result;
+ const char *b = array[i].dest;
+
+ while( 1 )
+ {
+ if( *a != *b )
+ {
+ printf("FAIL %d: %s != %.32s\n", i,
+ array[i].result, array[i].dest);
+ return PR_FALSE;
+ }
+
+ if( (char)0 == *a ) {
+ break;
+ }
+
+ a++;
+ b++;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strdup */
+PRBool test_006(void)
+{
+ static const char *array[] =
+ {
+ (const char *)0,
+ "",
+ "a",
+ "abcdefg"
+ };
+
+ int i;
+
+ printf("Test 006 (PL_strdup) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strdup(array[i]);
+
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: 0x%x -> 0\n", i, array[i]);
+ return PR_FALSE;
+ }
+
+ if( (const char *)0 == array[i] )
+ {
+ if( (char)0 != *rv )
+ {
+ printf("FAIL %d: (const char *)0 -> %.32s\n", i, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ const char *a = array[i];
+ const char *b = (const char *)rv;
+
+ while( 1 )
+ {
+ if( *a != *b )
+ {
+ printf("FAIL %d: %s != %.32s\n", i, array[i], rv);
+ return PR_FALSE;
+ }
+
+ if( (char)0 == *a ) {
+ break;
+ }
+
+ a++;
+ b++;
+ }
+
+ }
+ PL_strfree(rv);
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strndup */
+PRBool test_007(void)
+{
+ static struct
+ {
+ const char *str;
+ PRUint32 len;
+ const char *result;
+ } array[] =
+ {
+ { (const char *)0, 0, "" },
+ { (const char *)0, 1, "" },
+ { (const char *)0, 7, "" },
+ { "", 0, "" },
+ { "", 1, "" },
+ { "", 7, "" },
+ { "a", 0, "" },
+ { "a", 1, "a" },
+ { "a", 7, "a" },
+ { "ab", 0, "" },
+ { "ab", 1, "a" },
+ { "ab", 7, "ab" },
+ { "abcdefg", 0, "" },
+ { "abcdefg", 1, "a" },
+ { "abcdefg", 7, "abcdefg" },
+ { "abcdefghijk", 0, "" },
+ { "abcdefghijk", 1, "a" },
+ { "abcdefghijk", 7, "abcdefg" },
+ { "abcdef\0ghijk", 0, "" },
+ { "abcdef\0ghijk", 1, "a" },
+ { "abcdef\0ghijk", 7, "abcdef" }
+ };
+
+ int i;
+
+ printf("Test 007 (PL_strndup) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strndup(array[i].str, array[i].len);
+ const char *a;
+ const char *b;
+
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%lu -> 0\n", i,
+ array[i].str ? array[i].str : "(null)", array[i].len);
+ return PR_FALSE;
+ }
+
+ a = array[i].result;
+ b = (const char *)rv;
+
+ while( 1 )
+ {
+ if( *a != *b )
+ {
+ printf("FAIL %d: %s != %.32s\n", i, array[i].result, rv);
+ return PR_FALSE;
+ }
+
+ if( (char)0 == *a ) {
+ break;
+ }
+
+ a++;
+ b++;
+ }
+
+ free(rv);
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strcat */
+PRBool test_008(void)
+{
+ static struct
+ {
+ const char *first;
+ const char *second;
+ const char *result;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, (const char *)0 },
+ { (const char *)0, "xyz", (const char *)0 },
+ { "", (const char *)0, "" },
+ { "", "", "" },
+ { "ab", "", "ab" },
+ { "cd", "ef", "cdef" },
+ { "gh\0X", "", "gh" },
+ { "ij\0X", "kl", "ijkl" },
+ { "mn\0X", "op\0X", "mnop" },
+ { "qr", "st\0X", "qrst" },
+ { "uv\0X", "wx\0X", "uvwx" }
+ };
+
+ int i;
+
+ printf("Test 008 (PL_strcat) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char buffer[ 1024 ];
+ int j;
+ char *rv;
+
+ for( j = 0; j < sizeof(buffer); j++ ) {
+ buffer[j] = '-';
+ }
+
+ if( (const char *)0 != array[i].first ) {
+ (void)PL_strcpy(buffer, array[i].first);
+ }
+
+ rv = PL_strcat(((const char *)0 == array[i].first) ? (char *)0 : buffer,
+ array[i].second);
+
+ if( (const char *)0 == array[i].result )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s+%s -> %.32s, not zero\n", i,
+ array[i].first ? array[i].first : "(null)",
+ array[i].second ? array[i].second : "(null)",
+ rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s+%s -> null, not %s\n", i,
+ array[i].first ? array[i].first : "(null)",
+ array[i].second ? array[i].second : "(null)",
+ array[i].result);
+ return PR_FALSE;
+ }
+ else
+ {
+ const char *a = array[i].result;
+ const char *b = (const char *)rv;
+
+ while( 1 )
+ {
+ if( *a != *b )
+ {
+ printf("FAIL %d: %s+%s -> %.32s, not %s\n", i,
+ array[i].first ? array[i].first : "(null)",
+ array[i].second ? array[i].second : "(null)",
+ rv, array[i].result);
+ return PR_FALSE;
+ }
+
+ if( (char)0 == *a ) {
+ break;
+ }
+
+ a++;
+ b++;
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strncat */
+PRBool test_009(void)
+{
+ static struct
+ {
+ const char *first;
+ const char *second;
+ PRUint32 length;
+ PRBool nulled;
+ const char *result;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 0, PR_FALSE, (const char *)0 },
+ { (const char *)0, (const char *)0, 1, PR_FALSE, (const char *)0 },
+ { (const char *)0, (const char *)0, 7, PR_FALSE, (const char *)0 },
+ { (const char *)0, "", 0, PR_FALSE, (const char *)0 },
+ { (const char *)0, "", 1, PR_FALSE, (const char *)0 },
+ { (const char *)0, "", 7, PR_FALSE, (const char *)0 },
+ { (const char *)0, "stuff", 0, PR_FALSE, (const char *)0 },
+ { (const char *)0, "stuff", 1, PR_FALSE, (const char *)0 },
+ { (const char *)0, "stuff", 7, PR_FALSE, (const char *)0 },
+ { "", (const char *)0, 0, PR_TRUE, "" },
+ { "", (const char *)0, 1, PR_TRUE, "" },
+ { "", (const char *)0, 7, PR_TRUE, "" },
+ { "", "", 0, PR_TRUE, "" },
+ { "", "", 1, PR_TRUE, "" },
+ { "", "", 7, PR_TRUE, "" },
+ { "", "abcdefgh", 0, PR_TRUE, "" },
+ { "", "abcdefgh", 1, PR_FALSE, "a" },
+ { "", "abcdefgh", 7, PR_FALSE, "abcdefg" },
+ { "xyz", (const char *)0, 0, PR_TRUE, "xyz" },
+ { "xyz", (const char *)0, 1, PR_TRUE, "xyz" },
+ { "xyz", (const char *)0, 7, PR_TRUE, "xyz" },
+ { "xyz", "", 0, PR_TRUE, "xyz" },
+ { "xyz", "", 1, PR_TRUE, "xyz" },
+ { "xyz", "", 7, PR_TRUE, "xyz" },
+ { "xyz", "abcdefgh", 0, PR_TRUE, "xyz" },
+ { "xyz", "abcdefgh", 1, PR_FALSE, "xyza" },
+ { "xyz", "abcdefgh", 7, PR_FALSE, "xyzabcdefg" }
+ };
+
+ int i;
+
+ printf("Test 009 (PL_strncat) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char buffer[ 1024 ];
+ int j;
+ char *rv;
+
+ for( j = 0; j < sizeof(buffer); j++ ) {
+ buffer[j] = '-';
+ }
+
+ if( (const char *)0 != array[i].first ) {
+ (void)PL_strcpy(buffer, array[i].first);
+ }
+
+ rv = PL_strncat(((const char *)0 == array[i].first) ? (char *)0 : buffer,
+ array[i].second, array[i].length);
+
+ if( (const char *)0 == array[i].result )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s+%s/%lu -> %.32s, not zero\n", i,
+ array[i].first ? array[i].first : "(null)",
+ array[i].second ? array[i].second : "(null)",
+ array[i].length, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s+%s/%lu -> null, not %s\n", i,
+ array[i].first ? array[i].first : "(null)",
+ array[i].second ? array[i].second : "(null)",
+ array[i].length, array[i].result);
+ return PR_FALSE;
+ }
+ else
+ {
+ const char *a = array[i].result;
+ const char *b = (const char *)rv;
+
+ while( *a )
+ {
+ if( *a != *b )
+ {
+ printf("FAIL %d: %s+%s/%lu -> %.32s, not %s\n", i,
+ array[i].first ? array[i].first : "(null)",
+ array[i].second ? array[i].second : "(null)",
+ array[i].length, rv, array[i].result);
+ return PR_FALSE;
+ }
+
+ a++;
+ b++;
+ }
+
+ if( array[i].nulled )
+ {
+ if( (char)0 != *b )
+ {
+ printf("FAIL %d: %s+%s/%lu -> not nulled\n", i,
+ array[i].first ? array[i].first : "(null)",
+ array[i].second ? array[i].second : "(null)",
+ array[i].length);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char)0 == *b )
+ {
+ printf("FAIL %d: %s+%s/%lu -> overrun\n", i,
+ array[i].first ? array[i].first : "(null)",
+ array[i].second ? array[i].second : "(null)",
+ array[i].length);
+ return PR_FALSE;
+ }
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strcatn */
+PRBool test_010(void)
+{
+ static struct
+ {
+ const char *first;
+ const char *second;
+ PRUint32 length;
+ const char *result;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 0, (const char *)0 },
+ { (const char *)0, (const char *)0, 1, (const char *)0 },
+ { (const char *)0, (const char *)0, 7, (const char *)0 },
+ { (const char *)0, "", 0, (const char *)0 },
+ { (const char *)0, "", 1, (const char *)0 },
+ { (const char *)0, "", 7, (const char *)0 },
+ { (const char *)0, "stuff", 0, (const char *)0 },
+ { (const char *)0, "stuff", 1, (const char *)0 },
+ { (const char *)0, "stuff", 7, (const char *)0 },
+ { "", (const char *)0, 0, "" },
+ { "", (const char *)0, 1, "" },
+ { "", (const char *)0, 7, "" },
+ { "", "", 0, "" },
+ { "", "", 1, "" },
+ { "", "", 7, "" },
+ { "", "abcdefgh", 0, "" },
+ { "", "abcdefgh", 1, "" },
+ { "", "abcdefgh", 7, "abcdef" },
+ { "xyz", (const char *)0, 0, "xyz" },
+ { "xyz", (const char *)0, 1, "xyz" },
+ { "xyz", (const char *)0, 7, "xyz" },
+ { "xyz", "", 0, "xyz" },
+ { "xyz", "", 1, "xyz" },
+ { "xyz", "", 7, "xyz" },
+ { "xyz", "abcdefgh", 0, "xyz" },
+ { "xyz", "abcdefgh", 1, "xyz" },
+ { "xyz", "abcdefgh", 7, "xyzabc" }
+ };
+
+ int i;
+
+ printf("Test 010 (PL_strcatn) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char buffer[ 1024 ];
+ int j;
+ char *rv;
+
+ for( j = 0; j < sizeof(buffer); j++ ) {
+ buffer[j] = '-';
+ }
+
+ if( (const char *)0 != array[i].first ) {
+ (void)PL_strcpy(buffer, array[i].first);
+ }
+
+ rv = PL_strcatn(((const char *)0 == array[i].first) ? (char *)0 : buffer,
+ array[i].length, array[i].second);
+
+ if( (const char *)0 == array[i].result )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s+%s/%lu -> %.32s, not zero\n", i,
+ array[i].first ? array[i].first : "(null)",
+ array[i].second ? array[i].second : "(null)",
+ array[i].length, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s+%s/%lu -> null, not %s\n", i,
+ array[i].first ? array[i].first : "(null)",
+ array[i].second ? array[i].second : "(null)",
+ array[i].length, array[i].result);
+ return PR_FALSE;
+ }
+ else
+ {
+ const char *a = array[i].result;
+ const char *b = (const char *)rv;
+
+ while( 1 )
+ {
+ if( *a != *b )
+ {
+ printf("FAIL %d: %s+%s/%lu -> %.32s, not %s\n", i,
+ array[i].first ? array[i].first : "(null)",
+ array[i].second ? array[i].second : "(null)",
+ array[i].length, rv, array[i].result);
+ return PR_FALSE;
+ }
+
+ if( (char)0 == *a ) {
+ break;
+ }
+
+ a++;
+ b++;
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strcmp */
+PRBool test_011(void)
+{
+ static struct
+ {
+ const char *one;
+ const char *two;
+ PRIntn sign;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 0 },
+ { (const char *)0, "word", -1 },
+ { "word", (const char *)0, 1 },
+ { "word", "word", 0 },
+ { "aZYXVUT", "bZYXVUT", -1 },
+ { "aZYXVUT", "bAAAAAA", -1 },
+ { "a", "aa", -1 },
+ { "a", "a", 0 },
+ { "a", "A", 1 },
+ { "aaaaa", "baaaa", -1 },
+ { "aaaaa", "abaaa", -1 },
+ { "aaaaa", "aabaa", -1 },
+ { "aaaaa", "aaaba", -1 },
+ { "aaaaa", "aaaab", -1 },
+ { "bZYXVUT", "aZYXVUT", 1 },
+ { "bAAAAAA", "aZYXVUT", 1 },
+ { "aa", "a", 1 },
+ { "A", "a", -1 },
+ { "baaaa", "aaaaa", 1 },
+ { "abaaa", "aaaaa", 1 },
+ { "aabaa", "aaaaa", 1 },
+ { "aaaba", "aaaaa", 1 },
+ { "aaaab", "aaaaa", 1 },
+ { "word", "Word", 1 },
+ { "word", "wOrd", 1 },
+ { "word", "woRd", 1 },
+ { "word", "worD", 1 },
+ { "WORD", "wORD", -1 },
+ { "WORD", "WoRD", -1 },
+ { "WORD", "WOrD", -1 },
+ { "WORD", "WORd", -1 }
+ };
+
+ int i;
+
+ printf("Test 011 (PL_strcmp) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRIntn rv = PL_strcmp(array[i].one, array[i].two);
+
+ switch( array[i].sign )
+ {
+ case -1:
+ if( rv < 0 ) {
+ continue;
+ }
+ break;
+ case 1:
+ if( rv > 0 ) {
+ continue;
+ }
+ break;
+ case 0:
+ if( 0 == rv ) {
+ continue;
+ }
+ break;
+ default:
+ PR_NOT_REACHED("static data inconsistancy");
+ break;
+ }
+
+ printf("FAIL %d: %s-%s -> %d, not %d\n", i,
+ array[i].one ? array[i].one : "(null)",
+ array[i].two ? array[i].two : "(null)",
+ rv, array[i].sign);
+ return PR_FALSE;
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strncmp */
+PRBool test_012(void)
+{
+ static struct
+ {
+ const char *one;
+ const char *two;
+ PRUint32 max;
+ PRIntn sign;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 0, 0 },
+ { (const char *)0, (const char *)0, 1, 0 },
+ { (const char *)0, (const char *)0, 4, 0 },
+ { (const char *)0, "word", 0, -1 },
+ { (const char *)0, "word", 1, -1 },
+ { (const char *)0, "word", 4, -1 },
+ { "word", (const char *)0, 0, 1 },
+ { "word", (const char *)0, 1, 1 },
+ { "word", (const char *)0, 4, 1 },
+ { "word", "word", 0, 0 },
+ { "word", "word", 1, 0 },
+ { "word", "word", 3, 0 },
+ { "word", "word", 5, 0 },
+ { "aZYXVUT", "bZYXVUT", 0, 0 },
+ { "aZYXVUT", "bZYXVUT", 1, -1 },
+ { "aZYXVUT", "bZYXVUT", 4, -1 },
+ { "aZYXVUT", "bZYXVUT", 9, -1 },
+ { "aZYXVUT", "bAAAAAA", 0, 0 },
+ { "aZYXVUT", "bAAAAAA", 1, -1 },
+ { "aZYXVUT", "bAAAAAA", 4, -1 },
+ { "aZYXVUT", "bAAAAAA", 5, -1 },
+ { "a", "aa", 0, 0 },
+ { "a", "aa", 1, 0 },
+ { "a", "aa", 4, -1 },
+ { "a", "a", 0, 0 },
+ { "a", "a", 1, 0 },
+ { "a", "a", 4, 0 },
+ { "a", "A", 0, 0 },
+ { "a", "A", 1, 1 },
+ { "a", "A", 4, 1 },
+ { "aaaaa", "baaaa", 0, 0 },
+ { "aaaaa", "baaaa", 1, -1 },
+ { "aaaaa", "baaaa", 4, -1 },
+ { "aaaaa", "abaaa", 0, 0 },
+ { "aaaaa", "abaaa", 1, 0 },
+ { "aaaaa", "abaaa", 4, -1 },
+ { "aaaaa", "aabaa", 0, 0 },
+ { "aaaaa", "aabaa", 1, 0 },
+ { "aaaaa", "aabaa", 4, -1 },
+ { "aaaaa", "aaaba", 0, 0 },
+ { "aaaaa", "aaaba", 1, 0 },
+ { "aaaaa", "aaaba", 4, -1 },
+ { "aaaaa", "aaaab", 0, 0 },
+ { "aaaaa", "aaaab", 1, 0 },
+ { "aaaaa", "aaaab", 4, 0 },
+ { "bZYXVUT", "aZYXVUT", 0, 0 },
+ { "bZYXVUT", "aZYXVUT", 1, 1 },
+ { "bZYXVUT", "aZYXVUT", 4, 1 },
+ { "bAAAAAA", "aZYXVUT", 0, 0 },
+ { "bAAAAAA", "aZYXVUT", 1, 1 },
+ { "bAAAAAA", "aZYXVUT", 4, 1 },
+ { "aa", "a", 0, 0 },
+ { "aa", "a", 1, 0 },
+ { "aa", "a", 4, 1 },
+ { "A", "a", 0, 0 },
+ { "A", "a", 1, -1 },
+ { "A", "a", 4, -1 },
+ { "baaaa", "aaaaa", 0, 0 },
+ { "baaaa", "aaaaa", 1, 1 },
+ { "baaaa", "aaaaa", 4, 1 },
+ { "abaaa", "aaaaa", 0, 0 },
+ { "abaaa", "aaaaa", 1, 0 },
+ { "abaaa", "aaaaa", 4, 1 },
+ { "aabaa", "aaaaa", 0, 0 },
+ { "aabaa", "aaaaa", 1, 0 },
+ { "aabaa", "aaaaa", 4, 1 },
+ { "aaaba", "aaaaa", 0, 0 },
+ { "aaaba", "aaaaa", 1, 0 },
+ { "aaaba", "aaaaa", 4, 1 },
+ { "aaaab", "aaaaa", 0, 0 },
+ { "aaaab", "aaaaa", 1, 0 },
+ { "aaaab", "aaaaa", 4, 0 },
+ { "word", "Word", 0, 0 },
+ { "word", "Word", 1, 1 },
+ { "word", "Word", 3, 1 },
+ { "word", "wOrd", 0, 0 },
+ { "word", "wOrd", 1, 0 },
+ { "word", "wOrd", 3, 1 },
+ { "word", "woRd", 0, 0 },
+ { "word", "woRd", 1, 0 },
+ { "word", "woRd", 3, 1 },
+ { "word", "worD", 0, 0 },
+ { "word", "worD", 1, 0 },
+ { "word", "worD", 3, 0 },
+ { "WORD", "wORD", 0, 0 },
+ { "WORD", "wORD", 1, -1 },
+ { "WORD", "wORD", 3, -1 },
+ { "WORD", "WoRD", 0, 0 },
+ { "WORD", "WoRD", 1, 0 },
+ { "WORD", "WoRD", 3, -1 },
+ { "WORD", "WOrD", 0, 0 },
+ { "WORD", "WOrD", 1, 0 },
+ { "WORD", "WOrD", 3, -1 },
+ { "WORD", "WORd", 0, 0 },
+ { "WORD", "WORd", 1, 0 },
+ { "WORD", "WORd", 3, 0 }
+
+ };
+
+ int i;
+
+ printf("Test 012 (PL_strncmp) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRIntn rv = PL_strncmp(array[i].one, array[i].two, array[i].max);
+
+ switch( array[i].sign )
+ {
+ case -1:
+ if( rv < 0 ) {
+ continue;
+ }
+ break;
+ case 1:
+ if( rv > 0 ) {
+ continue;
+ }
+ break;
+ case 0:
+ if( 0 == rv ) {
+ continue;
+ }
+ break;
+ default:
+ PR_NOT_REACHED("static data inconsistancy");
+ break;
+ }
+
+ printf("FAIL %d: %s-%s/%ld -> %d, not %d\n", i,
+ array[i].one ? array[i].one : "(null)",
+ array[i].two ? array[i].two : "(null)",
+ array[i].max, rv, array[i].sign);
+ return PR_FALSE;
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strcasecmp */
+PRBool test_013(void)
+{
+ static struct
+ {
+ const char *one;
+ const char *two;
+ PRIntn sign;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 0 },
+ { (const char *)0, "word", -1 },
+ { "word", (const char *)0, 1 },
+ { "word", "word", 0 },
+ { "aZYXVUT", "bZYXVUT", -1 },
+ { "aZYXVUT", "bAAAAAA", -1 },
+ { "a", "aa", -1 },
+ { "a", "a", 0 },
+ { "a", "A", 0 },
+ { "aaaaa", "baaaa", -1 },
+ { "aaaaa", "abaaa", -1 },
+ { "aaaaa", "aabaa", -1 },
+ { "aaaaa", "aaaba", -1 },
+ { "aaaaa", "aaaab", -1 },
+ { "bZYXVUT", "aZYXVUT", 1 },
+ { "bAAAAAA", "aZYXVUT", 1 },
+ { "aa", "a", 1 },
+ { "A", "a", 0 },
+ { "baaaa", "aaaaa", 1 },
+ { "abaaa", "aaaaa", 1 },
+ { "aabaa", "aaaaa", 1 },
+ { "aaaba", "aaaaa", 1 },
+ { "aaaab", "aaaaa", 1 },
+ { "word", "Word", 0 },
+ { "word", "wOrd", 0 },
+ { "word", "woRd", 0 },
+ { "word", "worD", 0 },
+ { "WORD", "wORD", 0 },
+ { "WORD", "WoRD", 0 },
+ { "WORD", "WOrD", 0 },
+ { "WORD", "WORd", 0 }
+ };
+
+ int i;
+
+ printf("Test 013 (PL_strcasecmp) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRIntn rv = PL_strcasecmp(array[i].one, array[i].two);
+
+ switch( array[i].sign )
+ {
+ case -1:
+ if( rv < 0 ) {
+ continue;
+ }
+ break;
+ case 1:
+ if( rv > 0 ) {
+ continue;
+ }
+ break;
+ case 0:
+ if( 0 == rv ) {
+ continue;
+ }
+ break;
+ default:
+ PR_NOT_REACHED("static data inconsistancy");
+ break;
+ }
+
+ printf("FAIL %d: %s-%s -> %d, not %d\n", i,
+ array[i].one ? array[i].one : "(null)",
+ array[i].two ? array[i].two : "(null)",
+ rv, array[i].sign);
+ return PR_FALSE;
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strncasecmp */
+PRBool test_014(void)
+{
+ static struct
+ {
+ const char *one;
+ const char *two;
+ PRUint32 max;
+ PRIntn sign;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 0, 0 },
+ { (const char *)0, (const char *)0, 1, 0 },
+ { (const char *)0, (const char *)0, 4, 0 },
+ { (const char *)0, "word", 0, -1 },
+ { (const char *)0, "word", 1, -1 },
+ { (const char *)0, "word", 4, -1 },
+ { "word", (const char *)0, 0, 1 },
+ { "word", (const char *)0, 1, 1 },
+ { "word", (const char *)0, 4, 1 },
+ { "word", "word", 0, 0 },
+ { "word", "word", 1, 0 },
+ { "word", "word", 3, 0 },
+ { "word", "word", 5, 0 },
+ { "aZYXVUT", "bZYXVUT", 0, 0 },
+ { "aZYXVUT", "bZYXVUT", 1, -1 },
+ { "aZYXVUT", "bZYXVUT", 4, -1 },
+ { "aZYXVUT", "bZYXVUT", 9, -1 },
+ { "aZYXVUT", "bAAAAAA", 0, 0 },
+ { "aZYXVUT", "bAAAAAA", 1, -1 },
+ { "aZYXVUT", "bAAAAAA", 4, -1 },
+ { "aZYXVUT", "bAAAAAA", 5, -1 },
+ { "a", "aa", 0, 0 },
+ { "a", "aa", 1, 0 },
+ { "a", "aa", 4, -1 },
+ { "a", "a", 0, 0 },
+ { "a", "a", 1, 0 },
+ { "a", "a", 4, 0 },
+ { "a", "A", 0, 0 },
+ { "a", "A", 1, 0 },
+ { "a", "A", 4, 0 },
+ { "aaaaa", "baaaa", 0, 0 },
+ { "aaaaa", "baaaa", 1, -1 },
+ { "aaaaa", "baaaa", 4, -1 },
+ { "aaaaa", "abaaa", 0, 0 },
+ { "aaaaa", "abaaa", 1, 0 },
+ { "aaaaa", "abaaa", 4, -1 },
+ { "aaaaa", "aabaa", 0, 0 },
+ { "aaaaa", "aabaa", 1, 0 },
+ { "aaaaa", "aabaa", 4, -1 },
+ { "aaaaa", "aaaba", 0, 0 },
+ { "aaaaa", "aaaba", 1, 0 },
+ { "aaaaa", "aaaba", 4, -1 },
+ { "aaaaa", "aaaab", 0, 0 },
+ { "aaaaa", "aaaab", 1, 0 },
+ { "aaaaa", "aaaab", 4, 0 },
+ { "bZYXVUT", "aZYXVUT", 0, 0 },
+ { "bZYXVUT", "aZYXVUT", 1, 1 },
+ { "bZYXVUT", "aZYXVUT", 4, 1 },
+ { "bAAAAAA", "aZYXVUT", 0, 0 },
+ { "bAAAAAA", "aZYXVUT", 1, 1 },
+ { "bAAAAAA", "aZYXVUT", 4, 1 },
+ { "aa", "a", 0, 0 },
+ { "aa", "a", 1, 0 },
+ { "aa", "a", 4, 1 },
+ { "A", "a", 0, 0 },
+ { "A", "a", 1, 0 },
+ { "A", "a", 4, 0 },
+ { "baaaa", "aaaaa", 0, 0 },
+ { "baaaa", "aaaaa", 1, 1 },
+ { "baaaa", "aaaaa", 4, 1 },
+ { "abaaa", "aaaaa", 0, 0 },
+ { "abaaa", "aaaaa", 1, 0 },
+ { "abaaa", "aaaaa", 4, 1 },
+ { "aabaa", "aaaaa", 0, 0 },
+ { "aabaa", "aaaaa", 1, 0 },
+ { "aabaa", "aaaaa", 4, 1 },
+ { "aaaba", "aaaaa", 0, 0 },
+ { "aaaba", "aaaaa", 1, 0 },
+ { "aaaba", "aaaaa", 4, 1 },
+ { "aaaab", "aaaaa", 0, 0 },
+ { "aaaab", "aaaaa", 1, 0 },
+ { "aaaab", "aaaaa", 4, 0 },
+ { "word", "Word", 0, 0 },
+ { "word", "Word", 1, 0 },
+ { "word", "Word", 3, 0 },
+ { "word", "wOrd", 0, 0 },
+ { "word", "wOrd", 1, 0 },
+ { "word", "wOrd", 3, 0 },
+ { "word", "woRd", 0, 0 },
+ { "word", "woRd", 1, 0 },
+ { "word", "woRd", 3, 0 },
+ { "word", "worD", 0, 0 },
+ { "word", "worD", 1, 0 },
+ { "word", "worD", 3, 0 },
+ { "WORD", "wORD", 0, 0 },
+ { "WORD", "wORD", 1, 0 },
+ { "WORD", "wORD", 3, 0 },
+ { "WORD", "WoRD", 0, 0 },
+ { "WORD", "WoRD", 1, 0 },
+ { "WORD", "WoRD", 3, 0 },
+ { "WORD", "WOrD", 0, 0 },
+ { "WORD", "WOrD", 1, 0 },
+ { "WORD", "WOrD", 3, 0 },
+ { "WORD", "WORd", 0, 0 },
+ { "WORD", "WORd", 1, 0 },
+ { "WORD", "WORd", 3, 0 }
+ };
+
+ int i;
+
+ printf("Test 014 (PL_strncasecmp) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRIntn rv = PL_strncasecmp(array[i].one, array[i].two, array[i].max);
+
+ switch( array[i].sign )
+ {
+ case -1:
+ if( rv < 0 ) {
+ continue;
+ }
+ break;
+ case 1:
+ if( rv > 0 ) {
+ continue;
+ }
+ break;
+ case 0:
+ if( 0 == rv ) {
+ continue;
+ }
+ break;
+ default:
+ PR_NOT_REACHED("static data inconsistancy");
+ break;
+ }
+
+ printf("FAIL %d: %s-%s/%ld -> %d, not %d\n", i,
+ array[i].one ? array[i].one : "(null)",
+ array[i].two ? array[i].two : "(null)",
+ array[i].max, rv, array[i].sign);
+ return PR_FALSE;
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strchr */
+PRBool test_015(void)
+{
+ static struct
+ {
+ const char *str;
+ char chr;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, 'a', PR_FALSE, 0 },
+ { (const char *)0, '\0', PR_FALSE, 0 },
+ { "abcdefg", 'a', PR_TRUE, 0 },
+ { "abcdefg", 'b', PR_TRUE, 1 },
+ { "abcdefg", 'c', PR_TRUE, 2 },
+ { "abcdefg", 'd', PR_TRUE, 3 },
+ { "abcdefg", 'e', PR_TRUE, 4 },
+ { "abcdefg", 'f', PR_TRUE, 5 },
+ { "abcdefg", 'g', PR_TRUE, 6 },
+ { "abcdefg", 'h', PR_FALSE, 0 },
+ { "abcdefg", '\0', PR_TRUE, 7 },
+ { "abcdefg", 'A', PR_FALSE, 0 },
+ { "abcdefg", 'B', PR_FALSE, 0 },
+ { "abcdefg", 'C', PR_FALSE, 0 },
+ { "abcdefg", 'D', PR_FALSE, 0 },
+ { "abcdefg", 'E', PR_FALSE, 0 },
+ { "abcdefg", 'F', PR_FALSE, 0 },
+ { "abcdefg", 'G', PR_FALSE, 0 },
+ { "abcdefg", 'H', PR_FALSE, 0 },
+ { "abcdefgabcdefg", 'a', PR_TRUE, 0 },
+ { "abcdefgabcdefg", 'b', PR_TRUE, 1 },
+ { "abcdefgabcdefg", 'c', PR_TRUE, 2 },
+ { "abcdefgabcdefg", 'd', PR_TRUE, 3 },
+ { "abcdefgabcdefg", 'e', PR_TRUE, 4 },
+ { "abcdefgabcdefg", 'f', PR_TRUE, 5 },
+ { "abcdefgabcdefg", 'g', PR_TRUE, 6 },
+ { "abcdefgabcdefg", 'h', PR_FALSE, 0 },
+ { "abcdefgabcdefg", '\0', PR_TRUE, 14 }
+ };
+
+ int i;
+
+ printf("Test 015 (PL_strchr) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strchr(array[i].str, array[i].chr);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%c -> %.32s, not zero\n", i, array[i].str,
+ array[i].chr, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%c -> null, not +%lu\n", i, array[i].str,
+ array[i].chr, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%c -> 0x%x, not 0x%x+%lu\n", i, array[i].str,
+ array[i].chr, rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strrchr */
+PRBool test_016(void)
+{
+ static struct
+ {
+ const char *str;
+ char chr;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, 'a', PR_FALSE, 0 },
+ { (const char *)0, '\0', PR_FALSE, 0 },
+ { "abcdefg", 'a', PR_TRUE, 0 },
+ { "abcdefg", 'b', PR_TRUE, 1 },
+ { "abcdefg", 'c', PR_TRUE, 2 },
+ { "abcdefg", 'd', PR_TRUE, 3 },
+ { "abcdefg", 'e', PR_TRUE, 4 },
+ { "abcdefg", 'f', PR_TRUE, 5 },
+ { "abcdefg", 'g', PR_TRUE, 6 },
+ { "abcdefg", 'h', PR_FALSE, 0 },
+ { "abcdefg", '\0', PR_TRUE, 7 },
+ { "abcdefg", 'A', PR_FALSE, 0 },
+ { "abcdefg", 'B', PR_FALSE, 0 },
+ { "abcdefg", 'C', PR_FALSE, 0 },
+ { "abcdefg", 'D', PR_FALSE, 0 },
+ { "abcdefg", 'E', PR_FALSE, 0 },
+ { "abcdefg", 'F', PR_FALSE, 0 },
+ { "abcdefg", 'G', PR_FALSE, 0 },
+ { "abcdefg", 'H', PR_FALSE, 0 },
+ { "abcdefgabcdefg", 'a', PR_TRUE, 7 },
+ { "abcdefgabcdefg", 'b', PR_TRUE, 8 },
+ { "abcdefgabcdefg", 'c', PR_TRUE, 9 },
+ { "abcdefgabcdefg", 'd', PR_TRUE, 10 },
+ { "abcdefgabcdefg", 'e', PR_TRUE, 11 },
+ { "abcdefgabcdefg", 'f', PR_TRUE, 12 },
+ { "abcdefgabcdefg", 'g', PR_TRUE, 13 },
+ { "abcdefgabcdefg", 'h', PR_FALSE, 0 },
+ { "abcdefgabcdefg", '\0', PR_TRUE, 14 }
+ };
+
+ int i;
+
+ printf("Test 016 (PL_strrchr) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strrchr(array[i].str, array[i].chr);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%c -> %.32s, not zero\n", i, array[i].str,
+ array[i].chr, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%c -> null, not +%lu\n", i, array[i].str,
+ array[i].chr, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%c -> 0x%x, not 0x%x+%lu\n", i, array[i].str,
+ array[i].chr, rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strnchr */
+PRBool test_017(void)
+{
+ static struct
+ {
+ const char *str;
+ char chr;
+ PRUint32 max;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, 'a', 2, PR_FALSE, 0 },
+ { (const char *)0, '\0', 2, PR_FALSE, 0 },
+ { "abcdefg", 'a', 5, PR_TRUE, 0 },
+ { "abcdefg", 'b', 5, PR_TRUE, 1 },
+ { "abcdefg", 'c', 5, PR_TRUE, 2 },
+ { "abcdefg", 'd', 5, PR_TRUE, 3 },
+ { "abcdefg", 'e', 5, PR_TRUE, 4 },
+ { "abcdefg", 'f', 5, PR_FALSE, 0 },
+ { "abcdefg", 'g', 5, PR_FALSE, 0 },
+ { "abcdefg", 'h', 5, PR_FALSE, 0 },
+ { "abcdefg", '\0', 5, PR_FALSE, 0 },
+ { "abcdefg", '\0', 15, PR_TRUE, 7 },
+ { "abcdefg", 'A', 5, PR_FALSE, 0 },
+ { "abcdefg", 'B', 5, PR_FALSE, 0 },
+ { "abcdefg", 'C', 5, PR_FALSE, 0 },
+ { "abcdefg", 'D', 5, PR_FALSE, 0 },
+ { "abcdefg", 'E', 5, PR_FALSE, 0 },
+ { "abcdefg", 'F', 5, PR_FALSE, 0 },
+ { "abcdefg", 'G', 5, PR_FALSE, 0 },
+ { "abcdefg", 'H', 5, PR_FALSE, 0 },
+ { "abcdefgabcdefg", 'a', 10, PR_TRUE, 0 },
+ { "abcdefgabcdefg", 'b', 10, PR_TRUE, 1 },
+ { "abcdefgabcdefg", 'c', 10, PR_TRUE, 2 },
+ { "abcdefgabcdefg", 'd', 10, PR_TRUE, 3 },
+ { "abcdefgabcdefg", 'e', 10, PR_TRUE, 4 },
+ { "abcdefgabcdefg", 'f', 10, PR_TRUE, 5 },
+ { "abcdefgabcdefg", 'g', 10, PR_TRUE, 6 },
+ { "abcdefgabcdefg", 'h', 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", '\0', 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", '\0', 14, PR_FALSE, 0 },
+ { "abcdefgabcdefg", '\0', 15, PR_TRUE, 14 }
+ };
+
+ int i;
+
+ printf("Test 017 (PL_strnchr) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strnchr(array[i].str, array[i].chr, array[i].max);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%c/%lu -> %.32s, not zero\n", i, array[i].str,
+ array[i].chr, array[i].max, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%c/%lu -> null, not +%lu\n", i, array[i].str,
+ array[i].chr, array[i].max, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%c/%lu -> 0x%x, not 0x%x+%lu\n", i, array[i].str,
+ array[i].chr, array[i].max, rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strnrchr */
+PRBool test_018(void)
+{
+ static struct
+ {
+ const char *str;
+ char chr;
+ PRUint32 max;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, 'a', 2, PR_FALSE, 0 },
+ { (const char *)0, '\0', 2, PR_FALSE, 0 },
+ { "abcdefg", 'a', 5, PR_TRUE, 0 },
+ { "abcdefg", 'b', 5, PR_TRUE, 1 },
+ { "abcdefg", 'c', 5, PR_TRUE, 2 },
+ { "abcdefg", 'd', 5, PR_TRUE, 3 },
+ { "abcdefg", 'e', 5, PR_TRUE, 4 },
+ { "abcdefg", 'f', 5, PR_FALSE, 0 },
+ { "abcdefg", 'g', 5, PR_FALSE, 0 },
+ { "abcdefg", 'h', 5, PR_FALSE, 0 },
+ { "abcdefg", '\0', 5, PR_FALSE, 0 },
+ { "abcdefg", '\0', 15, PR_TRUE, 7 },
+ { "abcdefg", 'A', 5, PR_FALSE, 0 },
+ { "abcdefg", 'B', 5, PR_FALSE, 0 },
+ { "abcdefg", 'C', 5, PR_FALSE, 0 },
+ { "abcdefg", 'D', 5, PR_FALSE, 0 },
+ { "abcdefg", 'E', 5, PR_FALSE, 0 },
+ { "abcdefg", 'F', 5, PR_FALSE, 0 },
+ { "abcdefg", 'G', 5, PR_FALSE, 0 },
+ { "abcdefg", 'H', 5, PR_FALSE, 0 },
+ { "abcdefgabcdefg", 'a', 10, PR_TRUE, 7 },
+ { "abcdefgabcdefg", 'b', 10, PR_TRUE, 8 },
+ { "abcdefgabcdefg", 'c', 10, PR_TRUE, 9 },
+ { "abcdefgabcdefg", 'd', 10, PR_TRUE, 3 },
+ { "abcdefgabcdefg", 'e', 10, PR_TRUE, 4 },
+ { "abcdefgabcdefg", 'f', 10, PR_TRUE, 5 },
+ { "abcdefgabcdefg", 'g', 10, PR_TRUE, 6 },
+ { "abcdefgabcdefg", 'h', 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", '\0', 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", '\0', 14, PR_FALSE, 0 },
+ { "abcdefgabcdefg", '\0', 15, PR_TRUE, 14 }
+ };
+
+ int i;
+
+ printf("Test 018 (PL_strnrchr) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strnrchr(array[i].str, array[i].chr, array[i].max);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%c/%lu -> %.32s, not zero\n", i, array[i].str,
+ array[i].chr, array[i].max, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%c/%lu -> null, not +%lu\n", i, array[i].str,
+ array[i].chr, array[i].max, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%c/%lu -> 0x%x, not 0x%x+%lu\n", i, array[i].str,
+ array[i].chr, array[i].max, rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strpbrk */
+PRBool test_019(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *chrs;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, PR_FALSE, 0 },
+ { (const char *)0, "abc", PR_FALSE, 0 },
+ { "abc", (const char *)0, PR_FALSE, 0 },
+ { "abcdefg", "", PR_FALSE, 0 },
+ { "", "aeiou", PR_FALSE, 0 },
+ { "abcdefg", "ae", PR_TRUE, 0 },
+ { "abcdefg", "ei", PR_TRUE, 4 },
+ { "abcdefg", "io", PR_FALSE, 0 },
+ { "abcdefg", "bcd", PR_TRUE, 1 },
+ { "abcdefg", "cbd", PR_TRUE, 1 },
+ { "abcdefg", "dbc", PR_TRUE, 1 },
+ { "abcdefg", "ghi", PR_TRUE, 6 },
+ { "abcdefg", "AE", PR_FALSE, 0 },
+ { "abcdefg", "EI", PR_FALSE, 0 },
+ { "abcdefg", "IO", PR_FALSE, 0 },
+ { "abcdefg", "BCD", PR_FALSE, 0 },
+ { "abcdefg", "CBD", PR_FALSE, 0 },
+ { "abcdefg", "DBC", PR_FALSE, 0 },
+ { "abcdefg", "GHI", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ae", PR_TRUE, 0 },
+ { "abcdefgabcdefg", "ei", PR_TRUE, 4 },
+ { "abcdefgabcdefg", "io", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "bcd", PR_TRUE, 1 },
+ { "abcdefgabcdefg", "cbd", PR_TRUE, 1 },
+ { "abcdefgabcdefg", "dbc", PR_TRUE, 1 },
+ { "abcdefgabcdefg", "ghi", PR_TRUE, 6 },
+ { "abcdefgabcdefg", "AE", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "EI", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "IO", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "BCD", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "CBD", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "DBC", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "GHI", PR_FALSE, 0 }
+ };
+
+ int i;
+
+ printf("Test 019 (PL_strpbrk) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strpbrk(array[i].str, array[i].chrs);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s -> null, not +%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strprbrk */
+PRBool test_020(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *chrs;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, PR_FALSE, 0 },
+ { (const char *)0, "abc", PR_FALSE, 0 },
+ { "abc", (const char *)0, PR_FALSE, 0 },
+ { "abcdefg", "", PR_FALSE, 0 },
+ { "", "aeiou", PR_FALSE, 0 },
+ { "abcdefg", "ae", PR_TRUE, 4 },
+ { "abcdefg", "ei", PR_TRUE, 4 },
+ { "abcdefg", "io", PR_FALSE, 0 },
+ { "abcdefg", "bcd", PR_TRUE, 3 },
+ { "abcdefg", "cbd", PR_TRUE, 3 },
+ { "abcdefg", "dbc", PR_TRUE, 3 },
+ { "abcdefg", "ghi", PR_TRUE, 6 },
+ { "abcdefg", "AE", PR_FALSE, 0 },
+ { "abcdefg", "EI", PR_FALSE, 0 },
+ { "abcdefg", "IO", PR_FALSE, 0 },
+ { "abcdefg", "BCD", PR_FALSE, 0 },
+ { "abcdefg", "CBD", PR_FALSE, 0 },
+ { "abcdefg", "DBC", PR_FALSE, 0 },
+ { "abcdefg", "GHI", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ae", PR_TRUE, 11 },
+ { "abcdefgabcdefg", "ei", PR_TRUE, 11 },
+ { "abcdefgabcdefg", "io", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "bcd", PR_TRUE, 10 },
+ { "abcdefgabcdefg", "cbd", PR_TRUE, 10 },
+ { "abcdefgabcdefg", "dbc", PR_TRUE, 10 },
+ { "abcdefgabcdefg", "ghi", PR_TRUE, 13 },
+ { "abcdefgabcdefg", "AE", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "EI", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "IO", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "BCD", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "CBD", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "DBC", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "GHI", PR_FALSE, 0 }
+ };
+
+ int i;
+
+ printf("Test 020 (PL_strprbrk) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strprbrk(array[i].str, array[i].chrs);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s -> null, not +%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strnpbrk */
+PRBool test_021(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *chrs;
+ PRUint32 max;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 3, PR_FALSE, 0 },
+ { (const char *)0, "abc", 3, PR_FALSE, 0 },
+ { "abc", (const char *)0, 3, PR_FALSE, 0 },
+ { "abcdefg", "", 3, PR_FALSE, 0 },
+ { "", "aeiou", 3, PR_FALSE, 0 },
+ { "abcdefg", "ae", 0, PR_FALSE, 0 },
+ { "abcdefg", "ae", 1, PR_TRUE, 0 },
+ { "abcdefg", "ae", 4, PR_TRUE, 0 },
+ { "abcdefg", "ae", 5, PR_TRUE, 0 },
+ { "abcdefg", "ae", 6, PR_TRUE, 0 },
+ { "abcdefg", "ei", 4, PR_FALSE, 0 },
+ { "abcdefg", "io", 10, PR_FALSE, 0 },
+ { "abcdefg", "bcd", 2, PR_TRUE, 1 },
+ { "abcdefg", "cbd", 2, PR_TRUE, 1 },
+ { "abcdefg", "dbc", 2, PR_TRUE, 1 },
+ { "abcdefg", "ghi", 6, PR_FALSE, 0 },
+ { "abcdefg", "ghi", 7, PR_TRUE, 6 },
+ { "abcdefg", "AE", 9, PR_FALSE, 0 },
+ { "abcdefg", "EI", 9, PR_FALSE, 0 },
+ { "abcdefg", "IO", 9, PR_FALSE, 0 },
+ { "abcdefg", "BCD", 9, PR_FALSE, 0 },
+ { "abcdefg", "CBD", 9, PR_FALSE, 0 },
+ { "abcdefg", "DBC", 9, PR_FALSE, 0 },
+ { "abcdefg", "GHI", 9, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ae", 10, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "ei", 10, PR_TRUE, 4 },
+ { "abcdefgabcdefg", "io", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "bcd", 10, PR_TRUE, 1 },
+ { "abcdefgabcdefg", "cbd", 10, PR_TRUE, 1 },
+ { "abcdefgabcdefg", "dbc", 10, PR_TRUE, 1 },
+ { "abcdefgabcdefg", "ghi", 10, PR_TRUE, 6 },
+ { "abcdefgabcdefg", "AE", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "EI", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "IO", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "BCD", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "CBD", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "DBC", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "GHI", 10, PR_FALSE, 0 }
+ };
+
+ int i;
+
+ printf("Test 021 (PL_strnpbrk) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strnpbrk(array[i].str, array[i].chrs, array[i].max);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ array[i].max, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> null, not +%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ array[i].max, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ array[i].max, rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strnprbrk */
+PRBool test_022(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *chrs;
+ PRUint32 max;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 3, PR_FALSE, 0 },
+ { (const char *)0, "abc", 3, PR_FALSE, 0 },
+ { "abc", (const char *)0, 3, PR_FALSE, 0 },
+ { "abcdefg", "", 3, PR_FALSE, 0 },
+ { "", "aeiou", 3, PR_FALSE, 0 },
+ { "abcdefg", "ae", 0, PR_FALSE, 0 },
+ { "abcdefg", "ae", 1, PR_TRUE, 0 },
+ { "abcdefg", "ae", 4, PR_TRUE, 0 },
+ { "abcdefg", "ae", 5, PR_TRUE, 4 },
+ { "abcdefg", "ae", 6, PR_TRUE, 4 },
+ { "abcdefg", "ei", 4, PR_FALSE, 0 },
+ { "abcdefg", "io", 10, PR_FALSE, 0 },
+ { "abcdefg", "bcd", 2, PR_TRUE, 1 },
+ { "abcdefg", "cbd", 2, PR_TRUE, 1 },
+ { "abcdefg", "dbc", 2, PR_TRUE, 1 },
+ { "abcdefg", "bcd", 3, PR_TRUE, 2 },
+ { "abcdefg", "cbd", 3, PR_TRUE, 2 },
+ { "abcdefg", "dbc", 3, PR_TRUE, 2 },
+ { "abcdefg", "bcd", 5, PR_TRUE, 3 },
+ { "abcdefg", "cbd", 5, PR_TRUE, 3 },
+ { "abcdefg", "dbc", 5, PR_TRUE, 3 },
+ { "abcdefg", "bcd", 15, PR_TRUE, 3 },
+ { "abcdefg", "cbd", 15, PR_TRUE, 3 },
+ { "abcdefg", "dbc", 15, PR_TRUE, 3 },
+ { "abcdefg", "ghi", 6, PR_FALSE, 0 },
+ { "abcdefg", "ghi", 7, PR_TRUE, 6 },
+ { "abcdefg", "AE", 9, PR_FALSE, 0 },
+ { "abcdefg", "EI", 9, PR_FALSE, 0 },
+ { "abcdefg", "IO", 9, PR_FALSE, 0 },
+ { "abcdefg", "BCD", 9, PR_FALSE, 0 },
+ { "abcdefg", "CBD", 9, PR_FALSE, 0 },
+ { "abcdefg", "DBC", 9, PR_FALSE, 0 },
+ { "abcdefg", "GHI", 9, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ae", 10, PR_TRUE, 7 },
+ { "abcdefgabcdefg", "ei", 10, PR_TRUE, 4 },
+ { "abcdefgabcdefg", "io", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "bcd", 10, PR_TRUE, 9 },
+ { "abcdefgabcdefg", "cbd", 10, PR_TRUE, 9 },
+ { "abcdefgabcdefg", "dbc", 10, PR_TRUE, 9 },
+ { "abcdefgabcdefg", "ghi", 10, PR_TRUE, 6 },
+ { "abcdefgabcdefg", "AE", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "EI", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "IO", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "BCD", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "CBD", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "DBC", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "GHI", 10, PR_FALSE, 0 }
+ };
+
+ int i;
+
+ printf("Test 022 (PL_strnprbrk) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strnprbrk(array[i].str, array[i].chrs, array[i].max);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ array[i].max, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> null, not +%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ array[i].max, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ array[i].max, rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strstr */
+PRBool test_023(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *sub;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, PR_FALSE, 0 },
+ { (const char *)0, "blah", PR_FALSE, 0 },
+ { "blah-de-blah", (const char *)0, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", PR_TRUE, 0 },
+ { "", "blah", PR_FALSE, 0 },
+ { "blah-de-blah", "", PR_FALSE, 0 },
+ { "abcdefg", "a", PR_TRUE, 0 },
+ { "abcdefg", "c", PR_TRUE, 2 },
+ { "abcdefg", "e", PR_TRUE, 4 },
+ { "abcdefg", "g", PR_TRUE, 6 },
+ { "abcdefg", "i", PR_FALSE, 0 },
+ { "abcdefg", "ab", PR_TRUE, 0 },
+ { "abcdefg", "cd", PR_TRUE, 2 },
+ { "abcdefg", "ef", PR_TRUE, 4 },
+ { "abcdefg", "gh", PR_FALSE, 0 },
+ { "abcdabc", "bc", PR_TRUE, 1 },
+ { "abcdefg", "abcdefg", PR_TRUE, 0 },
+ { "abcdefgabcdefg", "a", PR_TRUE, 0 },
+ { "abcdefgabcdefg", "c", PR_TRUE, 2 },
+ { "abcdefgabcdefg", "e", PR_TRUE, 4 },
+ { "abcdefgabcdefg", "g", PR_TRUE, 6 },
+ { "abcdefgabcdefg", "i", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ab", PR_TRUE, 0 },
+ { "abcdefgabcdefg", "cd", PR_TRUE, 2 },
+ { "abcdefgabcdefg", "ef", PR_TRUE, 4 },
+ { "abcdefgabcdefg", "gh", PR_FALSE, 0 },
+ { "abcdabcabcdabc", "bc", PR_TRUE, 1 },
+ { "abcdefgabcdefg", "abcdefg", PR_TRUE, 0 },
+ { "ABCDEFG", "a", PR_FALSE, 0 },
+ { "ABCDEFG", "c", PR_FALSE, 0 },
+ { "ABCDEFG", "e", PR_FALSE, 0 },
+ { "ABCDEFG", "g", PR_FALSE, 0 },
+ { "ABCDEFG", "i", PR_FALSE, 0 },
+ { "ABCDEFG", "ab", PR_FALSE, 0 },
+ { "ABCDEFG", "cd", PR_FALSE, 0 },
+ { "ABCDEFG", "ef", PR_FALSE, 0 },
+ { "ABCDEFG", "gh", PR_FALSE, 0 },
+ { "ABCDABC", "bc", PR_FALSE, 0 },
+ { "ABCDEFG", "abcdefg", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "a", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "c", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "e", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "g", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "i", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ab", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "cd", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ef", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "gh", PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "abcdefg", PR_FALSE, 0 }
+ };
+
+ int i;
+
+ printf("Test 023 (PL_strstr) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strstr(array[i].str, array[i].sub);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s -> null, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strrstr */
+PRBool test_024(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *sub;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, PR_FALSE, 0 },
+ { (const char *)0, "blah", PR_FALSE, 0 },
+ { "blah-de-blah", (const char *)0, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", PR_TRUE, 8 },
+ { "", "blah", PR_FALSE, 0 },
+ { "blah-de-blah", "", PR_FALSE, 0 },
+ { "abcdefg", "a", PR_TRUE, 0 },
+ { "abcdefg", "c", PR_TRUE, 2 },
+ { "abcdefg", "e", PR_TRUE, 4 },
+ { "abcdefg", "g", PR_TRUE, 6 },
+ { "abcdefg", "i", PR_FALSE, 0 },
+ { "abcdefg", "ab", PR_TRUE, 0 },
+ { "abcdefg", "cd", PR_TRUE, 2 },
+ { "abcdefg", "ef", PR_TRUE, 4 },
+ { "abcdefg", "gh", PR_FALSE, 0 },
+ { "abcdabc", "bc", PR_TRUE, 5 },
+ { "abcdefg", "abcdefg", PR_TRUE, 0 },
+ { "abcdefgabcdefg", "a", PR_TRUE, 7 },
+ { "abcdefgabcdefg", "c", PR_TRUE, 9 },
+ { "abcdefgabcdefg", "e", PR_TRUE, 11 },
+ { "abcdefgabcdefg", "g", PR_TRUE, 13 },
+ { "abcdefgabcdefg", "i", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ab", PR_TRUE, 7 },
+ { "abcdefgabcdefg", "cd", PR_TRUE, 9 },
+ { "abcdefgabcdefg", "ef", PR_TRUE, 11 },
+ { "abcdefgabcdefg", "gh", PR_FALSE, 0 },
+ { "abcdabcabcdabc", "bc", PR_TRUE, 12 },
+ { "abcdefgabcdefg", "abcdefg", PR_TRUE, 7 },
+ { "ABCDEFG", "a", PR_FALSE, 0 },
+ { "ABCDEFG", "c", PR_FALSE, 0 },
+ { "ABCDEFG", "e", PR_FALSE, 0 },
+ { "ABCDEFG", "g", PR_FALSE, 0 },
+ { "ABCDEFG", "i", PR_FALSE, 0 },
+ { "ABCDEFG", "ab", PR_FALSE, 0 },
+ { "ABCDEFG", "cd", PR_FALSE, 0 },
+ { "ABCDEFG", "ef", PR_FALSE, 0 },
+ { "ABCDEFG", "gh", PR_FALSE, 0 },
+ { "ABCDABC", "bc", PR_FALSE, 0 },
+ { "ABCDEFG", "abcdefg", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "a", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "c", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "e", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "g", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "i", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ab", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "cd", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ef", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "gh", PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "abcdefg", PR_FALSE, 0 }
+ };
+
+ int i;
+
+ printf("Test 024 (PL_strrstr) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strrstr(array[i].str, array[i].sub);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s -> null, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strnstr */
+PRBool test_025(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *sub;
+ PRUint32 max;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 12, PR_FALSE, 0 },
+ { (const char *)0, "blah", 12, PR_FALSE, 0 },
+ { "blah-de-blah", (const char *)0, 12, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 0, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 2, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 3, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 4, PR_TRUE, 0 },
+ { "blah-de-blah", "blah", 5, PR_TRUE, 0 },
+ { "blah-de-blah", "blah", 12, PR_TRUE, 0 },
+ { "", "blah", 12, PR_FALSE, 0 },
+ { "blah-de-blah", "", 12, PR_FALSE, 0 },
+ { "abcdefg", "a", 5, PR_TRUE, 0 },
+ { "abcdefg", "c", 5, PR_TRUE, 2 },
+ { "abcdefg", "e", 5, PR_TRUE, 4 },
+ { "abcdefg", "g", 5, PR_FALSE, 0 },
+ { "abcdefg", "i", 5, PR_FALSE, 0 },
+ { "abcdefg", "ab", 5, PR_TRUE, 0 },
+ { "abcdefg", "cd", 5, PR_TRUE, 2 },
+ { "abcdefg", "ef", 5, PR_FALSE, 0 },
+ { "abcdefg", "gh", 5, PR_FALSE, 0 },
+ { "abcdabc", "bc", 5, PR_TRUE, 1 },
+ { "abcdabc", "bc", 6, PR_TRUE, 1 },
+ { "abcdabc", "bc", 7, PR_TRUE, 1 },
+ { "abcdefg", "abcdefg", 6, PR_FALSE, 0 },
+ { "abcdefg", "abcdefg", 7, PR_TRUE, 0 },
+ { "abcdefg", "abcdefg", 8, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "a", 12, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "c", 12, PR_TRUE, 2 },
+ { "abcdefgabcdefg", "e", 12, PR_TRUE, 4 },
+ { "abcdefgabcdefg", "g", 12, PR_TRUE, 6 },
+ { "abcdefgabcdefg", "i", 12, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ab", 12, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "cd", 12, PR_TRUE, 2 },
+ { "abcdefgabcdefg", "ef", 12, PR_TRUE, 4 },
+ { "abcdefgabcdefg", "gh", 12, PR_FALSE, 0 },
+ { "abcdabcabcdabc", "bc", 5, PR_TRUE, 1 },
+ { "abcdabcabcdabc", "bc", 6, PR_TRUE, 1 },
+ { "abcdabcabcdabc", "bc", 7, PR_TRUE, 1 },
+ { "abcdefgabcdefg", "abcdefg", 6, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "abcdefg", 7, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "abcdefg", 8, PR_TRUE, 0 },
+ { "ABCDEFG", "a", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "c", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "e", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "g", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "i", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "ab", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "cd", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "ef", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "gh", 5, PR_FALSE, 0 },
+ { "ABCDABC", "bc", 5, PR_FALSE, 0 },
+ { "ABCDABC", "bc", 6, PR_FALSE, 0 },
+ { "ABCDABC", "bc", 7, PR_FALSE, 0 },
+ { "ABCDEFG", "abcdefg", 6, PR_FALSE, 0 },
+ { "ABCDEFG", "abcdefg", 7, PR_FALSE, 0 },
+ { "ABCDEFG", "abcdefg", 8, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "a", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "c", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "e", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "g", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "i", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ab", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "cd", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ef", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "gh", 12, PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", 5, PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", 6, PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", 7, PR_FALSE, },
+ { "ABCDEFGABCDEFG", "abcdefg", 6, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "abcdefg", 7, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "abcdefg", 8, PR_FALSE, 0 }
+ };
+
+ int i;
+
+ printf("Test 025 (PL_strnstr) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strnstr(array[i].str, array[i].sub, array[i].max);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> null, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strnrstr */
+PRBool test_026(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *sub;
+ PRUint32 max;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 12, PR_FALSE, 0 },
+ { (const char *)0, "blah", 12, PR_FALSE, 0 },
+ { "blah-de-blah", (const char *)0, 12, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 0, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 2, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 3, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 4, PR_TRUE, 0 },
+ { "blah-de-blah", "blah", 5, PR_TRUE, 0 },
+ { "blah-de-blah", "blah", 11, PR_TRUE, 0 },
+ { "blah-de-blah", "blah", 12, PR_TRUE, 8 },
+ { "blah-de-blah", "blah", 13, PR_TRUE, 8 },
+ { "", "blah", 12, PR_FALSE, 0 },
+ { "blah-de-blah", "", 12, PR_FALSE, 0 },
+ { "abcdefg", "a", 5, PR_TRUE, 0 },
+ { "abcdefg", "c", 5, PR_TRUE, 2 },
+ { "abcdefg", "e", 5, PR_TRUE, 4 },
+ { "abcdefg", "g", 5, PR_FALSE, 0 },
+ { "abcdefg", "i", 5, PR_FALSE, 0 },
+ { "abcdefg", "ab", 5, PR_TRUE, 0 },
+ { "abcdefg", "cd", 5, PR_TRUE, 2 },
+ { "abcdefg", "ef", 5, PR_FALSE, 0 },
+ { "abcdefg", "gh", 5, PR_FALSE, 0 },
+ { "abcdabc", "bc", 5, PR_TRUE, 1 },
+ { "abcdabc", "bc", 6, PR_TRUE, 1 },
+ { "abcdabc", "bc", 7, PR_TRUE, 5 },
+ { "abcdefg", "abcdefg", 6, PR_FALSE, 0 },
+ { "abcdefg", "abcdefg", 7, PR_TRUE, 0 },
+ { "abcdefg", "abcdefg", 8, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "a", 12, PR_TRUE, 7 },
+ { "abcdefgabcdefg", "c", 12, PR_TRUE, 9 },
+ { "abcdefgabcdefg", "e", 12, PR_TRUE, 11 },
+ { "abcdefgabcdefg", "g", 12, PR_TRUE, 6 },
+ { "abcdefgabcdefg", "i", 12, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ab", 12, PR_TRUE, 7 },
+ { "abcdefgabcdefg", "cd", 12, PR_TRUE, 9 },
+ { "abcdefgabcdefg", "ef", 12, PR_TRUE, 4 },
+ { "abcdefgabcdefg", "gh", 12, PR_FALSE, 0 },
+ { "abcdabcabcdabc", "bc", 12, PR_TRUE, 8 },
+ { "abcdabcabcdabc", "bc", 13, PR_TRUE, 8 },
+ { "abcdabcabcdabc", "bc", 14, PR_TRUE, 12 },
+ { "abcdefgabcdefg", "abcdefg", 13, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "abcdefg", 14, PR_TRUE, 7 },
+ { "abcdefgabcdefg", "abcdefg", 15, PR_TRUE, 7 },
+ { "ABCDEFG", "a", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "c", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "e", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "g", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "i", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "ab", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "cd", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "ef", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "gh", 5, PR_FALSE, 0 },
+ { "ABCDABC", "bc", 5, PR_FALSE, 0 },
+ { "ABCDABC", "bc", 6, PR_FALSE, 0 },
+ { "ABCDABC", "bc", 7, PR_FALSE, 0 },
+ { "ABCDEFG", "abcdefg", 6, PR_FALSE, 0 },
+ { "ABCDEFG", "abcdefg", 7, PR_FALSE, 0 },
+ { "ABCDEFG", "abcdefg", 8, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "a", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "c", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "e", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "g", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "i", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ab", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "cd", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ef", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "gh", 12, PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", 12, PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", 13, PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", 14, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "abcdefg", 13, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "abcdefg", 14, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "abcdefg", 15, PR_FALSE, 0 }
+ };
+
+ int i;
+
+ printf("Test 026 (PL_strnrstr) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strnrstr(array[i].str, array[i].sub, array[i].max);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> null, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strcasestr */
+PRBool test_027(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *sub;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, PR_FALSE, 0 },
+ { (const char *)0, "blah", PR_FALSE, 0 },
+ { "blah-de-blah", (const char *)0, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", PR_TRUE, 0 },
+ { "", "blah", PR_FALSE, 0 },
+ { "blah-de-blah", "", PR_FALSE, 0 },
+ { "abcdefg", "a", PR_TRUE, 0 },
+ { "abcdefg", "c", PR_TRUE, 2 },
+ { "abcdefg", "e", PR_TRUE, 4 },
+ { "abcdefg", "g", PR_TRUE, 6 },
+ { "abcdefg", "i", PR_FALSE, 0 },
+ { "abcdefg", "ab", PR_TRUE, 0 },
+ { "abcdefg", "cd", PR_TRUE, 2 },
+ { "abcdefg", "ef", PR_TRUE, 4 },
+ { "abcdefg", "gh", PR_FALSE, 0 },
+ { "abcdabc", "bc", PR_TRUE, 1 },
+ { "abcdefg", "abcdefg", PR_TRUE, 0 },
+ { "abcdefgabcdefg", "a", PR_TRUE, 0 },
+ { "abcdefgabcdefg", "c", PR_TRUE, 2 },
+ { "abcdefgabcdefg", "e", PR_TRUE, 4 },
+ { "abcdefgabcdefg", "g", PR_TRUE, 6 },
+ { "abcdefgabcdefg", "i", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ab", PR_TRUE, 0 },
+ { "abcdefgabcdefg", "cd", PR_TRUE, 2 },
+ { "abcdefgabcdefg", "ef", PR_TRUE, 4 },
+ { "abcdefgabcdefg", "gh", PR_FALSE, 0 },
+ { "abcdabcabcdabc", "bc", PR_TRUE, 1 },
+ { "abcdefgabcdefg", "abcdefg", PR_TRUE, 0 },
+ { "ABCDEFG", "a", PR_TRUE, 0 },
+ { "ABCDEFG", "c", PR_TRUE, 2 },
+ { "ABCDEFG", "e", PR_TRUE, 4 },
+ { "ABCDEFG", "g", PR_TRUE, 6 },
+ { "ABCDEFG", "i", PR_FALSE, 0 },
+ { "ABCDEFG", "ab", PR_TRUE, 0 },
+ { "ABCDEFG", "cd", PR_TRUE, 2 },
+ { "ABCDEFG", "ef", PR_TRUE, 4 },
+ { "ABCDEFG", "gh", PR_FALSE, 0 },
+ { "ABCDABC", "bc", PR_TRUE, 1 },
+ { "ABCDEFG", "abcdefg", PR_TRUE, 0 },
+ { "ABCDEFGABCDEFG", "a", PR_TRUE, 0 },
+ { "ABCDEFGABCDEFG", "c", PR_TRUE, 2 },
+ { "ABCDEFGABCDEFG", "e", PR_TRUE, 4 },
+ { "ABCDEFGABCDEFG", "g", PR_TRUE, 6 },
+ { "ABCDEFGABCDEFG", "i", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ab", PR_TRUE, 0 },
+ { "ABCDEFGABCDEFG", "cd", PR_TRUE, 2 },
+ { "ABCDEFGABCDEFG", "ef", PR_TRUE, 4 },
+ { "ABCDEFGABCDEFG", "gh", PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", PR_TRUE, 1 },
+ { "ABCDEFGABCDEFG", "abcdefg", PR_TRUE, 0 }
+ };
+
+ int i;
+
+ printf("Test 027 (PL_strcasestr) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strcasestr(array[i].str, array[i].sub);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s -> null, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strcaserstr */
+PRBool test_028(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *sub;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, PR_FALSE, 0 },
+ { (const char *)0, "blah", PR_FALSE, 0 },
+ { "blah-de-blah", (const char *)0, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", PR_TRUE, 8 },
+ { "", "blah", PR_FALSE, 0 },
+ { "blah-de-blah", "", PR_FALSE, 0 },
+ { "abcdefg", "a", PR_TRUE, 0 },
+ { "abcdefg", "c", PR_TRUE, 2 },
+ { "abcdefg", "e", PR_TRUE, 4 },
+ { "abcdefg", "g", PR_TRUE, 6 },
+ { "abcdefg", "i", PR_FALSE, 0 },
+ { "abcdefg", "ab", PR_TRUE, 0 },
+ { "abcdefg", "cd", PR_TRUE, 2 },
+ { "abcdefg", "ef", PR_TRUE, 4 },
+ { "abcdefg", "gh", PR_FALSE, 0 },
+ { "abcdabc", "bc", PR_TRUE, 5 },
+ { "abcdefg", "abcdefg", PR_TRUE, 0 },
+ { "abcdefgabcdefg", "a", PR_TRUE, 7 },
+ { "abcdefgabcdefg", "c", PR_TRUE, 9 },
+ { "abcdefgabcdefg", "e", PR_TRUE, 11 },
+ { "abcdefgabcdefg", "g", PR_TRUE, 13 },
+ { "abcdefgabcdefg", "i", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ab", PR_TRUE, 7 },
+ { "abcdefgabcdefg", "cd", PR_TRUE, 9 },
+ { "abcdefgabcdefg", "ef", PR_TRUE, 11 },
+ { "abcdefgabcdefg", "gh", PR_FALSE, 0 },
+ { "abcdabcabcdabc", "bc", PR_TRUE, 12 },
+ { "abcdefgabcdefg", "abcdefg", PR_TRUE, 7 },
+ { "ABCDEFG", "a", PR_TRUE, 0 },
+ { "ABCDEFG", "c", PR_TRUE, 2 },
+ { "ABCDEFG", "e", PR_TRUE, 4 },
+ { "ABCDEFG", "g", PR_TRUE, 6 },
+ { "ABCDEFG", "i", PR_FALSE, 0 },
+ { "ABCDEFG", "ab", PR_TRUE, 0 },
+ { "ABCDEFG", "cd", PR_TRUE, 2 },
+ { "ABCDEFG", "ef", PR_TRUE, 4 },
+ { "ABCDEFG", "gh", PR_FALSE, 0 },
+ { "ABCDABC", "bc", PR_TRUE, 5 },
+ { "ABCDEFG", "abcdefg", PR_TRUE, 0 },
+ { "ABCDEFGABCDEFG", "a", PR_TRUE, 7 },
+ { "ABCDEFGABCDEFG", "c", PR_TRUE, 9 },
+ { "ABCDEFGABCDEFG", "e", PR_TRUE, 11 },
+ { "ABCDEFGABCDEFG", "g", PR_TRUE, 13 },
+ { "ABCDEFGABCDEFG", "i", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ab", PR_TRUE, 7 },
+ { "ABCDEFGABCDEFG", "cd", PR_TRUE, 9 },
+ { "ABCDEFGABCDEFG", "ef", PR_TRUE, 11 },
+ { "ABCDEFGABCDEFG", "gh", PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", PR_TRUE, 12 },
+ { "ABCDEFGABCDEFG", "abcdefg", PR_TRUE, 7 }
+ };
+
+ int i;
+
+ printf("Test 028 (PL_strcaserstr) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strcaserstr(array[i].str, array[i].sub);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s -> null, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strncasestr */
+PRBool test_029(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *sub;
+ PRUint32 max;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 12, PR_FALSE, 0 },
+ { (const char *)0, "blah", 12, PR_FALSE, 0 },
+ { "blah-de-blah", (const char *)0, 12, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 0, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 2, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 3, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 4, PR_TRUE, 0 },
+ { "blah-de-blah", "blah", 5, PR_TRUE, 0 },
+ { "blah-de-blah", "blah", 12, PR_TRUE, 0 },
+ { "", "blah", 12, PR_FALSE, 0 },
+ { "blah-de-blah", "", 12, PR_FALSE, 0 },
+ { "abcdefg", "a", 5, PR_TRUE, 0 },
+ { "abcdefg", "c", 5, PR_TRUE, 2 },
+ { "abcdefg", "e", 5, PR_TRUE, 4 },
+ { "abcdefg", "g", 5, PR_FALSE, 0 },
+ { "abcdefg", "i", 5, PR_FALSE, 0 },
+ { "abcdefg", "ab", 5, PR_TRUE, 0 },
+ { "abcdefg", "cd", 5, PR_TRUE, 2 },
+ { "abcdefg", "ef", 5, PR_FALSE, 0 },
+ { "abcdefg", "gh", 5, PR_FALSE, 0 },
+ { "abcdabc", "bc", 5, PR_TRUE, 1 },
+ { "abcdabc", "bc", 6, PR_TRUE, 1 },
+ { "abcdabc", "bc", 7, PR_TRUE, 1 },
+ { "abcdefg", "abcdefg", 6, PR_FALSE, 0 },
+ { "abcdefg", "abcdefg", 7, PR_TRUE, 0 },
+ { "abcdefg", "abcdefg", 8, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "a", 12, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "c", 12, PR_TRUE, 2 },
+ { "abcdefgabcdefg", "e", 12, PR_TRUE, 4 },
+ { "abcdefgabcdefg", "g", 12, PR_TRUE, 6 },
+ { "abcdefgabcdefg", "i", 12, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ab", 12, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "cd", 12, PR_TRUE, 2 },
+ { "abcdefgabcdefg", "ef", 12, PR_TRUE, 4 },
+ { "abcdefgabcdefg", "gh", 12, PR_FALSE, 0 },
+ { "abcdabcabcdabc", "bc", 5, PR_TRUE, 1 },
+ { "abcdabcabcdabc", "bc", 6, PR_TRUE, 1 },
+ { "abcdabcabcdabc", "bc", 7, PR_TRUE, 1 },
+ { "abcdefgabcdefg", "abcdefg", 6, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "abcdefg", 7, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "abcdefg", 8, PR_TRUE, 0 },
+ { "ABCDEFG", "a", 5, PR_TRUE, 0 },
+ { "ABCDEFG", "c", 5, PR_TRUE, 2 },
+ { "ABCDEFG", "e", 5, PR_TRUE, 4 },
+ { "ABCDEFG", "g", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "i", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "ab", 5, PR_TRUE, 0 },
+ { "ABCDEFG", "cd", 5, PR_TRUE, 2 },
+ { "ABCDEFG", "ef", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "gh", 5, PR_FALSE, 0 },
+ { "ABCDABC", "bc", 5, PR_TRUE, 1 },
+ { "ABCDABC", "bc", 6, PR_TRUE, 1 },
+ { "ABCDABC", "bc", 7, PR_TRUE, 1 },
+ { "ABCDEFG", "abcdefg", 6, PR_FALSE, 0 },
+ { "ABCDEFG", "abcdefg", 7, PR_TRUE, 0 },
+ { "ABCDEFG", "abcdefg", 8, PR_TRUE, 0 },
+ { "ABCDEFGABCDEFG", "a", 12, PR_TRUE, 0 },
+ { "ABCDEFGABCDEFG", "c", 12, PR_TRUE, 2 },
+ { "ABCDEFGABCDEFG", "e", 12, PR_TRUE, 4 },
+ { "ABCDEFGABCDEFG", "g", 12, PR_TRUE, 6 },
+ { "ABCDEFGABCDEFG", "i", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ab", 12, PR_TRUE, 0 },
+ { "ABCDEFGABCDEFG", "cd", 12, PR_TRUE, 2 },
+ { "ABCDEFGABCDEFG", "ef", 12, PR_TRUE, 4 },
+ { "ABCDEFGABCDEFG", "gh", 12, PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", 5, PR_TRUE, 1 },
+ { "ABCDABCABCDABC", "bc", 6, PR_TRUE, 1 },
+ { "ABCDABCABCDABC", "bc", 7, PR_TRUE, 1 },
+ { "ABCDEFGABCDEFG", "abcdefg", 6, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "abcdefg", 7, PR_TRUE, 0 },
+ { "ABCDEFGABCDEFG", "abcdefg", 8, PR_TRUE, 0 }
+ };
+
+ int i;
+
+ printf("Test 029 (PL_strncasestr) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strncasestr(array[i].str, array[i].sub, array[i].max);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> null, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strncaserstr */
+PRBool test_030(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *sub;
+ PRUint32 max;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 12, PR_FALSE, 0 },
+ { (const char *)0, "blah", 12, PR_FALSE, 0 },
+ { "blah-de-blah", (const char *)0, 12, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 0, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 2, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 3, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 4, PR_TRUE, 0 },
+ { "blah-de-blah", "blah", 5, PR_TRUE, 0 },
+ { "blah-de-blah", "blah", 11, PR_TRUE, 0 },
+ { "blah-de-blah", "blah", 12, PR_TRUE, 8 },
+ { "blah-de-blah", "blah", 13, PR_TRUE, 8 },
+ { "", "blah", 12, PR_FALSE, 0 },
+ { "blah-de-blah", "", 12, PR_FALSE, 0 },
+ { "abcdefg", "a", 5, PR_TRUE, 0 },
+ { "abcdefg", "c", 5, PR_TRUE, 2 },
+ { "abcdefg", "e", 5, PR_TRUE, 4 },
+ { "abcdefg", "g", 5, PR_FALSE, 0 },
+ { "abcdefg", "i", 5, PR_FALSE, 0 },
+ { "abcdefg", "ab", 5, PR_TRUE, 0 },
+ { "abcdefg", "cd", 5, PR_TRUE, 2 },
+ { "abcdefg", "ef", 5, PR_FALSE, 0 },
+ { "abcdefg", "gh", 5, PR_FALSE, 0 },
+ { "abcdabc", "bc", 5, PR_TRUE, 1 },
+ { "abcdabc", "bc", 6, PR_TRUE, 1 },
+ { "abcdabc", "bc", 7, PR_TRUE, 5 },
+ { "abcdefg", "abcdefg", 6, PR_FALSE, 0 },
+ { "abcdefg", "abcdefg", 7, PR_TRUE, 0 },
+ { "abcdefg", "abcdefg", 8, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "a", 12, PR_TRUE, 7 },
+ { "abcdefgabcdefg", "c", 12, PR_TRUE, 9 },
+ { "abcdefgabcdefg", "e", 12, PR_TRUE, 11 },
+ { "abcdefgabcdefg", "g", 12, PR_TRUE, 6 },
+ { "abcdefgabcdefg", "i", 12, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ab", 12, PR_TRUE, 7 },
+ { "abcdefgabcdefg", "cd", 12, PR_TRUE, 9 },
+ { "abcdefgabcdefg", "ef", 12, PR_TRUE, 4 },
+ { "abcdefgabcdefg", "gh", 12, PR_FALSE, 0 },
+ { "abcdabcabcdabc", "bc", 12, PR_TRUE, 8 },
+ { "abcdabcabcdabc", "bc", 13, PR_TRUE, 8 },
+ { "abcdabcabcdabc", "bc", 14, PR_TRUE, 12 },
+ { "abcdefgabcdefg", "abcdefg", 13, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "abcdefg", 14, PR_TRUE, 7 },
+ { "abcdefgabcdefg", "abcdefg", 15, PR_TRUE, 7 },
+ { "ABCDEFG", "a", 5, PR_TRUE, 0 },
+ { "ABCDEFG", "c", 5, PR_TRUE, 2 },
+ { "ABCDEFG", "e", 5, PR_TRUE, 4 },
+ { "ABCDEFG", "g", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "i", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "ab", 5, PR_TRUE, 0 },
+ { "ABCDEFG", "cd", 5, PR_TRUE, 2 },
+ { "ABCDEFG", "ef", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "gh", 5, PR_FALSE, 0 },
+ { "ABCDABC", "bc", 5, PR_TRUE, 1 },
+ { "ABCDABC", "bc", 6, PR_TRUE, 1 },
+ { "ABCDABC", "bc", 7, PR_TRUE, 5 },
+ { "ABCDEFG", "abcdefg", 6, PR_FALSE, 0 },
+ { "ABCDEFG", "abcdefg", 7, PR_TRUE, 0 },
+ { "ABCDEFG", "abcdefg", 8, PR_TRUE, 0 },
+ { "ABCDEFGABCDEFG", "a", 12, PR_TRUE, 7 },
+ { "ABCDEFGABCDEFG", "c", 12, PR_TRUE, 9 },
+ { "ABCDEFGABCDEFG", "e", 12, PR_TRUE, 11 },
+ { "ABCDEFGABCDEFG", "g", 12, PR_TRUE, 6 },
+ { "ABCDEFGABCDEFG", "i", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ab", 12, PR_TRUE, 7 },
+ { "ABCDEFGABCDEFG", "cd", 12, PR_TRUE, 9 },
+ { "ABCDEFGABCDEFG", "ef", 12, PR_TRUE, 4 },
+ { "ABCDEFGABCDEFG", "gh", 12, PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", 12, PR_TRUE, 8 },
+ { "ABCDABCABCDABC", "bc", 13, PR_TRUE, 8 },
+ { "ABCDABCABCDABC", "bc", 14, PR_TRUE, 12 },
+ { "ABCDEFGABCDEFG", "abcdefg", 13, PR_TRUE, 0 },
+ { "ABCDEFGABCDEFG", "abcdefg", 14, PR_TRUE, 7 },
+ { "ABCDEFGABCDEFG", "abcdefg", 15, PR_TRUE, 7 }
+ };
+
+ int i;
+
+ printf("Test 030 (PL_strncaserstr)..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strncaserstr(array[i].str, array[i].sub, array[i].max);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> null, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strtok_r */
+PRBool test_031(void)
+{
+ static const char *tokens[] = {
+ "wtc", "relyea", "nelsonb", "jpierre", "nicolson",
+ "ian.mcgreer", "kirk.erickson", "sonja.mirtitsch", "mhein"
+ };
+
+ static const char *seps[] = {
+ ", ", ",", " ", "\t", ",,,", " ,", " ", " \t\t", ","
+ };
+
+ static const char s2[] = ", \t";
+
+ char string[ 1024 ];
+ char *s1;
+ char *token;
+ char *lasts;
+ unsigned int i;
+
+ printf("Test 031 (PL_strtok_r) ..."); fflush(stdout);
+
+ /* Build the string. */
+ string[0] = '\0';
+ for( i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++ )
+ {
+ PL_strcat(string, tokens[i]);
+ PL_strcat(string, seps[i]);
+ }
+
+ /* Scan the string for tokens. */
+ i = 0;
+ s1 = string;
+ while( (token = PL_strtok_r(s1, s2, &lasts)) != NULL)
+ {
+ if( PL_strcmp(token, tokens[i]) != 0 )
+ {
+ printf("FAIL wrong token scanned\n");
+ return PR_FALSE;
+ }
+ i++;
+ s1 = NULL;
+ }
+ if( i != sizeof(tokens)/sizeof(tokens[0]) )
+ {
+ printf("FAIL wrong number of tokens scanned\n");
+ return PR_FALSE;
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+int
+main
+(
+ int argc,
+ char *argv[]
+)
+{
+ printf("Testing the Portable Library string functions:\n");
+
+ if( 1
+ && test_001()
+ && test_001()
+ && test_002()
+ && test_003()
+ && test_004()
+ && test_005()
+ && test_006()
+ && test_007()
+ && test_008()
+ && test_009()
+ && test_010()
+ && test_011()
+ && test_012()
+ && test_013()
+ && test_014()
+ && test_015()
+ && test_016()
+ && test_017()
+ && test_018()
+ && test_019()
+ && test_020()
+ && test_021()
+ && test_022()
+ && test_023()
+ && test_024()
+ && test_025()
+ && test_026()
+ && test_027()
+ && test_028()
+ && test_029()
+ && test_030()
+ && test_031()
+ )
+ {
+ printf("Suite passed.\n");
+ return 0;
+ }
+ else
+ {
+ printf("Suite failed.\n");
+ return 1;
+ }
+
+ /*NOTREACHED*/
+}