| OLD | NEW |
| (Empty) |
| 1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
| 2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 /* | |
| 9 | |
| 10 Copyright 1987, 1988 by the Student Information Processing Board | |
| 11 of the Massachusetts Institute of Technology | |
| 12 | |
| 13 Permission to use, copy, modify, and distribute this software | |
| 14 and its documentation for any purpose and without fee is | |
| 15 hereby granted, provided that the above copyright notice | |
| 16 appear in all copies and that both that copyright notice and | |
| 17 this permission notice appear in supporting documentation, | |
| 18 and that the names of M.I.T. and the M.I.T. S.I.P.B. not be | |
| 19 used in advertising or publicity pertaining to distribution | |
| 20 of the software without specific, written prior permission. | |
| 21 M.I.T. and the M.I.T. S.I.P.B. make no representations about | |
| 22 the suitability of this software for any purpose. It is | |
| 23 provided "as is" without express or implied warranty. | |
| 24 | |
| 25 */ | |
| 26 | |
| 27 #include <string.h> | |
| 28 #include <assert.h> | |
| 29 #include <errno.h> | |
| 30 #include "prmem.h" | |
| 31 #include "prerror.h" | |
| 32 | |
| 33 #define ERRCODE_RANGE 8 /* # of bits to shift table number */ | |
| 34 #define BITS_PER_CHAR 6 /* # bits to shift per character in name */ | |
| 35 | |
| 36 #ifdef NEED_SYS_ERRLIST | |
| 37 extern char const * const sys_errlist[]; | |
| 38 extern const int sys_nerr; | |
| 39 #endif | |
| 40 | |
| 41 /* List of error tables */ | |
| 42 struct PRErrorTableList { | |
| 43 struct PRErrorTableList *next; | |
| 44 const struct PRErrorTable *table; | |
| 45 struct PRErrorCallbackTablePrivate *table_private; | |
| 46 }; | |
| 47 static struct PRErrorTableList * Table_List = (struct PRErrorTableList *) NULL; | |
| 48 | |
| 49 /* Supported languages */ | |
| 50 static const char * default_languages[] = { "i-default", "en", 0 }; | |
| 51 static const char * const * callback_languages = default_languages; | |
| 52 | |
| 53 /* Callback info */ | |
| 54 static struct PRErrorCallbackPrivate *callback_private = 0; | |
| 55 static PRErrorCallbackLookupFn *callback_lookup = 0; | |
| 56 static PRErrorCallbackNewTableFn *callback_newtable = 0; | |
| 57 | |
| 58 | |
| 59 static const char char_set[] = | |
| 60 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"; | |
| 61 | |
| 62 static const char * | |
| 63 error_table_name (PRErrorCode num) | |
| 64 { | |
| 65 static char buf[6]; /* only used if internal code problems exist */ | |
| 66 | |
| 67 long ch; | |
| 68 int i; | |
| 69 char *p; | |
| 70 | |
| 71 /* num = aa aaa abb bbb bcc ccc cdd ddd d?? ??? ??? */ | |
| 72 p = buf; | |
| 73 num >>= ERRCODE_RANGE; | |
| 74 /* num = ?? ??? ??? aaa aaa bbb bbb ccc ccc ddd ddd */ | |
| 75 num &= 077777777; | |
| 76 /* num = 00 000 000 aaa aaa bbb bbb ccc ccc ddd ddd */ | |
| 77 for (i = 4; i >= 0; i--) { | |
| 78 ch = (num >> BITS_PER_CHAR * i) & ((1 << BITS_PER_CHAR) - 1); | |
| 79 if (ch != 0) | |
| 80 *p++ = char_set[ch-1]; | |
| 81 } | |
| 82 *p = '\0'; | |
| 83 return(buf); | |
| 84 } | |
| 85 | |
| 86 PR_IMPLEMENT(const char *) | |
| 87 PR_ErrorToString(PRErrorCode code, PRLanguageCode language) | |
| 88 { | |
| 89 /* static buffer only used if code is using inconsistent error message | |
| 90 * numbers, so just ignore the possible thread contention | |
| 91 */ | |
| 92 static char buffer[25]; | |
| 93 | |
| 94 const char *msg; | |
| 95 int offset; | |
| 96 PRErrorCode table_num; | |
| 97 struct PRErrorTableList *et; | |
| 98 int started = 0; | |
| 99 char *cp; | |
| 100 | |
| 101 for (et = Table_List; et; et = et->next) { | |
| 102 if (et->table->base <= code && | |
| 103 et->table->base + et->table->n_msgs > code) { | |
| 104 /* This is the right table */ | |
| 105 if (callback_lookup) { | |
| 106 msg = callback_lookup(code, language, et->table, | |
| 107 callback_private, et->table_private); | |
| 108 if (msg) return msg; | |
| 109 } | |
| 110 | |
| 111 return(et->table->msgs[code - et->table->base].en_text); | |
| 112 } | |
| 113 } | |
| 114 | |
| 115 if (code >= 0 && code < 256) { | |
| 116 return strerror(code); | |
| 117 } | |
| 118 | |
| 119 offset = (int) (code & ((1<<ERRCODE_RANGE)-1)); | |
| 120 table_num = code - offset; | |
| 121 strcpy (buffer, "Unknown code "); | |
| 122 if (table_num) { | |
| 123 strcat(buffer, error_table_name (table_num)); | |
| 124 strcat(buffer, " "); | |
| 125 } | |
| 126 for (cp = buffer; *cp; cp++) | |
| 127 ; | |
| 128 if (offset >= 100) { | |
| 129 *cp++ = (char)('0' + offset / 100); | |
| 130 offset %= 100; | |
| 131 started++; | |
| 132 } | |
| 133 if (started || offset >= 10) { | |
| 134 *cp++ = (char)('0' + offset / 10); | |
| 135 offset %= 10; | |
| 136 } | |
| 137 *cp++ = (char)('0' + offset); | |
| 138 *cp = '\0'; | |
| 139 return(buffer); | |
| 140 } | |
| 141 | |
| 142 PR_IMPLEMENT(const char *) | |
| 143 PR_ErrorToName(PRErrorCode code) | |
| 144 { | |
| 145 struct PRErrorTableList *et; | |
| 146 | |
| 147 for (et = Table_List; et; et = et->next) { | |
| 148 if (et->table->base <= code && | |
| 149 et->table->base + et->table->n_msgs > code) { | |
| 150 /* This is the right table */ | |
| 151 return(et->table->msgs[code - et->table->base].name); | |
| 152 } | |
| 153 } | |
| 154 | |
| 155 return 0; | |
| 156 } | |
| 157 | |
| 158 PR_IMPLEMENT(const char * const *) | |
| 159 PR_ErrorLanguages(void) | |
| 160 { | |
| 161 return callback_languages; | |
| 162 } | |
| 163 | |
| 164 PR_IMPLEMENT(PRErrorCode) | |
| 165 PR_ErrorInstallTable(const struct PRErrorTable *table) | |
| 166 { | |
| 167 struct PRErrorTableList * new_et; | |
| 168 | |
| 169 new_et = (struct PRErrorTableList *) | |
| 170 PR_Malloc(sizeof(struct PRErrorTableList
)); | |
| 171 if (!new_et) | |
| 172 return errno; /* oops */ | |
| 173 new_et->table = table; | |
| 174 if (callback_newtable) { | |
| 175 new_et->table_private = callback_newtable(table, callback_private); | |
| 176 } else { | |
| 177 new_et->table_private = 0; | |
| 178 } | |
| 179 new_et->next = Table_List; | |
| 180 Table_List = new_et; | |
| 181 return 0; | |
| 182 } | |
| 183 | |
| 184 PR_IMPLEMENT(void) | |
| 185 PR_ErrorInstallCallback(const char * const * languages, | |
| 186 PRErrorCallbackLookupFn *lookup, | |
| 187 PRErrorCallbackNewTableFn *newtable, | |
| 188 struct PRErrorCallbackPrivate *cb_private) | |
| 189 { | |
| 190 struct PRErrorTableList *et; | |
| 191 | |
| 192 assert(strcmp(languages[0], "i-default") == 0); | |
| 193 assert(strcmp(languages[1], "en") == 0); | |
| 194 | |
| 195 callback_languages = languages; | |
| 196 callback_lookup = lookup; | |
| 197 callback_newtable = newtable; | |
| 198 callback_private = cb_private; | |
| 199 | |
| 200 if (callback_newtable) { | |
| 201 for (et = Table_List; et; et = et->next) { | |
| 202 et->table_private = callback_newtable(et->table, callback_private); | |
| 203 } | |
| 204 } | |
| 205 } | |
| OLD | NEW |