andre@0: /* This Source Code Form is subject to the terms of the Mozilla Public andre@0: * License, v. 2.0. If a copy of the MPL was not distributed with this andre@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ andre@0: andre@0: andre@0: andre@0: andre@0: /* andre@0: andre@0: Copyright 1987, 1988 by the Student Information Processing Board andre@0: of the Massachusetts Institute of Technology andre@0: andre@0: Permission to use, copy, modify, and distribute this software andre@0: and its documentation for any purpose and without fee is andre@0: hereby granted, provided that the above copyright notice andre@0: appear in all copies and that both that copyright notice and andre@0: this permission notice appear in supporting documentation, andre@0: and that the names of M.I.T. and the M.I.T. S.I.P.B. not be andre@0: used in advertising or publicity pertaining to distribution andre@0: of the software without specific, written prior permission. andre@0: M.I.T. and the M.I.T. S.I.P.B. make no representations about andre@0: the suitability of this software for any purpose. It is andre@0: provided "as is" without express or implied warranty. andre@0: andre@0: */ andre@0: andre@0: #include andre@0: #include andre@0: #include andre@0: #include "prmem.h" andre@0: #include "prerror.h" andre@0: andre@0: #define ERRCODE_RANGE 8 /* # of bits to shift table number */ andre@0: #define BITS_PER_CHAR 6 /* # bits to shift per character in name */ andre@0: andre@0: #ifdef NEED_SYS_ERRLIST andre@0: extern char const * const sys_errlist[]; andre@0: extern const int sys_nerr; andre@0: #endif andre@0: andre@0: /* List of error tables */ andre@0: struct PRErrorTableList { andre@0: struct PRErrorTableList *next; andre@0: const struct PRErrorTable *table; andre@0: struct PRErrorCallbackTablePrivate *table_private; andre@0: }; andre@0: static struct PRErrorTableList * Table_List = (struct PRErrorTableList *) NULL; andre@0: andre@0: /* Supported languages */ andre@0: static const char * default_languages[] = { "i-default", "en", 0 }; andre@0: static const char * const * callback_languages = default_languages; andre@0: andre@0: /* Callback info */ andre@0: static struct PRErrorCallbackPrivate *callback_private = 0; andre@0: static PRErrorCallbackLookupFn *callback_lookup = 0; andre@0: static PRErrorCallbackNewTableFn *callback_newtable = 0; andre@0: andre@0: andre@0: static const char char_set[] = andre@0: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"; andre@0: andre@0: static const char * andre@0: error_table_name (PRErrorCode num) andre@0: { andre@0: static char buf[6]; /* only used if internal code problems exist */ andre@0: andre@0: long ch; andre@0: int i; andre@0: char *p; andre@0: andre@0: /* num = aa aaa abb bbb bcc ccc cdd ddd d?? ??? ??? */ andre@0: p = buf; andre@0: num >>= ERRCODE_RANGE; andre@0: /* num = ?? ??? ??? aaa aaa bbb bbb ccc ccc ddd ddd */ andre@0: num &= 077777777; andre@0: /* num = 00 000 000 aaa aaa bbb bbb ccc ccc ddd ddd */ andre@0: for (i = 4; i >= 0; i--) { andre@0: ch = (num >> BITS_PER_CHAR * i) & ((1 << BITS_PER_CHAR) - 1); andre@0: if (ch != 0) andre@0: *p++ = char_set[ch-1]; andre@0: } andre@0: *p = '\0'; andre@0: return(buf); andre@0: } andre@0: andre@0: PR_IMPLEMENT(const char *) andre@0: PR_ErrorToString(PRErrorCode code, PRLanguageCode language) andre@0: { andre@0: /* static buffer only used if code is using inconsistent error message andre@0: * numbers, so just ignore the possible thread contention andre@0: */ andre@0: static char buffer[25]; andre@0: andre@0: const char *msg; andre@0: int offset; andre@0: PRErrorCode table_num; andre@0: struct PRErrorTableList *et; andre@0: int started = 0; andre@0: char *cp; andre@0: andre@0: for (et = Table_List; et; et = et->next) { andre@0: if (et->table->base <= code && andre@0: et->table->base + et->table->n_msgs > code) { andre@0: /* This is the right table */ andre@0: if (callback_lookup) { andre@0: msg = callback_lookup(code, language, et->table, andre@0: callback_private, et->table_private); andre@0: if (msg) return msg; andre@0: } andre@0: andre@0: return(et->table->msgs[code - et->table->base].en_text); andre@0: } andre@0: } andre@0: andre@0: if (code >= 0 && code < 256) { andre@0: return strerror(code); andre@0: } andre@0: andre@0: offset = (int) (code & ((1<= 100) { andre@0: *cp++ = (char)('0' + offset / 100); andre@0: offset %= 100; andre@0: started++; andre@0: } andre@0: if (started || offset >= 10) { andre@0: *cp++ = (char)('0' + offset / 10); andre@0: offset %= 10; andre@0: } andre@0: *cp++ = (char)('0' + offset); andre@0: *cp = '\0'; andre@0: return(buffer); andre@0: } andre@0: andre@0: PR_IMPLEMENT(const char *) andre@0: PR_ErrorToName(PRErrorCode code) andre@0: { andre@0: struct PRErrorTableList *et; andre@0: andre@0: for (et = Table_List; et; et = et->next) { andre@0: if (et->table->base <= code && andre@0: et->table->base + et->table->n_msgs > code) { andre@0: /* This is the right table */ andre@0: return(et->table->msgs[code - et->table->base].name); andre@0: } andre@0: } andre@0: andre@0: return 0; andre@0: } andre@0: andre@0: PR_IMPLEMENT(const char * const *) andre@0: PR_ErrorLanguages(void) andre@0: { andre@0: return callback_languages; andre@0: } andre@0: andre@0: PR_IMPLEMENT(PRErrorCode) andre@0: PR_ErrorInstallTable(const struct PRErrorTable *table) andre@0: { andre@0: struct PRErrorTableList * new_et; andre@0: andre@0: new_et = (struct PRErrorTableList *) andre@0: PR_Malloc(sizeof(struct PRErrorTableList)); andre@0: if (!new_et) andre@0: return errno; /* oops */ andre@0: new_et->table = table; andre@0: if (callback_newtable) { andre@0: new_et->table_private = callback_newtable(table, callback_private); andre@0: } else { andre@0: new_et->table_private = 0; andre@0: } andre@0: new_et->next = Table_List; andre@0: Table_List = new_et; andre@0: return 0; andre@0: } andre@0: andre@0: PR_IMPLEMENT(void) andre@0: PR_ErrorInstallCallback(const char * const * languages, andre@0: PRErrorCallbackLookupFn *lookup, andre@0: PRErrorCallbackNewTableFn *newtable, andre@0: struct PRErrorCallbackPrivate *cb_private) andre@0: { andre@0: struct PRErrorTableList *et; andre@0: andre@0: assert(strcmp(languages[0], "i-default") == 0); andre@0: assert(strcmp(languages[1], "en") == 0); andre@0: andre@0: callback_languages = languages; andre@0: callback_lookup = lookup; andre@0: callback_newtable = newtable; andre@0: callback_private = cb_private; andre@0: andre@0: if (callback_newtable) { andre@0: for (et = Table_List; et; et = et->next) { andre@0: et->table_private = callback_newtable(et->table, callback_private); andre@0: } andre@0: } andre@0: }