Landing of miscellaneous changes, including the new error code to
authorwtc%netscape.com
Fri, 26 Feb 1999 20:41:06 +0000
changeset 475 d664f3cc7aae3ef493ceada455cea1db1346e7a8
parent 474 a3a6e8f7bad213f901e674d33998322d0f22431b
child 476 62eb270c04f6caef910bee3c1f5d055a989b8efd
push idunknown
push userunknown
push dateunknown
Landing of miscellaneous changes, including the new error code to string function contributed by John Myers <jgmyers@netscape.com>.
lib/tests/Makefile
pr/include/MANIFEST
pr/include/nspr.h
pr/include/prerr.h
pr/include/prerror.h
pr/include/prerrorplugin.h
pr/src/Makefile
pr/src/md/unix/uxpoll.c
pr/src/misc/Makefile
pr/src/misc/compile-et.pl
pr/src/misc/prerr.c
pr/src/misc/prerr.et
pr/src/misc/prerrortable.c
pr/src/misc/prinit.c
pr/src/pthreads/ptthread.c
pr/src/threads/prrwlock.c
pr/tests/Makefile
pr/tests/strod.c
--- a/lib/tests/Makefile
+++ b/lib/tests/Makefile
@@ -69,16 +69,27 @@ endif
 ifneq ($(OS_ARCH), WINNT)
 PWD = $(shell pwd)
 endif
 
 ifeq ($(OS_ARCH), IRIX)
 LDOPTS += -rpath $(PWD)/$(DIST)/lib
 endif
 
+ifeq ($(OS_ARCH), Linux)
+    ifeq ($(OS_RELEASE), 1.2)
+        EXTRA_LIBS = -ldl
+    else
+        LDOPTS += -Xlinker -rpath $(PWD)/$(DIST)/lib
+        ifeq ($(USE_PTHREADS),1)
+            EXTRA_LIBS = -lpthread
+        endif
+    endif
+endif
+
 ifeq ($(OS_ARCH), OSF1)
 LDOPTS += -rpath $(PWD)/$(DIST)/lib -lpthread
 endif
 
 ifeq ($(OS_ARCH), HP-UX)
 LDOPTS += -Wl,+s,+b,$(PWD)/$(DIST)/lib
 endif
 
--- a/pr/include/MANIFEST
+++ b/pr/include/MANIFEST
@@ -6,33 +6,36 @@ nspr.h
 pratom.h
 prbit.h
 prclist.h
 prcmon.h
 prcountr.h
 prcvar.h
 prdtoa.h
 prenv.h
+prerr.h
 prerror.h
+prerrorplugin.h
 prinet.h
 prinit.h
 prinrval.h
 prio.h
 prlink.h
 prlock.h
 prlog.h
 prlong.h
 prmem.h
 prmon.h
 prmwait.h
 prnetdb.h
 prolock.h
 prpdce.h
 prprf.h
 prproces.h
+prrwlock.h
 prsystem.h
 prthread.h
 prtime.h
 prtrace.h
 prtypes.h
 prvrsion.h
 prwin16.h
 
--- a/pr/include/nspr.h
+++ b/pr/include/nspr.h
@@ -22,28 +22,30 @@
 #include "pratom.h"
 #include "prbit.h"
 #include "prclist.h"
 #include "prcmon.h"
 #include "prcvar.h"
 #include "prdtoa.h"
 #include "prenv.h"
 #include "prerror.h"
+#include "prerrorplugin.h"
 #include "prinet.h"
 #include "prinit.h"
 #include "prinrval.h"
 #include "prio.h"
 #include "prlink.h"
 #include "prlock.h"
 #include "prlog.h"
 #include "prlong.h"
 #include "prmem.h"
 #include "prmon.h"
 #include "prmwait.h"
 #include "prnetdb.h"
 #include "prprf.h"
 #include "prproces.h"
+#include "prrwlock.h"
 #include "prsystem.h"
 #include "prthread.h"
 #include "prtime.h"
 #include "prtypes.h"
 
 #endif /* nspr_h___ */
new file mode 100644
--- /dev/null
+++ b/pr/include/prerr.h
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL.  You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ * 
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ * 
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation.  Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
+ * Reserved.
+ */
+
+#ifndef prerr_h___
+#define prerr_h___
+
+/*
+ *
+ * prerr.h
+ * This file is automatically generated; please do not edit it.
+ */
+#define PR_OUT_OF_MEMORY_ERROR                   (-6000L)
+#define PR_BAD_DESCRIPTOR_ERROR                  (-5999L)
+#define PR_WOULD_BLOCK_ERROR                     (-5998L)
+#define PR_ACCESS_FAULT_ERROR                    (-5997L)
+#define PR_INVALID_METHOD_ERROR                  (-5996L)
+#define PR_ILLEGAL_ACCESS_ERROR                  (-5995L)
+#define PR_UNKNOWN_ERROR                         (-5994L)
+#define PR_PENDING_INTERRUPT_ERROR               (-5993L)
+#define PR_NOT_IMPLEMENTED_ERROR                 (-5992L)
+#define PR_IO_ERROR                              (-5991L)
+#define PR_IO_TIMEOUT_ERROR                      (-5990L)
+#define PR_IO_PENDING_ERROR                      (-5989L)
+#define PR_DIRECTORY_OPEN_ERROR                  (-5988L)
+#define PR_INVALID_ARGUMENT_ERROR                (-5987L)
+#define PR_ADDRESS_NOT_AVAILABLE_ERROR           (-5986L)
+#define PR_ADDRESS_NOT_SUPPORTED_ERROR           (-5985L)
+#define PR_IS_CONNECTED_ERROR                    (-5984L)
+#define PR_BAD_ADDRESS_ERROR                     (-5983L)
+#define PR_ADDRESS_IN_USE_ERROR                  (-5982L)
+#define PR_CONNECT_REFUSED_ERROR                 (-5981L)
+#define PR_NETWORK_UNREACHABLE_ERROR             (-5980L)
+#define PR_CONNECT_TIMEOUT_ERROR                 (-5979L)
+#define PR_NOT_CONNECTED_ERROR                   (-5978L)
+#define PR_LOAD_LIBRARY_ERROR                    (-5977L)
+#define PR_UNLOAD_LIBRARY_ERROR                  (-5976L)
+#define PR_FIND_SYMBOL_ERROR                     (-5975L)
+#define PR_INSUFFICIENT_RESOURCES_ERROR          (-5974L)
+#define PR_DIRECTORY_LOOKUP_ERROR                (-5973L)
+#define PR_TPD_RANGE_ERROR                       (-5972L)
+#define PR_PROC_DESC_TABLE_FULL_ERROR            (-5971L)
+#define PR_SYS_DESC_TABLE_FULL_ERROR             (-5970L)
+#define PR_NOT_SOCKET_ERROR                      (-5969L)
+#define PR_NOT_TCP_SOCKET_ERROR                  (-5968L)
+#define PR_SOCKET_ADDRESS_IS_BOUND_ERROR         (-5967L)
+#define PR_NO_ACCESS_RIGHTS_ERROR                (-5966L)
+#define PR_OPERATION_NOT_SUPPORTED_ERROR         (-5965L)
+#define PR_PROTOCOL_NOT_SUPPORTED_ERROR          (-5964L)
+#define PR_REMOTE_FILE_ERROR                     (-5963L)
+#define PR_BUFFER_OVERFLOW_ERROR                 (-5962L)
+#define PR_CONNECT_RESET_ERROR                   (-5961L)
+#define PR_RANGE_ERROR                           (-5960L)
+#define PR_DEADLOCK_ERROR                        (-5959L)
+#define PR_FILE_IS_LOCKED_ERROR                  (-5958L)
+#define PR_FILE_TOO_BIG_ERROR                    (-5957L)
+#define PR_NO_DEVICE_SPACE_ERROR                 (-5956L)
+#define PR_PIPE_ERROR                            (-5955L)
+#define PR_NO_SEEK_DEVICE_ERROR                  (-5954L)
+#define PR_IS_DIRECTORY_ERROR                    (-5953L)
+#define PR_LOOP_ERROR                            (-5952L)
+#define PR_NAME_TOO_LONG_ERROR                   (-5951L)
+#define PR_FILE_NOT_FOUND_ERROR                  (-5950L)
+#define PR_NOT_DIRECTORY_ERROR                   (-5949L)
+#define PR_READ_ONLY_FILESYSTEM_ERROR            (-5948L)
+#define PR_DIRECTORY_NOT_EMPTY_ERROR             (-5947L)
+#define PR_FILESYSTEM_MOUNTED_ERROR              (-5946L)
+#define PR_NOT_SAME_DEVICE_ERROR                 (-5945L)
+#define PR_DIRECTORY_CORRUPTED_ERROR             (-5944L)
+#define PR_FILE_EXISTS_ERROR                     (-5943L)
+#define PR_MAX_DIRECTORY_ENTRIES_ERROR           (-5942L)
+#define PR_INVALID_DEVICE_STATE_ERROR            (-5941L)
+#define PR_DEVICE_IS_LOCKED_ERROR                (-5940L)
+#define PR_NO_MORE_FILES_ERROR                   (-5939L)
+#define PR_END_OF_FILE_ERROR                     (-5938L)
+#define PR_FILE_SEEK_ERROR                       (-5937L)
+#define PR_FILE_IS_BUSY_ERROR                    (-5936L)
+#define PR_RESERVED_ERROR                        (-5935L)
+#define PR_IN_PROGRESS_ERROR                     (-5934L)
+#define PR_ALREADY_INITIATED_ERROR               (-5933L)
+#define PR_GROUP_EMPTY_ERROR                     (-5932L)
+#define PR_INVALID_STATE_ERROR                   (-5931L)
+#define PR_NETWORK_DOWN_ERROR                    (-5930L)
+#define PR_SOCKET_SHUTDOWN_ERROR                 (-5929L)
+#define PR_CONNECT_ABORTED_ERROR                 (-5928L)
+#define PR_HOST_UNREACHABLE_ERROR                (-5927L)
+#define PR_MAX_ERROR                             (-5926L)
+extern void pr_init_error_table_nspr(void);
+#define ERROR_TABLE_BASE_nspr (-6000L)
+
+#endif /* prerr_h___ */
--- a/pr/include/prerror.h
+++ b/pr/include/prerror.h
@@ -22,142 +22,17 @@
 #include "prtypes.h"
 
 PR_BEGIN_EXTERN_C
 
 typedef PRInt32 PRErrorCode;
 
 #define PR_NSPR_ERROR_BASE -6000
 
