• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 **********************************************************************
3 * Copyright (C) 1998-2012, 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 UResourceBundle *gBundle = NULL;
88 
89 U_STRING_DECL(gNoFormatting, " (UCONFIG_NO_FORMATTING see uconfig.h)", 38);
90 
u_wmsg_setPath(const char * path,UErrorCode * err)91 U_CFUNC UResourceBundle *u_wmsg_setPath(const char *path, UErrorCode *err)
92 {
93   if(U_FAILURE(*err))
94   {
95     return 0;
96   }
97 
98   if(gBundle != NULL)
99   {
100     *err = U_ILLEGAL_ARGUMENT_ERROR;
101     return 0;
102   }
103   else
104   {
105     UResourceBundle *b = NULL;
106     b = ures_open(path, NULL, err);
107     if(U_FAILURE(*err))
108     {
109          return 0;
110     }
111 
112     gBundle = b;
113 
114     U_STRING_INIT(gNoFormatting, " (UCONFIG_NO_FORMATTING see uconfig.h)", 38);
115   }
116 
117   return gBundle;
118 }
119 
120 /* Format a message and print it's output to fp */
u_wmsg(FILE * fp,const char * tag,...)121 U_CFUNC int u_wmsg(FILE *fp, const char *tag, ... )
122 {
123     const UChar *msg;
124     int32_t      msgLen;
125     UErrorCode  err = U_ZERO_ERROR;
126 #if !UCONFIG_NO_FORMATTING
127     va_list ap;
128 #endif
129     UChar   result[4096];
130     int32_t resultLength = LENGTHOF(result);
131 
132     if(gBundle == NULL)
133     {
134 #if 0
135         fprintf(stderr, "u_wmsg: No path set!!\n"); /* FIXME: codepage?? */
136 #endif
137         return -1;
138     }
139 
140     msg = ures_getStringByKey(gBundle, tag, &msgLen, &err);
141 
142     if(U_FAILURE(err))
143     {
144         return -1;
145     }
146 
147 #if UCONFIG_NO_FORMATTING
148     resultLength = sizeof(gNoFormatting) / U_SIZEOF_UCHAR;
149     if((msgLen + resultLength) <= LENGTHOF(result)) {
150         memcpy(result, msg, msgLen * U_SIZEOF_UCHAR);
151         memcpy(result + msgLen, gNoFormatting, resultLength);
152         resultLength += msgLen;
153         uprint(result, resultLength, fp, &err);
154     } else {
155         uprint(msg,msgLen, fp, &err);
156     }
157 #else
158     va_start(ap, tag);
159 
160     resultLength = u_vformatMessage(uloc_getDefault(), msg, msgLen, result, resultLength, ap, &err);
161 
162     va_end(ap);
163 
164     if(U_FAILURE(err))
165     {
166 #if 0
167         fprintf(stderr, "u_wmsg: failed to format %s:%s, err %s\n",
168             uloc_getDefault(),
169             tag,
170             u_errorName(err));
171 #endif
172         err = U_ZERO_ERROR;
173         uprint(msg,msgLen, fp, &err);
174         return -1;
175     }
176 
177     uprint(result, resultLength, fp, &err);
178 #endif
179 
180     if(U_FAILURE(err))
181     {
182 #if 0
183         fprintf(stderr, "u_wmsg: failed to print %s: %s, err %s\n",
184             uloc_getDefault(),
185             tag,
186             u_errorName(err));
187 #endif
188         return -1;
189     }
190 
191     return 0;
192 }
193 
194 /* these will break if the # of messages change. simply add or remove 0's .. */
195 UChar **gInfoMessages = NULL;
196 
197 UChar **gErrMessages = NULL;
198 
fetchErrorName(UErrorCode err)199 static const UChar *fetchErrorName(UErrorCode err)
200 {
201     if (!gInfoMessages) {
202         gInfoMessages = (UChar **)malloc((U_ERROR_WARNING_LIMIT-U_ERROR_WARNING_START)*sizeof(UChar*));
203         memset(gInfoMessages, 0, (U_ERROR_WARNING_LIMIT-U_ERROR_WARNING_START)*sizeof(UChar*));
204     }
205     if (!gErrMessages) {
206         gErrMessages = (UChar **)malloc(U_ERROR_LIMIT*sizeof(UChar*));
207         memset(gErrMessages, 0, U_ERROR_LIMIT*sizeof(UChar*));
208     }
209     if(err>=0)
210         return gErrMessages[err];
211     else
212         return gInfoMessages[err-U_ERROR_WARNING_START];
213 }
214 
u_wmsg_errorName(UErrorCode err)215 U_CFUNC const UChar *u_wmsg_errorName(UErrorCode err)
216 {
217     UChar *msg;
218     int32_t msgLen;
219     UErrorCode subErr = U_ZERO_ERROR;
220     const char *textMsg = NULL;
221 
222     /* try the cache */
223     msg = (UChar*)fetchErrorName(err);
224 
225     if(msg)
226     {
227         return msg;
228     }
229 
230     if(gBundle == NULL)
231     {
232         msg = NULL;
233     }
234     else
235     {
236         const char *errname = u_errorName(err);
237         if (errname) {
238             msg = (UChar*)ures_getStringByKey(gBundle, errname, &msgLen, &subErr);
239             if(U_FAILURE(subErr))
240             {
241                 msg = NULL;
242             }
243         }
244     }
245 
246     if(msg == NULL)  /* Couldn't find it anywhere.. */
247     {
248         char error[128];
249         textMsg = u_errorName(err);
250         if (!textMsg) {
251             sprintf(error, "UNDOCUMENTED ICU ERROR %d", err);
252             textMsg = error;
253         }
254         msg = (UChar*)malloc((strlen(textMsg)+1)*sizeof(msg[0]));
255         u_charsToUChars(textMsg, msg, (int32_t)(strlen(textMsg)+1));
256     }
257 
258     if(err>=0)
259         gErrMessages[err] = msg;
260     else
261         gInfoMessages[err-U_ERROR_WARNING_START] = msg;
262 
263     return msg;
264 }
265