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