-#define PR_OUT_OF_MEMORY_ERROR              PR_NSPR_ERROR_BASE + 0
-                                    /* Insufficient memory to perform request   */
-#define PR_BAD_DESCRIPTOR_ERROR             PR_NSPR_ERROR_BASE + 1
-                                    /* the file descriptor used as an argument
-                                       in the function is invalid; either it has
-                                       been deleted or otherwise corrupted.     */
-#define PR_WOULD_BLOCK_ERROR                PR_NSPR_ERROR_BASE + 2
-                                    /* The operation would have blocked and that
-                                       is in conflict with the semantics that
-                                       have been established.                   */
-#define PR_ACCESS_FAULT_ERROR               PR_NSPR_ERROR_BASE + 3
-#define PR_INVALID_METHOD_ERROR             PR_NSPR_ERROR_BASE + 4
-                                    /* The method being called is invalid for
-                                       the type of file descriptor used.        */
-#define PR_ILLEGAL_ACCESS_ERROR             PR_NSPR_ERROR_BASE + 5
-#define PR_UNKNOWN_ERROR                    PR_NSPR_ERROR_BASE + 6
-                                    /* Some unknown error has occured */
-#define PR_PENDING_INTERRUPT_ERROR          PR_NSPR_ERROR_BASE + 7
-                                    /* The operation terminated because another
-                                       thread has interrupted it (PR_Interrupt) */
-#define PR_NOT_IMPLEMENTED_ERROR            PR_NSPR_ERROR_BASE + 8
-                                    /* The function called has not been
-                                       implemented.                             */
-#define PR_IO_ERROR                         PR_NSPR_ERROR_BASE + 9
-#define PR_IO_TIMEOUT_ERROR                 PR_NSPR_ERROR_BASE + 10
-                                    /* The I/O operation has not completed in
-                                       the time specified for the function.     */
-#define PR_IO_PENDING_ERROR                 PR_NSPR_ERROR_BASE + 11
-                                    /* An I/O operation has been attempted on
-                                       a file descriptor that is currently
-                                       busy with another operation.             */
-#define PR_DIRECTORY_OPEN_ERROR             PR_NSPR_ERROR_BASE + 12
-                                    /* The directory could not be opened.       */
-#define PR_INVALID_ARGUMENT_ERROR           PR_NSPR_ERROR_BASE + 13
-                                    /* One or more of the arguments to the 
-                                       function is invalid.                     */
-#define PR_ADDRESS_NOT_AVAILABLE_ERROR      PR_NSPR_ERROR_BASE + 14
-                                    /* The network address (PRNetAddr) is not
-                                       available (probably in use).             */
-#define PR_ADDRESS_NOT_SUPPORTED_ERROR      PR_NSPR_ERROR_BASE + 15
-#define PR_IS_CONNECTED_ERROR               PR_NSPR_ERROR_BASE + 16
-                                    /* An attempt to connect on an already
-                                       connected network file descriptor.       */ 
-#define PR_BAD_ADDRESS_ERROR                PR_NSPR_ERROR_BASE + 17
-                                     /* The network address specified is invalid
-                                       (as reported by the network).            */
-#define PR_ADDRESS_IN_USE_ERROR             PR_NSPR_ERROR_BASE + 18
-#define PR_CONNECT_REFUSED_ERROR            PR_NSPR_ERROR_BASE + 19
-                                    /* The peer has refused to allow the connec-
-                                       tion to be established.                  */
-#define PR_NETWORK_UNREACHABLE_ERROR        PR_NSPR_ERROR_BASE + 20
-                                    /* The network address specifies a host
-                                       that is unreachable (perhaps temporary). */
-#define PR_CONNECT_TIMEOUT_ERROR            PR_NSPR_ERROR_BASE + 21
-                                    /* The connection attempt did not complete
-                                       in a reasonable period of time.          */
-#define PR_NOT_CONNECTED_ERROR              PR_NSPR_ERROR_BASE + 22
-                                    /* The call attempted to use connected
-                                       sematics on a network file descriptor
-                                       that was not connected.                  */
-#define PR_LOAD_LIBRARY_ERROR               PR_NSPR_ERROR_BASE + 23
-                                    /* Some sort of failure attempting to load
-                                       a dynamic library.                       */
-#define PR_UNLOAD_LIBRARY_ERROR             PR_NSPR_ERROR_BASE + 24
-                                    /* Some sort of failure attempting to unload
-                                       a dynamic library.                       */
-#define PR_FIND_SYMBOL_ERROR                PR_NSPR_ERROR_BASE + 25
-                                    /* Dynamic library symbol could not be found
-                                       in any of the available libraries.       */
-#define PR_INSUFFICIENT_RESOURCES_ERROR     PR_NSPR_ERROR_BASE + 26
-                                    /* There are insufficient system resources
-                                       to process the request.                  */
-#define PR_DIRECTORY_LOOKUP_ERROR           PR_NSPR_ERROR_BASE + 27
-#define PR_TPD_RANGE_ERROR                  PR_NSPR_ERROR_BASE + 28
-                                    /* Attempt to access a TPD key that is beyond
-                                       any key that has been allocated to the
-                                       process.                                 */
-
-#define PR_PROC_DESC_TABLE_FULL_ERROR       PR_NSPR_ERROR_BASE + 29
-#define PR_SYS_DESC_TABLE_FULL_ERROR        PR_NSPR_ERROR_BASE + 30
-#define PR_NOT_SOCKET_ERROR                 PR_NSPR_ERROR_BASE + 31
-#define PR_NOT_TCP_SOCKET_ERROR             PR_NSPR_ERROR_BASE + 32
-#define PR_SOCKET_ADDRESS_IS_BOUND_ERROR    PR_NSPR_ERROR_BASE + 33
-#define PR_NO_ACCESS_RIGHTS_ERROR           PR_NSPR_ERROR_BASE + 34
-#define PR_OPERATION_NOT_SUPPORTED_ERROR    PR_NSPR_ERROR_BASE + 35
-#define PR_PROTOCOL_NOT_SUPPORTED_ERROR     PR_NSPR_ERROR_BASE + 36
-#define PR_REMOTE_FILE_ERROR                PR_NSPR_ERROR_BASE + 37
-#define PR_BUFFER_OVERFLOW_ERROR            PR_NSPR_ERROR_BASE + 38
-#define PR_CONNECT_RESET_ERROR              PR_NSPR_ERROR_BASE + 39
-#define PR_RANGE_ERROR                      PR_NSPR_ERROR_BASE + 40
-
-#define PR_DEADLOCK_ERROR                   PR_NSPR_ERROR_BASE + 41
-#define PR_FILE_IS_LOCKED_ERROR             PR_NSPR_ERROR_BASE + 42
-#define PR_FILE_TOO_BIG_ERROR               PR_NSPR_ERROR_BASE + 43
-#define PR_NO_DEVICE_SPACE_ERROR            PR_NSPR_ERROR_BASE + 44
-#define PR_PIPE_ERROR                       PR_NSPR_ERROR_BASE + 45
-#define PR_NO_SEEK_DEVICE_ERROR             PR_NSPR_ERROR_BASE + 46
-#define PR_IS_DIRECTORY_ERROR               PR_NSPR_ERROR_BASE + 47
-#define PR_LOOP_ERROR                       PR_NSPR_ERROR_BASE + 48
-#define PR_NAME_TOO_LONG_ERROR              PR_NSPR_ERROR_BASE + 49
-#define PR_FILE_NOT_FOUND_ERROR             PR_NSPR_ERROR_BASE + 50
-#define PR_NOT_DIRECTORY_ERROR              PR_NSPR_ERROR_BASE + 51
-#define PR_READ_ONLY_FILESYSTEM_ERROR       PR_NSPR_ERROR_BASE + 52
-#define PR_DIRECTORY_NOT_EMPTY_ERROR        PR_NSPR_ERROR_BASE + 53
-#define PR_FILESYSTEM_MOUNTED_ERROR         PR_NSPR_ERROR_BASE + 54
-#define PR_NOT_SAME_DEVICE_ERROR            PR_NSPR_ERROR_BASE + 55
-#define PR_DIRECTORY_CORRUPTED_ERROR        PR_NSPR_ERROR_BASE + 56
-#define PR_FILE_EXISTS_ERROR                PR_NSPR_ERROR_BASE + 57
-#define PR_MAX_DIRECTORY_ENTRIES_ERROR      PR_NSPR_ERROR_BASE + 58
-#define PR_INVALID_DEVICE_STATE_ERROR       PR_NSPR_ERROR_BASE + 59
-#define PR_DEVICE_IS_LOCKED_ERROR           PR_NSPR_ERROR_BASE + 60
-#define PR_NO_MORE_FILES_ERROR              PR_NSPR_ERROR_BASE + 61
-#define PR_END_OF_FILE_ERROR                PR_NSPR_ERROR_BASE + 62
-#define PR_FILE_SEEK_ERROR                  PR_NSPR_ERROR_BASE + 63
-#define PR_FILE_IS_BUSY_ERROR               PR_NSPR_ERROR_BASE + 64
-	
-#define PR_IN_PROGRESS_ERROR                PR_NSPR_ERROR_BASE + 66
-#define PR_ALREADY_INITIATED_ERROR          PR_NSPR_ERROR_BASE + 67
-#define PR_GROUP_EMPTY_ERROR                PR_NSPR_ERROR_BASE + 68
-#define PR_INVALID_STATE_ERROR              PR_NSPR_ERROR_BASE + 69
-#define PR_NETWORK_DOWN_ERROR               PR_NSPR_ERROR_BASE + 70
-#define PR_SOCKET_SHUTDOWN_ERROR            PR_NSPR_ERROR_BASE + 71
-#define PR_CONNECT_ABORTED_ERROR            PR_NSPR_ERROR_BASE + 72
-#define PR_HOST_UNREACHABLE_ERROR           PR_NSPR_ERROR_BASE + 73
-#define PR_MAX_ERROR                        PR_NSPR_ERROR_BASE + 74
-                                    /* Place holder for the end of the list     */
+#include "prerr.h"
 
 /*
 ** Set error will preserve an error condition within a thread context.
 ** The values stored are the NSPR (platform independent) translation of
 ** the error. Also, if available, the platform specific oserror is stored.
 ** If there is no appropriate OS error number, a zero my be supplied.
 */
 PR_EXTERN(void) PR_SetError(PRErrorCode errorCode, PRInt32 oserr);
