mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-05-12 02:17:17 +00:00
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3693 d0543943-73ff-0310-b7d9-9358b9ac24b2
241 lines
7.0 KiB
C
241 lines
7.0 KiB
C
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is the Netscape Portable Runtime (NSPR).
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 1998-2000
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
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>
|
|
#ifdef SUNOS4
|
|
#include "md/sunos4.h" /* for strerror */
|
|
#endif
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include "prmem.h"
|
|
#include "prerror.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 PRErrorCallbackTablePrivate *table_private;
|
|
};
|
|
static struct PRErrorTableList * Table_List = (struct PRErrorTableList *) NULL;
|
|
|
|
/* Supported languages */
|
|
static const char * default_languages[] = { "i-default", "en", 0 };
|
|
static const char * const * callback_languages = default_languages;
|
|
|
|
/* Callback info */
|
|
static struct PRErrorCallbackPrivate *callback_private = 0;
|
|
static PRErrorCallbackLookupFn *callback_lookup = 0;
|
|
static PRErrorCallbackNewTableFn *callback_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 (callback_lookup) {
|
|
msg = callback_lookup(code, language, et->table,
|
|
callback_private, et->table_private);
|
|
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 *)
|
|
PR_ErrorToName(PRErrorCode code)
|
|
{
|
|
struct PRErrorTableList *et;
|
|
|
|
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 */
|
|
return(et->table->msgs[code - et->table->base].name);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
PR_IMPLEMENT(const char * const *)
|
|
PR_ErrorLanguages(void)
|
|
{
|
|
return callback_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 (callback_newtable) {
|
|
new_et->table_private = callback_newtable(table, callback_private);
|
|
} else {
|
|
new_et->table_private = 0;
|
|
}
|
|
new_et->next = Table_List;
|
|
Table_List = new_et;
|
|
return 0;
|
|
}
|
|
|
|
PR_IMPLEMENT(void)
|
|
PR_ErrorInstallCallback(const char * const * languages,
|
|
PRErrorCallbackLookupFn *lookup,
|
|
PRErrorCallbackNewTableFn *newtable,
|
|
struct PRErrorCallbackPrivate *cb_private)
|
|
{
|
|
struct PRErrorTableList *et;
|
|
|
|
assert(strcmp(languages[0], "i-default") == 0);
|
|
assert(strcmp(languages[1], "en") == 0);
|
|
|
|
callback_languages = languages;
|
|
callback_lookup = lookup;
|
|
callback_newtable = newtable;
|
|
callback_private = cb_private;
|
|
|
|
if (callback_newtable) {
|
|
for (et = Table_List; et; et = et->next) {
|
|
et->table_private = callback_newtable(et->table, callback_private);
|
|
}
|
|
}
|
|
}
|