Line data Source code
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 0 : 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 0 : p = buf;
73 0 : num >>= ERRCODE_RANGE;
74 : /* num = ?? ??? ??? aaa aaa bbb bbb ccc ccc ddd ddd */
75 0 : num &= 077777777;
76 : /* num = 00 000 000 aaa aaa bbb bbb ccc ccc ddd ddd */
77 0 : for (i = 4; i >= 0; i--) {
78 0 : ch = (num >> BITS_PER_CHAR * i) & ((1 << BITS_PER_CHAR) - 1);
79 0 : if (ch != 0)
80 0 : *p++ = char_set[ch-1];
81 : }
82 0 : *p = '\0';
83 0 : 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 0 : int started = 0;
99 : char *cp;
100 :
101 0 : for (et = Table_List; et; et = et->next) {
102 0 : if (et->table->base <= code &&
103 0 : et->table->base + et->table->n_msgs > code) {
104 : /* This is the right table */
105 0 : if (callback_lookup) {
106 0 : msg = callback_lookup(code, language, et->table,
107 : callback_private, et->table_private);
108 0 : if (msg) return msg;
109 : }
110 :
111 0 : return(et->table->msgs[code - et->table->base].en_text);
112 : }
113 : }
114 :
115 0 : if (code >= 0 && code < 256) {
116 0 : return strerror(code);
117 : }
118 :
119 0 : offset = (int) (code & ((1<<ERRCODE_RANGE)-1));
120 0 : table_num = code - offset;
121 0 : strcpy (buffer, "Unknown code ");
122 0 : if (table_num) {
123 0 : strcat(buffer, error_table_name (table_num));
124 0 : strcat(buffer, " ");
125 : }
126 0 : for (cp = buffer; *cp; cp++)
127 : ;
128 0 : if (offset >= 100) {
129 0 : *cp++ = (char)('0' + offset / 100);
130 0 : offset %= 100;
131 0 : started++;
132 : }
133 0 : if (started || offset >= 10) {
134 0 : *cp++ = (char)('0' + offset / 10);
135 0 : offset %= 10;
136 : }
137 0 : *cp++ = (char)('0' + offset);
138 0 : *cp = '\0';
139 0 : return(buffer);
140 : }
141 :
142 : PR_IMPLEMENT(const char *)
143 : PR_ErrorToName(PRErrorCode code)
144 : {
145 : struct PRErrorTableList *et;
146 :
147 0 : for (et = Table_List; et; et = et->next) {
148 0 : if (et->table->base <= code &&
149 0 : et->table->base + et->table->n_msgs > code) {
150 : /* This is the right table */
151 0 : return(et->table->msgs[code - et->table->base].name);
152 : }
153 : }
154 :
155 0 : return 0;
156 : }
157 :
158 : PR_IMPLEMENT(const char * const *)
159 : PR_ErrorLanguages(void)
160 : {
161 0 : return callback_languages;
162 : }
163 :
164 : PR_IMPLEMENT(PRErrorCode)
165 : PR_ErrorInstallTable(const struct PRErrorTable *table)
166 : {
167 : struct PRErrorTableList * new_et;
168 :
169 8 : new_et = (struct PRErrorTableList *)
170 : PR_Malloc(sizeof(struct PRErrorTableList));
171 8 : if (!new_et)
172 0 : return errno; /* oops */
173 8 : new_et->table = table;
174 8 : if (callback_newtable) {
175 0 : new_et->table_private = callback_newtable(table, callback_private);
176 : } else {
177 8 : new_et->table_private = 0;
178 : }
179 8 : new_et->next = Table_List;
180 8 : Table_List = new_et;
181 8 : 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 0 : assert(strcmp(languages[0], "i-default") == 0);
193 0 : assert(strcmp(languages[1], "en") == 0);
194 :
195 0 : callback_languages = languages;
196 0 : callback_lookup = lookup;
197 0 : callback_newtable = newtable;
198 0 : callback_private = cb_private;
199 :
200 0 : if (callback_newtable) {
201 0 : for (et = Table_List; et; et = et->next) {
202 0 : et->table_private = callback_newtable(et->table, callback_private);
203 : }
204 : }
205 0 : }
|