/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  | 0  | PR_ErrorInstallTable(const struct PRErrorTable* table) { | 
155  | 0  |   struct PRErrorTableList* new_et;  | 
156  |  | 
  | 
157  | 0  |   new_et = (struct PRErrorTableList*)PR_Malloc(sizeof(struct PRErrorTableList));  | 
158  | 0  |   if (!new_et) { | 
159  | 0  |     return errno; /* oops */  | 
160  | 0  |   }  | 
161  | 0  |   new_et->table = table;  | 
162  | 0  |   if (callback_newtable) { | 
163  | 0  |     new_et->table_private = callback_newtable(table, callback_private);  | 
164  | 0  |   } else { | 
165  | 0  |     new_et->table_private = 0;  | 
166  | 0  |   }  | 
167  | 0  |   new_et->next = Table_List;  | 
168  | 0  |   Table_List = new_et;  | 
169  | 0  |   return 0;  | 
170  | 0  | }  | 
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  | }  |