1 /*
2 **********************************************************************
3 * Copyright (C) 1998-2014, International Business Machines Corporation
4 * and others. All Rights Reserved.
5 **********************************************************************
6 *
7 * File uwmsg.c
8 *
9 * Modification History:
10 *
11 * Date Name Description
12 * 06/14/99 stephen Creation.
13 *******************************************************************************
14 */
15
16 #include "unicode/ucnv.h"
17 #include "unicode/ustring.h"
18 #include "unicode/umsg.h"
19 #include "unicode/uwmsg.h"
20 #include "unicode/ures.h"
21 #include "unicode/putil.h"
22 #include "cstring.h"
23
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <string.h>
28
29 #define BUF_SIZE 128
30
31 /* Print a ustring to the specified FILE* in the default codepage */
32 static void
uprint(const UChar * s,int32_t sourceLen,FILE * f,UErrorCode * status)33 uprint(const UChar *s,
34 int32_t sourceLen,
35 FILE *f,
36 UErrorCode *status)
37 {
38 /* converter */
39 UConverter *converter;
40 char buf [BUF_SIZE];
41 const UChar *mySource;
42 const UChar *mySourceEnd;
43 char *myTarget;
44 int32_t arraySize;
45
46 if(s == 0) return;
47
48 /* set up the conversion parameters */
49 mySource = s;
50 mySourceEnd = mySource + sourceLen;
51 myTarget = buf;
52 arraySize = BUF_SIZE;
53
54 /* open a default converter */
55 converter = ucnv_open(0, status);
56
57 /* if we failed, clean up and exit */
58 if(U_FAILURE(*status)) goto finish;
59
60 /* perform the conversion */
61 do {
62 /* reset the error code */
63 *status = U_ZERO_ERROR;
64
65 /* perform the conversion */
66 ucnv_fromUnicode(converter, &myTarget, myTarget + arraySize,
67 &mySource, mySourceEnd, NULL,
68 TRUE, status);
69
70 /* Write the converted data to the FILE* */
71 fwrite(buf, sizeof(char), myTarget - buf, f);
72
73 /* update the conversion parameters*/
74 myTarget = buf;
75 arraySize = BUF_SIZE;
76 }
77 while(*status == U_BUFFER_OVERFLOW_ERROR);
78
79 finish:
80
81 /* close the converter */
82 ucnv_close(converter);
83 }
84
85 static UResourceBundle *gBundle = NULL;
86
87 U_STRING_DECL(gNoFormatting, " (UCONFIG_NO_FORMATTING see uconfig.h)", 38);
88
u_wmsg_setPath(const char * path,UErrorCode * err)89 U_CFUNC UResourceBundle *u_wmsg_setPath(const char *path, UErrorCode *err)
90 {
91 if(U_FAILURE(*err))
92 {
93 return 0;
94 }
95
96 if(gBundle != NULL)
97 {
98 *err = U_ILLEGAL_ARGUMENT_ERROR;
99 return 0;
100 }
101 else
102 {
103 UResourceBundle *b = NULL;
104 b = ures_open(path, NULL, err);
105 if(U_FAILURE(*err))
106 {
107 return 0;
108 }
109
110 gBundle = b;
111
112 U_STRING_INIT(gNoFormatting, " (UCONFIG_NO_FORMATTING see uconfig.h)", 38);
113 }
114
115 return gBundle;
116 }
117
118 /* Format a message and print it's output to fp */
u_wmsg(FILE * fp,const char * tag,...)119 U_CFUNC int u_wmsg(FILE *fp, const char *tag, ... )
120 {
121 const UChar *msg;
122 int32_t msgLen;
123 UErrorCode err = U_ZERO_ERROR;
124 #if !UCONFIG_NO_FORMATTING
125 va_list ap;
126 #endif
127 UChar result[4096];
128 int32_t resultLength = UPRV_LENGTHOF(result);
129
130 if(gBundle == NULL)
131 {
132 #if 0
133 fprintf(stderr, "u_wmsg: No path set!!\n"); /* FIXME: codepage?? */
134 #endif
135 return -1;
136 }
137
138 msg = ures_getStringByKey(gBundle, tag, &msgLen, &err);
139
140 if(U_FAILURE(err))
141 {
142 return -1;
143 }
144
145 #if UCONFIG_NO_FORMATTING
146 resultLength = sizeof(gNoFormatting) / U_SIZEOF_UCHAR;
147 if((msgLen + resultLength) <= UPRV_LENGTHOF(result)) {
148 memcpy(result, msg, msgLen * U_SIZEOF_UCHAR);
149 memcpy(result + msgLen, gNoFormatting, resultLength);
150 resultLength += msgLen;
151 uprint(result, resultLength, fp, &err);
152 } else {
153 uprint(msg,msgLen, fp, &err);
154 }
155 #else
156 va_start(ap, tag);
157
158 resultLength = u_vformatMessage(uloc_getDefault(), msg, msgLen, result, resultLength, ap, &err);
159
160 va_end(ap);
161
162 if(U_FAILURE(err))
163 {
164 #if 0
165 fprintf(stderr, "u_wmsg: failed to format %s:%s, err %s\n",
166 uloc_getDefault(),
167 tag,
168 u_errorName(err));
169 #endif
170 err = U_ZERO_ERROR;
171 uprint(msg,msgLen, fp, &err);
172 return -1;
173 }
174
175 uprint(result, resultLength, fp, &err);
176 #endif
177
178 if(U_FAILURE(err))
179 {
180 #if 0
181 fprintf(stderr, "u_wmsg: failed to print %s: %s, err %s\n",
182 uloc_getDefault(),
183 tag,
184 u_errorName(err));
185 #endif
186 return -1;
187 }
188
189 return 0;
190 }
191
192 /* these will break if the # of messages change. simply add or remove 0's .. */
193 UChar **gInfoMessages = NULL;
194
195 UChar **gErrMessages = NULL;
196
fetchErrorName(UErrorCode err)197 static const UChar *fetchErrorName(UErrorCode err)
198 {
199 if (!gInfoMessages) {
200 gInfoMessages = (UChar **)malloc((U_ERROR_WARNING_LIMIT-U_ERROR_WARNING_START)*sizeof(UChar*));
201 memset(gInfoMessages, 0, (U_ERROR_WARNING_LIMIT-U_ERROR_WARNING_START)*sizeof(UChar*));
202 }
203 if (!gErrMessages) {
204 gErrMessages = (UChar **)malloc(U_ERROR_LIMIT*sizeof(UChar*));
205 memset(gErrMessages, 0, U_ERROR_LIMIT*sizeof(UChar*));
206 }
207 if(err>=0)
208 return gErrMessages[err];
209 else
210 return gInfoMessages[err-U_ERROR_WARNING_START];
211 }
212
u_wmsg_errorName(UErrorCode err)213 U_CFUNC const UChar *u_wmsg_errorName(UErrorCode err)
214 {
215 UChar *msg;
216 int32_t msgLen;
217 UErrorCode subErr = U_ZERO_ERROR;
218 const char *textMsg = NULL;
219
220 /* try the cache */
221 msg = (UChar*)fetchErrorName(err);
222
223 if(msg)
224 {
225 return msg;
226 }
227
228 if(gBundle == NULL)
229 {
230 msg = NULL;
231 }
232 else
233 {
234 const char *errname = u_errorName(err);
235 if (errname) {
236 msg = (UChar*)ures_getStringByKey(gBundle, errname, &msgLen, &subErr);
237 if(U_FAILURE(subErr))
238 {
239 msg = NULL;
240 }
241 }
242 }
243
244 if(msg == NULL) /* Couldn't find it anywhere.. */
245 {
246 char error[128];
247 textMsg = u_errorName(err);
248 if (!textMsg) {
249 sprintf(error, "UNDOCUMENTED ICU ERROR %d", err);
250 textMsg = error;
251 }
252 msg = (UChar*)malloc((strlen(textMsg)+1)*sizeof(msg[0]));
253 u_charsToUChars(textMsg, msg, (int32_t)(strlen(textMsg)+1));
254 }
255
256 if(err>=0)
257 gErrMessages[err] = msg;
258 else
259 gInfoMessages[err-U_ERROR_WARNING_START] = msg;
260
261 return msg;
262 }
263