@@ -195,11 +70,116 @@ PR_EXTERN(PRInt32) PR_GetErrorTextLength
 /*
 ** Copy the current threads current error text. Then actual number of bytes
 ** copied is returned as the result. If the result is zero, the 'text' area
 ** is unaffected.
 */
 PR_EXTERN(PRInt32) PR_GetErrorText(char *text);
 
 
+/*
+Copyright (C) 1987, 1988 Student Information Processing Board of the
+Massachusetts Institute of Technology.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted, provided
+that the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+used in advertising or publicity pertaining to distribution of the software
+without specific, written prior permission.  M.I.T. and the M.I.T. S.I.P.B.
+make no representations about the suitability of this software for any
+purpose.  It is provided "as is" without express or implied warranty.
+*/
+
+/*
+** Description:	Localizable error code to string function.
+**
+**
+** NSPR provides a mechanism for converting an error code to a descriptive
+** string, in a caller-specified language.
+**
+** Error codes themselves are 32 bit (signed) integers.  Typically, the high
+** order 24 bits are an identifier of which error table the error code is
+** from, and the low order 8 bits are a sequential error number within
+** the table.  NSPR supports error tables whose first error code is not
+** a multiple of 256, such error code assignments should be avoided when
+** possible.
+**
+** Error table 0 is defined to match the UNIX system call error table
+** (sys_errlist); this allows errno values to be used directly in the
+** library.  Other error table numbers are typically formed by compacting
+** together the first four characters of the error table name.  The mapping
+** between characters in the name and numeric values in the error code are
+** defined in a system-independent fashion, so that two systems that can
+** pass integral values between them can reliably pass error codes without
+** loss of meaning; this should work even if the character sets used are not
+** the same. (However, if this is to be done, error table 0 should be avoided,
+** since the local system call error tables may differ.)
+**
+** Libraries defining error codes need only provide a table mapping error
+** code numbers to names and default English descriptions, calling a routine
+** to make the table ``known'' to NSPR library.  Any error code the library
+** generates can be converted to the corresponding error message.  There is
+** also a default format for error codes accidentally returned before making
+** the table known, which is of the form "unknown code foo 32", where "foo"
+** would be the name of the table.
+**
+** Normally, the error code conversion routine only supports the languages
+** "i-default" and "en", returning the error-table-provided English
+** description for both languages.  The application may provide a
+** localization plugin, allowing support for additional languages.
+**
+**/
+
+/**********************************************************************/
+/************************* TYPES AND CONSTANTS ************************/
+/**********************************************************************/
+
+/*
+ * PRLanguageCode --
+ *
+ *    NSPR represents a language code as a non-negative integer.
+ *    Languages 0 is always "i-default" the language you get without
+ *    explicit negotiation.  Language 1 is always "en", English
+ *    which has been explicitly negotiated.  Additional language
+ *    codes are defined by an application-provided localization plugin.
+ */
+typedef PRInt32 PRLanguageCode;
+#define PR_LANGUAGE_I_DEFAULT 0 /* i-default, the default language */
+#define PR_LANGUAGE_EN 1 /* English, explicitly negotiated */
+
+/**********************************************************************/
+/****************************** FUNCTIONS *****************************/
+/**********************************************************************/
+
+/***********************************************************************
+** FUNCTION:    PR_ErrorTableToString
+** DESCRIPTION:
+**  Returns the UTF-8 message for an error code in
+**  the requested language.  May return the message
+**  in the default language if a translation in the requested
+**  language is not available.  The returned string is
+**  valid for the duration of the process.  Never returns NULL.
+**
+***********************************************************************/
+PR_EXTERN(const char *) PR_ErrorToString(PRErrorCode code,
+    PRLanguageCode language);
+
+/***********************************************************************
+** FUNCTION:    PR_ErrorLanguages
+** DESCRIPTION:
+**  Returns the RFC 1766 language tags for the language
+**  codes PR_ErrorToString() supports.  The returned array is valid
+**  for the duration of the process.  Never returns NULL.  The first
+**  item in the returned array is the language tag for PRLanguageCode 0,
+**  the second is for PRLanguageCode 1, and so on.  The array is terminated
+**  with a null pointer.
+**
+***********************************************************************/
+/*
+ * Return the language codes for supported languages.
+ */
+PR_EXTERN(const char * const *) PR_ErrorLanguages(void);
+
 PR_END_EXTERN_C
 
 #endif /* prerror_h___ */
