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 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 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 */ 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 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 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