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