new file mode 100644
--- /dev/null
+++ b/pr/include/prerrorplugin.h
@@ -0,0 +1,124 @@
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL.  You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ * 
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ * 
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation.  Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
+ * Reserved.
+ */
+
+#ifndef prerrorplugin_h___
+#define prerrorplugin_h___
+
+#include "prerror.h"
+
+PR_BEGIN_EXTERN_C
+
+/**********************************************************************/
+/************************* TYPES AND CONSTANTS ************************/
+/**********************************************************************/
+
+/*
+ * struct PRErrorTable --
+ *
+ *    An error table, provided by a library.
+ */
+struct PRErrorTable {
+    struct PRErrorMessage {
+	const char * const name;    /* Macro name for error */
+	const char * const en_text; /* default english text */
+    } const * msgs; /* Array of error information */
+
+    const char *name; /* Name of error table source */
+    PRErrorCode base; /* Error code for first error in table */
+    int n_msgs; /* Number of codes in table */
+};
+
+/*
+ * struct PRErrorPluginRock --
+ *
+ *    A rock, under which the localization plugin may store information
+ *    that is private to itself.
+ */
+struct PRErrorPluginRock;
+
+/*
+ * struct PRErrorPluginTableRock --
+ *
+ *    A rock, under which the localization plugin may store information,
+ *    associated with an error table, that is private to itself.
+ */
+struct PRErrorPluginTableRock;
+
+/*
+ * PRErrorPluginLookupFn --
+ *
+ *    A function of PRErrorPluginLookupFn type is a localization
+ *    plugin callback which converts an error code into a description
+ *    in the requested language.  The callback is provided the
+ *    appropriate error table, rock, and table rock.  The callback
+ *    returns the appropriate UTF-8 encoded description, or NULL if no
+ *    description can be found.
+ */
+typedef const char *
+PRErrorPluginLookupFn(PRErrorCode code, PRLanguageCode language, 
+		   const struct PRErrorTable *table,
+		   struct PRErrorPluginRock *rock,
+		   struct PRErrorPluginTableRock *table_rock);
+
+/*
+ * PRErrorPluginNewtableFn --
+ *
+ *    A function PRErrorPluginNewtableFn type is a localization plugin
+ *    callback which is called once with each error table registered
+ *    with NSPR.  The callback is provided with the error table and
+ *    the plugin rock.  The callback returns any table rock it wishes
+ *    to associate with the error table.  Does not need to be thread
+ *    safe.
+ */
+typedef struct PRErrorPluginTableRock *
+PRErrorPluginNewtableFn(const struct PRErrorTable *table,
+			struct PRErrorPluginRock *rock);
+
+/**********************************************************************/
+/****************************** FUNCTIONS *****************************/
+/**********************************************************************/
+
+/***********************************************************************
+** FUNCTION:    PR_ErrorInstallTable
+** DESCRIPTION:
+**  Registers an error table with NSPR.  Must be done exactly once per
+**  table.
+**  NOT THREAD SAFE!
+**  
+***********************************************************************/
+PR_EXTERN(PRErrorCode) PR_ErrorInstallTable(const struct PRErrorTable *table);
+
+
+/***********************************************************************
+** FUNCTION:    PR_ErrorInstallPlugin
+** DESCRIPTION:
+**  Registers an error localization plugin with NSPR.  May be called
+**  at most one time.  `languages' contains the language codes supported
+**  by this plugin.  Languages 0 and 1 must be "i-default" and "en"
+**  respectively.  `lookup' and `newtable' contain pointers to
+**  the plugin callback functions.  `rock' contains any information
+**  private to the plugin functions.
+**  NOT THREAD SAFE!
+***********************************************************************/
+PR_EXTERN(void) PR_ErrorInstallPlugin(const char * const * languages,
+			      PRErrorPluginLookupFn *lookup, 
+			      PRErrorPluginNewtableFn *newtable,
+			      struct PRErrorPluginRock *rock);
+
+PR_END_EXTERN_C
+
+#endif /* prerrorplugin_h___ */
--- a/pr/src/Makefile
+++ b/pr/src/Makefile
@@ -172,17 +172,19 @@ OBJS = \
     malloc/$(OBJDIR)/prmem.$(OBJ_SUFFIX) \
     md/$(OBJDIR)/prosdep.$(OBJ_SUFFIX) \
     memory/$(OBJDIR)/prseg.$(OBJ_SUFFIX) \
     misc/$(OBJDIR)/pralarm.$(OBJ_SUFFIX) \
     misc/$(OBJDIR)/pratom.$(OBJ_SUFFIX) \
     misc/$(OBJDIR)/prcountr.$(OBJ_SUFFIX) \
     misc/$(OBJDIR)/prdtoa.$(OBJ_SUFFIX) \
     misc/$(OBJDIR)/prenv.$(OBJ_SUFFIX) \
+    misc/$(OBJDIR)/prerr.$(OBJ_SUFFIX) \
     misc/$(OBJDIR)/prerror.$(OBJ_SUFFIX) \
+    misc/$(OBJDIR)/prerrortable.$(OBJ_SUFFIX) \
     misc/$(OBJDIR)/prinit.$(OBJ_SUFFIX) \
     misc/$(OBJDIR)/prinrval.$(OBJ_SUFFIX) \
     misc/$(OBJDIR)/prlog2.$(OBJ_SUFFIX) \
     misc/$(OBJDIR)/prlong.$(OBJ_SUFFIX) \
     misc/$(OBJDIR)/prnetdb.$(OBJ_SUFFIX) \
     misc/$(OBJDIR)/prolock.$(OBJ_SUFFIX)	 \
     misc/$(OBJDIR)/prsystem.$(OBJ_SUFFIX) \
     misc/$(OBJDIR)/prthinfo.$(OBJ_SUFFIX) \
--- a/pr/src/md/unix/uxpoll.c
+++ b/pr/src/md/unix/uxpoll.c
@@ -12,16 +12,20 @@
  * 
  * The Initial Developer of this code under the NPL is Netscape
  * Communications Corporation.  Portions created by Netscape are
  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  * Reserved.
  */
 
 #if defined(_PR_PTHREADS)
+
+/* Some compilers don't like an empty source file. */
+static int dummy = 0;
+
 #else  /* defined(_PR_PTHREADS) */
 
 #include "primpl.h"
 
 #include <sys/time.h>
 
 #include <fcntl.h>
 #ifdef _PR_USE_POLL
--- a/pr/src/misc/Makefile
+++ b/pr/src/misc/Makefile
@@ -29,17 +29,19 @@ endif
 endif
 
 CSRCS = \
 	pralarm.c  \
 	pratom.c   \
 	prcountr.c \
 	prdtoa.c   \
 	prenv.c    \
+	prerr.c  \
 	prerror.c  \
+	prerrortable.c  \
 	prinit.c   \
 	prinrval.c \
 	prlog2.c   \
 	prlong.c   \
 	prnetdb.c  \
 	prolock.c  \
 	prsystem.c \
 	prtime.c   \
@@ -56,12 +58,15 @@ include $(MOD_DEPTH)/config/rules.mk
 # An AIX Optimization bug causes PR_dtoa() to produce wrong result.
 # This suppresses optimization for this single compilation unit.
 ifeq ($(OS_ARCH), AIX)
 $(OBJDIR)/prdtoa.o:
 	@$(MAKE_OBJDIR)
 	$(CC) -o $@ -c $(filter-out -O, $(CFLAGS)) prdtoa.c
 endif
 
+build_prerr : prerr.et
+	perl compile-et.pl prerr.et
+
 export:: $(TARGETS)
 
 install:: export
 
new file mode 100644
--- /dev/null
+++ b/pr/src/misc/compile-et.pl
@@ -0,0 +1,115 @@
+#!/usr/bin/perl
+
+# usage: compile-et input.et
+
+# The contents of this file are subject to the Netscape Public License
+# Version 1.0 (the "NPL"); you may not use this file except in
+# compliance with the NPL.  You may obtain a copy of the NPL at
+# http://www.mozilla.org/NPL/
+# 
+# Software distributed under the NPL is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+# for the specific language governing rights and limitations under the
+# NPL.
+# 
+# The Initial Developer of this code under the NPL is Netscape
+# Communications Corporation.  Portions created by Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation.  All Rights
+# Reserved.
+
+sub header
+{
+    local($filename, $comment) = @_;
+
+<<EOF
+$comment
+$comment $filename
+$comment This file is automatically generated; please do not edit it.
+EOF
+}
+
+sub table_base
+{
+    local($name) = @_;
+    local($base) = 0;
+
+    for ($i = 0; $i < length($name); $i++) {
+	$base *= 64;
+	$base += index("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_", substr($name, $i, 1)) + 1;
+    }
+    $base -= 0x1000000 if ($base > 0x7fffff);
+    $base*256;
+}
+
+sub code {
+    local($macro, $text) = @_;
+    $code = $table_base + $table_item_count;
+
+    printf H "#define %-40s (%dL)\n", $macro, $code;
+
+    print C "\t{\"", $macro, "\",    \"", $text, "\"},\n";
+
+    print PROPERTIES $macro, "=", $text, "\n";
+
+    $table_item_count++;
+}
+
+
+$filename = $ARGV[0];
+open(INPUT, "< $filename") || die "Can't read $filename: $!\n";
+
+$base = "$filename";
+$base =~ s/\.et$//;
+$base =~ s#.*/##;
+
+open(H, "> ${base}.h") || die "Can't write ${base}.h\n";
+open(C, "> ${base}.c") || die "Can't write ${base}.c\n";
+open(PROPERTIES, "> ${base}.properties") || die "Can't write ${base}.properties\n";
+
+print H "/*\n", &header("${base}.h", " *"), " */\n";
+print C "/*\n", &header("${base}.c", " *"), " */\n";
+print PROPERTIES &header("${base}.properties", "#");
+
+$skipone = 0;
+
+while ($_ = <INPUT>) {
+    next if /^#/;
+
+    if (/^[ \t]*(error_table|et)[ \t]+([a-zA-Z][a-zA-Z0-9_]+) *(-?[0-9]*)/) {
+	$table_name = $2;
+	if ($3) {
+	    $table_base = $3;
+	}
+	else {
+	    $table_base = &table_base($table_name);
+	}
+	$table_item_count = 0;
+
+	print C "#include \"prerrorplugin.h\"\n";
+	print C "static const struct PRErrorMessage text[] = {\n";
+    }
+    elsif (/^[ \t]*(error_code|ec)[ \t]+([A-Z_0-9]+),[ \t]*$/) {
+	$skipone = 1;
+	$macro = $2;
+    }
+    elsif (/^[ \t]*(error_code|ec)[ \t]+([A-Z_0-9]+),[ \t]*"(.*)"[ \t]*$/) {
+	&code($2, $3);
+    }
+    elsif ($skipone && /^[ \t]*"(.*)"[ \t]*$/) {
+	&code($macro, $1);
+    }
+}
+
+print H "extern void pr_init_error_table_", $table_name, "(void);\n";
+printf H "#define ERROR_TABLE_BASE_%s (%dL)\n", $table_name, $table_base;
+
+print C "\t{0, 0}\n";
+print C "};\n\n";
+printf C "static const struct PRErrorTable et = { text, \"%s\", %dL, %d };\n",
+    $base, $table_base, $table_item_count;
+print C "\n";
+print C "void pr_init_error_table_", $table_name, "() {\n";
+print C "    PR_ErrorInstallTable(&et);\n";
+print C "}\n";
+
+0;
new file mode 100644
--- /dev/null
+++ b/pr/src/misc/prerr.c
@@ -0,0 +1,90 @@
+/*
+ *
+ * prerr.c
+ * This file is automatically generated; please do not edit it.
+ */
+#include "prerrorplugin.h"
+static const struct PRErrorMessage text[] = {
+	{"PR_OUT_OF_MEMORY_ERROR",    "Memory allocation attempt failed"},
+	{"PR_BAD_DESCRIPTOR_ERROR",    "Invalid file descriptor"},
+	{"PR_WOULD_BLOCK_ERROR",    "The operation would have blocked"},
+	{"PR_ACCESS_FAULT_ERROR",    "Invalid memory address argument"},
+	{"PR_INVALID_METHOD_ERROR",    "Invalid function for file type"},
+	{"PR_ILLEGAL_ACCESS_ERROR",    "Invalid memory address argument"},
+	{"PR_UNKNOWN_ERROR",    "Some unknown error has occurred"},
+	{"PR_PENDING_INTERRUPT_ERROR",    "Operation interrupted by another thread"},
+	{"PR_NOT_IMPLEMENTED_ERROR",    "function not implemented"},
+	{"PR_IO_ERROR",    "I/O function error"},
+	{"PR_IO_TIMEOUT_ERROR",    "I/O operation timed out"},
+	{"PR_IO_PENDING_ERROR",    "I/O operation on busy file descriptor"},
+	{"PR_DIRECTORY_OPEN_ERROR",    "The directory could not be opened"},
+	{"PR_INVALID_ARGUMENT_ERROR",    "Invalid function argument"},
+	{"PR_ADDRESS_NOT_AVAILABLE_ERROR",    "Network address not available (in use?)"},
+	{"PR_ADDRESS_NOT_SUPPORTED_ERROR",    "Network address type not supported"},
+	{"PR_IS_CONNECTED_ERROR",    "Already connected"},
+	{"PR_BAD_ADDRESS_ERROR",    "Network address is invalid"},
+	{"PR_ADDRESS_IN_USE_ERROR",    "Local Network address is in use"},
+	{"PR_CONNECT_REFUSED_ERROR",    "Connection refused by peer"},
+	{"PR_NETWORK_UNREACHABLE_ERROR",    "Network address is presently unreachable"},
+	{"PR_CONNECT_TIMEOUT_ERROR",    "Connection attempt timed out"},
+	{"PR_NOT_CONNECTED_ERROR",    "Network file descriptor is not connected"},
+	{"PR_LOAD_LIBRARY_ERROR",    "Failure to load dynamic library"},
+	{"PR_UNLOAD_LIBRARY_ERROR",    "Failure to unload dynamic library"},
+	{"PR_FIND_SYMBOL_ERROR",    "Symbol not found in any of the loaded dynamic libraries"},
+	{"PR_INSUFFICIENT_RESOURCES_ERROR",    "Insufficient system resources"},
+	{"PR_DIRECTORY_LOOKUP_ERROR",    "A directory lookup on a network address has failed"},
+	{"PR_TPD_RANGE_ERROR",    "Attempt to access a TPD key that is out of range"},
+	{"PR_PROC_DESC_TABLE_FULL_ERROR",    "Process open FD table is full"},
+	{"PR_SYS_DESC_TABLE_FULL_ERROR",    "System open FD table is full"},
+	{"PR_NOT_SOCKET_ERROR",    "Network operation attempted on non-network file descriptor"},
+	{"PR_NOT_TCP_SOCKET_ERROR",    "TCP-specific function attempted on a non-TCP file descriptor"},
+	{"PR_SOCKET_ADDRESS_IS_BOUND_ERROR",    "TCP file descriptor is already bound"},
+	{"PR_NO_ACCESS_RIGHTS_ERROR",    "Access Denied"},
+	{"PR_OPERATION_NOT_SUPPORTED_ERROR",    "The requested operation is not supported by the platform"},
+	{"PR_PROTOCOL_NOT_SUPPORTED_ERROR",    "The host operating system does not support the protocol requested"},
+	{"PR_REMOTE_FILE_ERROR",    "Access to the remote file has been severed"},
+	{"PR_BUFFER_OVERFLOW_ERROR",    "The value requested is too large to be stored in the data buffer provided"},
+	{"PR_CONNECT_RESET_ERROR",    "TCP connection reset by peer"},
+	{"PR_RANGE_ERROR",    "Unused"},
+	{"PR_DEADLOCK_ERROR",    "The operation would have deadlocked"},
+	{"PR_FILE_IS_LOCKED_ERROR",    "The file is already locked"},
+	{"PR_FILE_TOO_BIG_ERROR",    "Write would result in file larger than the system allows"},
+	{"PR_NO_DEVICE_SPACE_ERROR",    "The device for storing the file is full"},
+	{"PR_PIPE_ERROR",    "Unused"},
+	{"PR_NO_SEEK_DEVICE_ERROR",    "Unused"},
+	{"PR_IS_DIRECTORY_ERROR",    "Cannot perform a normal file operation on a directory"},
+	{"PR_LOOP_ERROR",    "Symbolic link loop"},
+	{"PR_NAME_TOO_LONG_ERROR",    "File name is too long"},
+	{"PR_FILE_NOT_FOUND_ERROR",    "File not found"},
+	{"PR_NOT_DIRECTORY_ERROR",    "Cannot perform directory operation on a normal file"},
+	{"PR_READ_ONLY_FILESYSTEM_ERROR",    "Cannot write to a read-only file system"},
+	{"PR_DIRECTORY_NOT_EMPTY_ERROR",    "Cannot delete a directory that is not empty"},
+	{"PR_FILESYSTEM_MOUNTED_ERROR",    "Cannot delete or rename a file object while the file system is busy"},
+	{"PR_NOT_SAME_DEVICE_ERROR",    "Cannot rename a file to a file system on another device"},
+	{"PR_DIRECTORY_CORRUPTED_ERROR",    "The directory object in the file system is corrupted"},
+	{"PR_FILE_EXISTS_ERROR",    "Cannot create or rename a filename that already exists"},
+	{"PR_MAX_DIRECTORY_ENTRIES_ERROR",    "Directory is full.  No additional filenames may be added"},
+	{"PR_INVALID_DEVICE_STATE_ERROR",    "The required device was in an invalid state"},
+	{"PR_DEVICE_IS_LOCKED_ERROR",    "The device is locked"},
+	{"PR_NO_MORE_FILES_ERROR",    "No more entries in the directory"},
+	{"PR_END_OF_FILE_ERROR",    "Encountered end of file"},
+	{"PR_FILE_SEEK_ERROR",    "Seek error"},
+	{"PR_FILE_IS_BUSY_ERROR",    "The file is busy"},
+	{"PR_RESERVED_ERROR",    "Reserved Error Code"},
+	{"PR_IN_PROGRESS_ERROR",    "Operation is still in progress (probably a non-blocking connect)"},
+	{"PR_ALREADY_INITIATED_ERROR",    "Operation has already been initiated (probably a non-blocking connect)"},
+	{"PR_GROUP_EMPTY_ERROR",    "The wait group is empty"},
+	{"PR_INVALID_STATE_ERROR",    "Object state improper for request"},
+	{"PR_NETWORK_DOWN_ERROR",    "Network is down"},
+	{"PR_SOCKET_SHUTDOWN_ERROR",    "Socket shutdown"},
+	{"PR_CONNECT_ABORTED_ERROR",    "Connection aborted"},
+	{"PR_HOST_UNREACHABLE_ERROR",    "Host is unreachable"},
+	{"PR_MAX_ERROR",    "Placeholder for the end of the list"},
+	{0, 0}
+};
+
+static const struct PRErrorTable et = { text, "prerr", -6000L, 75 };
+
+void pr_init_error_table_nspr() {
+    PR_ErrorInstallTable(&et);
+}
new file mode 100644
--- /dev/null
+++ b/pr/src/misc/prerr.et
@@ -0,0 +1,116 @@
+# The contents of this file are subject to the Netscape Public License
+# Version 1.0 (the "NPL"); you may not use this file except in
+# compliance with the NPL.  You may obtain a copy of the NPL at
+# http://www.mozilla.org/NPL/
+#
+# Software distributed under the NPL is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+# for the specific language governing rights and limitations under the
+# NPL.
+#
+# The Initial Developer of this code under the NPL is Netscape
+# Communications Corporation.  Portions created by Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation.  All Rights
+# Reserved.
+
+et nspr -6000
+
+ec PR_OUT_OF_MEMORY_ERROR,      "Memory allocation attempt failed"
+ec PR_BAD_DESCRIPTOR_ERROR,     "Invalid file descriptor"
+ec PR_WOULD_BLOCK_ERROR,        "The operation would have blocked"
+ec PR_ACCESS_FAULT_ERROR,       "Invalid memory address argument"
+ec PR_INVALID_METHOD_ERROR,     "Invalid function for file type"
+ec PR_ILLEGAL_ACCESS_ERROR,     "Invalid memory address argument"
+ec PR_UNKNOWN_ERROR,            "Some unknown error has occurred"
+ec PR_PENDING_INTERRUPT_ERROR,"Operation interrupted by another thread"
+ec PR_NOT_IMPLEMENTED_ERROR,    "function not implemented"
+ec PR_IO_ERROR,                 "I/O function error"
+ec PR_IO_TIMEOUT_ERROR,         "I/O operation timed out"
+ec PR_IO_PENDING_ERROR,         "I/O operation on busy file descriptor"
+ec PR_DIRECTORY_OPEN_ERROR,     "The directory could not be opened"
+ec PR_INVALID_ARGUMENT_ERROR, "Invalid function argument"
+ec PR_ADDRESS_NOT_AVAILABLE_ERROR, "Network address not available (in use?)"
+ec PR_ADDRESS_NOT_SUPPORTED_ERROR, "Network address type not supported"
+ec PR_IS_CONNECTED_ERROR,       "Already connected"
+ec PR_BAD_ADDRESS_ERROR,        "Network address is invalid"
+ec PR_ADDRESS_IN_USE_ERROR,     "Local Network address is in use"
+ec PR_CONNECT_REFUSED_ERROR,    "Connection refused by peer"
+ec PR_NETWORK_UNREACHABLE_ERROR, "Network address is presently unreachable"
+ec PR_CONNECT_TIMEOUT_ERROR,    "Connection attempt timed out"
+ec PR_NOT_CONNECTED_ERROR,      "Network file descriptor is not connected"
+ec PR_LOAD_LIBRARY_ERROR,       "Failure to load dynamic library"
+ec PR_UNLOAD_LIBRARY_ERROR,     "Failure to unload dynamic library"
+ec PR_FIND_SYMBOL_ERROR,
+"Symbol not found in any of the loaded dynamic libraries"
+ec PR_INSUFFICIENT_RESOURCES_ERROR, "Insufficient system resources"
+ec PR_DIRECTORY_LOOKUP_ERROR,
+"A directory lookup on a network address has failed"
+ec PR_TPD_RANGE_ERROR,
+"Attempt to access a TPD key that is out of range"
+ec PR_PROC_DESC_TABLE_FULL_ERROR, "Process open FD table is full"
+ec PR_SYS_DESC_TABLE_FULL_ERROR, "System open FD table is full"
+ec PR_NOT_SOCKET_ERROR,
+"Network operation attempted on non-network file descriptor"
+ec PR_NOT_TCP_SOCKET_ERROR,
+"TCP-specific function attempted on a non-TCP file descriptor"
+ec PR_SOCKET_ADDRESS_IS_BOUND_ERROR, "TCP file descriptor is already bound"
+ec PR_NO_ACCESS_RIGHTS_ERROR, "Access Denied"
+ec PR_OPERATION_NOT_SUPPORTED_ERROR,
+"The requested operation is not supported by the platform"
+ec PR_PROTOCOL_NOT_SUPPORTED_ERROR,
+"The host operating system does not support the protocol requested"
+ec PR_REMOTE_FILE_ERROR,        "Access to the remote file has been severed"
+ec PR_BUFFER_OVERFLOW_ERROR,
+"The value requested is too large to be stored in the data buffer provided"
+ec PR_CONNECT_RESET_ERROR,      "TCP connection reset by peer"
+ec PR_RANGE_ERROR,              "Unused"
+ec PR_DEADLOCK_ERROR,   "The operation would have deadlocked"
+ec PR_FILE_IS_LOCKED_ERROR,     "The file is already locked"
+ec PR_FILE_TOO_BIG_ERROR,
+"Write would result in file larger than the system allows"
+ec PR_NO_DEVICE_SPACE_ERROR,    "The device for storing the file is full"
+ec PR_PIPE_ERROR,               "Unused"
+ec PR_NO_SEEK_DEVICE_ERROR,     "Unused"
+ec PR_IS_DIRECTORY_ERROR,
+"Cannot perform a normal file operation on a directory"
+ec PR_LOOP_ERROR,               "Symbolic link loop"
+ec PR_NAME_TOO_LONG_ERROR,      "File name is too long"
+ec PR_FILE_NOT_FOUND_ERROR,     "File not found"
+ec PR_NOT_DIRECTORY_ERROR,
+"Cannot perform directory operation on a normal file"
+ec PR_READ_ONLY_FILESYSTEM_ERROR,
+"Cannot write to a read-only file system"
+ec PR_DIRECTORY_NOT_EMPTY_ERROR,
+"Cannot delete a directory that is not empty"
+ec PR_FILESYSTEM_MOUNTED_ERROR,
+"Cannot delete or rename a file object while the file system is busy"
+ec PR_NOT_SAME_DEVICE_ERROR,
+"Cannot rename a file to a file system on another device"
+ec PR_DIRECTORY_CORRUPTED_ERROR,
+"The directory object in the file system is corrupted"
+ec PR_FILE_EXISTS_ERROR,
+"Cannot create or rename a filename that already exists"
+ec PR_MAX_DIRECTORY_ENTRIES_ERROR,
+"Directory is full.  No additional filenames may be added"
+ec PR_INVALID_DEVICE_STATE_ERROR,
+"The required device was in an invalid state"
+ec PR_DEVICE_IS_LOCKED_ERROR, "The device is locked"
+ec PR_NO_MORE_FILES_ERROR,      "No more entries in the directory"
+ec PR_END_OF_FILE_ERROR,        "Encountered end of file"
+ec PR_FILE_SEEK_ERROR,  "Seek error"
+ec PR_FILE_IS_BUSY_ERROR,       "The file is busy"
+ec PR_RESERVED_ERROR,       "Reserved Error Code"
+ec PR_IN_PROGRESS_ERROR,
+"Operation is still in progress (probably a non-blocking connect)"
+ec PR_ALREADY_INITIATED_ERROR,
+"Operation has already been initiated (probably a non-blocking connect)"
+ec PR_GROUP_EMPTY_ERROR,        "The wait group is empty"
+ec PR_INVALID_STATE_ERROR,      "Object state improper for request"
+ec PR_NETWORK_DOWN_ERROR,       "Network is down"
+ec PR_SOCKET_SHUTDOWN_ERROR,    "Socket shutdown"
+ec PR_CONNECT_ABORTED_ERROR,    "Connection aborted"
+ec PR_HOST_UNREACHABLE_ERROR,   "Host is unreachable"
+
+ec PR_MAX_ERROR,                "Placeholder for the end of the list"
+
+end
new file mode 100644
--- /dev/null
+++ b/pr/src/misc/prerrortable.c
@@ -0,0 +1,201 @@
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL.  You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ * 
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ * 
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation.  Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
+ * Reserved.
+ */
+/*
+
+Copyright 1987, 1988 by the Student Information Processing Board
+	of the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this software
+and its documentation for any purpose and without fee is
+hereby granted, provided that the above copyright notice
+appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation,
+and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+M.I.T. and the M.I.T. S.I.P.B. make no representations about
+the suitability of this software for any purpose.  It is
+provided "as is" without express or implied warranty.
+
+*/
+
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include "prmem.h"
+#include "prerror.h"
+#include "prerrorplugin.h"
+
+#define	ERRCODE_RANGE	8	/* # of bits to shift table number */
+#define	BITS_PER_CHAR	6	/* # bits to shift per character in name */
+
+#ifdef NEED_SYS_ERRLIST
+extern char const * const sys_errlist[];
+extern const int sys_nerr;
+#endif
+
+/* List of error tables */
+struct PRErrorTableList {
+    struct PRErrorTableList *next;
+    const struct PRErrorTable *table;
+    struct PRErrorPluginTableRock *table_rock;
+};
+static struct PRErrorTableList * Table_List = (struct PRErrorTableList *) NULL;
+
+/* Supported languages */
+static const char * default_languages[] = { "i-default", "en", 0 };
+static const char * const * plugin_languages = default_languages;
+
+/* Plugin info */
+static struct PRErrorPluginRock *plugin_rock = 0;
+static PRErrorPluginLookupFn *plugin_lookup = 0;
+static PRErrorPluginNewtableFn *plugin_newtable = 0;
+
+
+static const char char_set[] =
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
+
+static const char *
+error_table_name (PRErrorCode num)
+{
+    static char buf[6];	/* only used if internal code problems exist */
+
+    long ch;
+    int i;
+    char *p;
+
+    /* num = aa aaa abb bbb bcc ccc cdd ddd d?? ??? ??? */
+    p = buf;
+    num >>= ERRCODE_RANGE;
+    /* num = ?? ??? ??? aaa aaa bbb bbb ccc ccc ddd ddd */
+    num &= 077777777;
+    /* num = 00 000 000 aaa aaa bbb bbb ccc ccc ddd ddd */
+    for (i = 4; i >= 0; i--) {
+	ch = (num >> BITS_PER_CHAR * i) & ((1 << BITS_PER_CHAR) - 1);
+	if (ch != 0)
+	    *p++ = char_set[ch-1];
+    }
+    *p = '\0';
+    return(buf);
+}
+
+
+
+PR_IMPLEMENT(const char *)
+PR_ErrorToString(PRErrorCode code, PRLanguageCode language)
+{
+    /* static buffer only used if code is using inconsistent error message
+     * numbers, so just ignore the possible thread contention
+     */
+    static char buffer[25];
+
+    const char *msg;
+    int offset;
+    PRErrorCode table_num;
+    struct PRErrorTableList *et;
+    int started = 0;
+    char *cp;
+
+    for (et = Table_List; et; et = et->next) {
+	if (et->table->base <= code &&
+	    et->table->base + et->table->n_msgs > code) {
+	    /* This is the right table */
+	    if (plugin_lookup) {
+		msg = plugin_lookup(code, language, et->table,
+		    plugin_rock, et->table_rock);
+		if (msg) return msg;
+	    }
+    
+	    return(et->table->msgs[code - et->table->base].en_text);
+	}
+    }
+
+    if (code >= 0 && code < 256) {
+	return strerror(code);
+    }
+
+    offset = (int) (code & ((1<<ERRCODE_RANGE)-1));
+    table_num = code - offset;
+    strcpy (buffer, "Unknown code ");
+    if (table_num) {
+	strcat(buffer, error_table_name (table_num));
+	strcat(buffer, " ");
+    }
+    for (cp = buffer; *cp; cp++)
+	;
+    if (offset >= 100) {
+	*cp++ = (char)('0' + offset / 100);
+	offset %= 100;
+	started++;
+    }
+    if (started || offset >= 10) {
+	*cp++ = (char)('0' + offset / 10);
+	offset %= 10;
+    }
+    *cp++ = (char)('0' + offset);
+    *cp = '\0';
+    return(buffer);
+}
+
+PR_IMPLEMENT(const char * const *)
+PR_ErrorLanguages(void)
+{
+    return plugin_languages;
+}
+
+PR_IMPLEMENT(PRErrorCode)
+PR_ErrorInstallTable(const struct PRErrorTable *table)
+{
+    struct PRErrorTableList * new_et;
+
+    new_et = (struct PRErrorTableList *)
+					PR_Malloc(sizeof(struct PRErrorTableList));
+    if (!new_et)
+	return errno;	/* oops */
+    new_et->table = table;
+    if (plugin_newtable) {
+	new_et->table_rock = plugin_newtable(table, plugin_rock);
+    } else {
+	new_et->table_rock = 0;
+    }
+    new_et->next = Table_List;
+    Table_List = new_et;
+    return 0;
+}
+
+PR_IMPLEMENT(void)
+PR_ErrorInstallPlugin(const char * const * languages,
+		       PRErrorPluginLookupFn *lookup, 
+		       PRErrorPluginNewtableFn *newtable,
+		       struct PRErrorPluginRock *rock)
+{
+    struct PRErrorTableList *et;
+
+    assert(strcmp(languages[0], "i-default") == 0);
+    assert(strcmp(languages[1], "en") == 0);
+    
+    plugin_languages = languages;
+    plugin_lookup = lookup;
+    plugin_newtable = newtable;
+    plugin_rock = rock;
+
+    if (plugin_newtable) {
+	for (et = Table_List; et; et = et->next) {
+	    et->table_rock = plugin_newtable(et->table, plugin_rock);
+	}
+    }
+}
--- a/pr/src/misc/prinit.c
+++ b/pr/src/misc/prinit.c
@@ -145,16 +145,18 @@ static void _PR_InitStuff(void)
 #ifdef PR_LOGGING
     _PR_InitLog();
 #endif
     _PR_InitLinker();
     _PR_InitCallOnce();
     _PR_InitDtoa();
     _PR_InitMW();
 
+    pr_init_error_table_nspr();
+
     _PR_MD_FINAL_INIT();
 }
 
 void _PR_ImplicitInitialization()
 {
 	_PR_InitStuff();
 
     /* Enable interrupts */
--- a/pr/src/pthreads/ptthread.c
+++ b/pr/src/pthreads/ptthread.c
@@ -337,17 +337,22 @@ static PRThread* _PR_CreateThread(
         /* make the thread counted to the rest of the runtime */
         PR_Lock(pt_book.ml);
         if (PR_SYSTEM_THREAD == type)
             pt_book.system += 1;
         else pt_book.user += 1;
         PR_Unlock(pt_book.ml);
 
         if (thred->state & PT_THREAD_BOUND) {
+			/*
+			 * should a Posix feature test be used here?
+			 */
+#ifdef PTHREAD_SCOPE_SYSTEM
     		rv = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
+#endif
 		}
         /*
          * We pass a pointer to a local copy (instead of thred->id)
          * to pthread_create() because who knows what wacky things
          * pthread_create() may be doing to its argument.
          */
         rv = PTHREAD_CREATE(&id, tattr, _pt_root, thred);
 
--- a/pr/src/threads/prrwlock.c
+++ b/pr/src/threads/prrwlock.c
@@ -12,17 +12,16 @@
  * 
  * The Initial Developer of this code under the NPL is Netscape
  * Communications Corporation.  Portions created by Netscape are
  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  * Reserved.
  */
 
 #include "nspr.h"
-#include "prrwlock.h"
 
 #include <string.h>
 
 /*
  * Reader-writer lock
  */
 struct PRRWLock {
     PRLock			*rw_lock;
@@ -41,19 +40,19 @@ struct PRRWLock {
 #ifdef DEBUG
 #define _PR_RWLOCK_RANK_ORDER_DEBUG	/* enable deadlock detection using
 									   rank-order for locks
 									*/
 #endif
 
 #ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
 
-static PRUintn	ps_thread_rwlock_initialized;
-static PRUintn	ps_thread_rwlock;				/* TPD key for lock stack */
-static PRUintn	ps_thread_rwlock_alloc_failed;
+static PRUintn	pr_thread_rwlock_initialized;
+static PRUintn	pr_thread_rwlock;				/* TPD key for lock stack */
+static PRUintn	pr_thread_rwlock_alloc_failed;
 
 #define	_PR_RWLOCK_RANK_ORDER_LIMIT	10
 
 typedef struct thread_rwlock_stack {
 	PRInt32		trs_index;									/* top of stack */
 	PRRWLock	*trs_stack[_PR_RWLOCK_RANK_ORDER_LIMIT];	/* stack of lock
 														 	   pointers */
 
@@ -286,113 +285,113 @@ PRThread *me = PR_GetCurrentThread();
 
 /*
  * _PR_SET_THREAD_RWLOCK_RANK
  *		Set a thread's lock rank, which is the highest of the ranks of all
  *		the locks held by the thread. Pointers to the locks are added to a
  *		per-thread list, which is anchored off a thread-private data key.
  */
 
-void
+static void
 _PR_SET_THREAD_RWLOCK_RANK(PRThread *me, PRRWLock *rwlock)
 {
 thread_rwlock_stack *lock_stack;
 PRStatus rv;
 
 	/*
 	 * allocated thread-private-data for rwlock list, if not already allocated
 	 */
-	if (!ps_thread_rwlock_initialized) {
+	if (!pr_thread_rwlock_initialized) {
 		/*
 		 * allocate tpd, only if not failed already
 		 */
-		if (!ps_thread_rwlock_alloc_failed) {
-			if (PR_NewThreadPrivateIndex(&ps_thread_rwlock,
+		if (!pr_thread_rwlock_alloc_failed) {
+			if (PR_NewThreadPrivateIndex(&pr_thread_rwlock,
 										_PR_RELEASE_LOCK_STACK)
 												== PR_FAILURE) {
-				ps_thread_rwlock_alloc_failed = 1;
+				pr_thread_rwlock_alloc_failed = 1;
 				return;
 			}
 		} else
 			return;
 	}
 	/*
 	 * allocate a lock stack
 	 */
-	if ((lock_stack = PR_GetThreadPrivate(ps_thread_rwlock)) == NULL) {
+	if ((lock_stack = PR_GetThreadPrivate(pr_thread_rwlock)) == NULL) {
 		lock_stack = (thread_rwlock_stack *)
 						PR_CALLOC(1 * sizeof(thread_rwlock_stack));
 		if (lock_stack) {
-			rv = PR_SetThreadPrivate(ps_thread_rwlock, lock_stack);
+			rv = PR_SetThreadPrivate(pr_thread_rwlock, lock_stack);
 			if (rv == PR_FAILURE) {
 				PR_DELETE(lock_stack);
-				ps_thread_rwlock_alloc_failed = 1;
+				pr_thread_rwlock_alloc_failed = 1;
 				return;
 			}
 		} else {
-			ps_thread_rwlock_alloc_failed = 1;
+			pr_thread_rwlock_alloc_failed = 1;
 			return;
 		}
 	}
 	/*
 	 * add rwlock to lock stack, if limit is not exceeded
 	 */
 	if (lock_stack) {
 		if (lock_stack->trs_index < _PR_RWLOCK_RANK_ORDER_LIMIT)
 			lock_stack->trs_stack[lock_stack->trs_index++] = rwlock;	
 	}
-	ps_thread_rwlock_initialized = 1;
+	pr_thread_rwlock_initialized = 1;
 }
 
-void
+static void
 _PR_RELEASE_LOCK_STACK(void *lock_stack)
 {
 	PR_ASSERT(lock_stack);
 	PR_DELETE(lock_stack);
 }
 
 /*
  * _PR_GET_THREAD_RWLOCK_RANK
  *
  *		return thread's lock rank. If thread-private-data for the lock
  *		stack is not allocated, return PR_RWLOCK_RANK_NONE.
  */
 	
-PRUint32
+static PRUint32
 _PR_GET_THREAD_RWLOCK_RANK(PRThread *me)
 {
 	thread_rwlock_stack *lock_stack;
 
-	if (ps_thread_rwlock_initialized) {
-		if ((lock_stack = PR_GetThreadPrivate(ps_thread_rwlock)) == NULL)
+	if (pr_thread_rwlock_initialized) {
+		if ((lock_stack = PR_GetThreadPrivate(pr_thread_rwlock)) == NULL)
 			return (PR_RWLOCK_RANK_NONE);
 		else
 			return(lock_stack->trs_stack[lock_stack->trs_index - 1]->rw_rank);
 
 	} else
 			return (PR_RWLOCK_RANK_NONE);
 }
 
 /*
  * _PR_UNSET_THREAD_RWLOCK_RANK
  *
  *		remove the rwlock from the lock stack. Since locks may not be
  *		unlocked in a FIFO order, the entire lock stack is searched.
  */
 	
-void
+static void
 _PR_UNSET_THREAD_RWLOCK_RANK(PRThread *me, PRRWLock *rwlock)
 {
 	thread_rwlock_stack *lock_stack;
 	int new_index = 0, index, done = 0;
 
-	if (!ps_thread_rwlock_initialized)
+	if (!pr_thread_rwlock_initialized)
 		return;
 
-	lock_stack = PR_GetThreadPrivate(ps_thread_rwlock);
+	lock_stack = PR_GetThreadPrivate(pr_thread_rwlock);
 
 	PR_ASSERT(lock_stack != NULL);
 
 	index = lock_stack->trs_index - 1;
 	while (index-- >= 0) {
 		if ((lock_stack->trs_stack[index] == rwlock) && !done)  {
 			/*
 			 * reset the slot for rwlock
--- a/pr/tests/Makefile
+++ b/pr/tests/Makefile
@@ -33,16 +33,17 @@ DIRS = dll
 endif
 
 ifeq ($(OS_TARGET),OS2)
 OS_CFLAGS = $(OS_EXE_CFLAGS)
 endif
 
 CSRCS =             \
 	accept.c		\
+	acceptread.c	\
 	alarm.c			\
 	atomic.c		\
 	attach.c		\
 	bigfile.c		\
 	cleanup.c		\
 	cltsrv.c		\
 	concur.c	    \
 	cvar.c			\
@@ -94,20 +95,19 @@ CSRCS =             \
 	poll_nm.c		\
 	poll_to.c		\
 	pollable.c		\
 	prftest.c		\
 	prftest1.c		\
 	prftest2.c		\
 	priotest.c		\
 	provider.c		\
+	prpoll.c		\
 	ranfile.c       \
 	rwlocktest.c    \
-	prpoll.c		\
-	ranfile.c       \
 	sel_spd.c  		\
 	selct_er.c	    \
 	selct_nm.c	    \
 	selct_to.c	    \
 	select2.c  		\
 	sem.c 	  		\
 	server_test.c	\
 	servr_kk.c		\
--- a/pr/tests/strod.c
+++ b/pr/tests/strod.c
@@ -67,17 +67,17 @@ static PRIntn PR_CALLBACK RealMain(PRInt
     PR_fprintf(err, "\tNumber to translate %s\n", number);
     PR_fprintf(err, "\tLoops to run test: %d\n", loops);
 
     while (loops--)
     {
         answer = PR_strtod(number, NULL);
         PR_fprintf(err, "Translation = %20.0f\n", answer);
     }
-    return 2;
+    return 0;
 }
 
 
 
 PRIntn main(PRIntn argc, char *argv[])
 {
     PRIntn rv;