Home | History | Annotate | Download | only in uresb
      1 /*
      2 *******************************************************************************
      3 *
      4 *   Copyright (C) 1999-2007, International Business Machines
      5 *   Corporation and others.  All Rights Reserved.
      6 *
      7 *******************************************************************************
      8 *   file name:  uresb.c
      9 *   encoding:   US-ASCII
     10 *   tab size:   8 (not used)
     11 *   indentation:4
     12 *
     13 *   created on: 2000sep6
     14 *   created by: Vladimir Weinstein
     15 */
     16 
     17 /******************************************************************************
     18  * This program prints out resource bundles - example for
     19  * ICU workshop
     20  * TODO: make a complete i18n layout for this program.
     21  ******************************************************************************/
     22 
     23 #include "unicode/putil.h"
     24 #include "unicode/ures.h"
     25 #include "unicode/ustdio.h"
     26 #include "unicode/uloc.h"
     27 #include "unicode/ustring.h"
     28 #include "uoptions.h"
     29 #include "toolutil.h"
     30 
     31 #include <string.h>
     32 #include <stdlib.h>
     33 #ifdef WIN32
     34 #include <direct.h>
     35 #else
     36 #include <unistd.h>
     37 #endif
     38 
     39 #define URESB_DEFAULTTRUNC 40
     40 
     41 static char *currdir = NULL;
     42 /*--locale sr_YU and --encoding cp855
     43  * are interesting on Win32
     44  */
     45 
     46 static const char *locale = NULL;
     47 static const char *encoding = NULL;
     48 static const char *resPath = NULL;
     49 static const int32_t indentsize = 4;
     50 static UFILE *outerr = NULL;
     51 static int32_t truncsize = URESB_DEFAULTTRUNC;
     52 static UBool trunc = FALSE;
     53 
     54 const UChar baderror[] = { 0x0042, 0x0041, 0x0044, 0x0000 };
     55 
     56 const UChar *getErrorName(UErrorCode errorNumber);
     57 void reportError(UErrorCode *status);
     58 static UChar *quotedString(const UChar *string);
     59 void printOutBundle(UFILE *out, UResourceBundle *resource, int32_t indent, UErrorCode *status);
     60 void printIndent(UFILE *out, int32_t indent);
     61 void printHex(UFILE *out, const int8_t *what);
     62 
     63 static UOption options[]={
     64     UOPTION_HELP_H,
     65     UOPTION_HELP_QUESTION_MARK,
     66     { "locale", NULL, NULL, NULL, 'l', UOPT_REQUIRES_ARG, 0 },
     67     UOPTION_ENCODING,
     68     { "path", NULL, NULL, NULL, 'p', UOPT_OPTIONAL_ARG, 0 },
     69     { "truncate", NULL, NULL, NULL, 't', UOPT_OPTIONAL_ARG, 0 },
     70     UOPTION_VERBOSE
     71 };
     72 
     73 static UBool VERBOSE = FALSE;
     74 
     75 extern int
     76 main(int argc, char* argv[]) {
     77 
     78     UResourceBundle *bundle = NULL;
     79     UErrorCode status = U_ZERO_ERROR;
     80     UFILE *out = NULL;
     81     int32_t i = 0;
     82     const char* arg;
     83     char resPathBuffer[1024];
     84 #ifdef WIN32
     85     currdir = _getcwd(NULL, 0);
     86 #else
     87     currdir = getcwd(NULL, 0);
     88 #endif
     89 
     90     argc=u_parseArgs(argc, argv, sizeof(options)/sizeof(options[0]), options);
     91 
     92     /* error handling, printing usage message */
     93     if(argc<0) {
     94         fprintf(stderr,
     95             "error in command line argument \"%s\"\n",
     96             argv[-argc]);
     97     }
     98     if(argc<2 || options[0].doesOccur || options[1].doesOccur) {
     99         fprintf(stderr,
    100             "usage: %s [-options] locale(s)\n",
    101             argv[0]);
    102         return argc<0 ? U_ILLEGAL_ARGUMENT_ERROR : U_ZERO_ERROR;
    103     }
    104 
    105     if(options[2].doesOccur) {
    106         locale = options[2].value;
    107     } else {
    108         locale = 0;
    109     }
    110 
    111     if(options[3].doesOccur) {
    112         encoding = options[3].value;
    113     } else {
    114         encoding = NULL;
    115     }
    116 
    117     if(options[4].doesOccur) {
    118         if(options[4].value != NULL) {
    119             resPath = options[4].value; /* we'll use users resources */
    120         } else {
    121             resPath = NULL; /* we'll use ICU system resources for dumping */
    122         }
    123     } else {
    124         strcpy(resPathBuffer, currdir);
    125         /*strcat(resPathBuffer, U_FILE_SEP_STRING);
    126         strcat(resPathBuffer, "uresb");*/
    127         resPath = resPathBuffer; /* we'll just dump uresb samples resources */
    128     }
    129 
    130     if(options[5].doesOccur) {
    131         trunc = TRUE;
    132         if(options[5].value != NULL) {
    133             truncsize = atoi(options[5].value); /* user defined printable size */
    134         } else {
    135             truncsize = URESB_DEFAULTTRUNC; /* we'll use default omitting size */
    136         }
    137     } else {
    138         trunc = FALSE;
    139     }
    140 
    141     if(options[6].doesOccur) {
    142         VERBOSE = TRUE;
    143     }
    144 
    145     outerr = u_finit(stderr, locale, encoding);
    146     out = u_finit(stdout, locale, encoding);
    147 
    148     for(i = 1; i < argc; ++i) {
    149         status = U_ZERO_ERROR;
    150         arg = getLongPathname(argv[i]);
    151 
    152         u_fprintf(out, "uresb: processing file \"%s\" in path \"%s\"\n", arg, resPath);
    153         bundle = ures_open(resPath, arg, &status);
    154         if(U_SUCCESS(status)) {
    155             u_fprintf(out, "%s\n", arg);
    156             printOutBundle(out, bundle, 0, &status);
    157         } else {
    158             reportError(&status);
    159         }
    160 
    161         ures_close(bundle);
    162     }
    163 
    164 
    165 
    166     u_fclose(out);
    167     u_fclose(outerr);
    168     return 0;
    169 }
    170 
    171 void printIndent(UFILE *out, int32_t indent) {
    172     char inchar[256];
    173     int32_t i = 0;
    174     for(i = 0; i<indent; i++) {
    175         inchar[i] = ' ';
    176     }
    177     inchar[indent] = '\0';
    178     u_fprintf(out, "%s", inchar);
    179 }
    180 
    181 void printHex(UFILE *out, const int8_t *what) {
    182   u_fprintf(out, "%02X", (uint8_t)*what);
    183 }
    184 
    185 static UChar *quotedString(const UChar *string) {
    186     int len = u_strlen(string);
    187     int alen = len;
    188     const UChar *sp;
    189     UChar *newstr, *np;
    190 
    191     for (sp = string; *sp; ++sp) {
    192         switch (*sp) {
    193             case '\n':
    194             case 0x0022:
    195                 ++alen;
    196                 break;
    197         }
    198     }
    199 
    200     newstr = (UChar *) malloc((1 + alen) * sizeof(*newstr));
    201     for (sp = string, np = newstr; *sp; ++sp) {
    202         switch (*sp) {
    203             case '\n':
    204                 *np++ = 0x005C;
    205                 *np++ = 0x006E;
    206                 break;
    207 
    208             case 0x0022:
    209                 *np++ = 0x005C;
    210 
    211             default:
    212                 *np++ = *sp;
    213                 break;
    214         }
    215     }
    216     *np = 0;
    217 
    218     return newstr;
    219 }
    220 
    221 void printOutBundle(UFILE *out, UResourceBundle *resource, int32_t indent, UErrorCode *status) {
    222     int32_t i = 0;
    223     const char *key = ures_getKey(resource);
    224 
    225     switch(ures_getType(resource)) {
    226     case URES_STRING :
    227         {
    228             int32_t len=0;
    229             const UChar*thestr = ures_getString(resource, &len, status);
    230             UChar *string = quotedString(thestr);
    231 
    232             /* TODO: String truncation */
    233             /*
    234             if(trunc && len > truncsize) {
    235                 printIndent(out, indent);
    236                 u_fprintf(out, "// WARNING: this string, size %d is truncated to %d\n", len, truncsize/2);
    237                 len = truncsize/2;
    238             }
    239             */
    240             printIndent(out, indent);
    241             if(key != NULL) {
    242                 u_fprintf(out, "%s { \"%S\" } ", key, string);
    243             } else {
    244                 u_fprintf(out, "\"%S\",", string);
    245             }
    246             if(VERBOSE) {
    247                 u_fprintf(out, " // STRING");
    248             }
    249             u_fprintf(out, "\n");
    250             free(string);
    251         }
    252         break;
    253     case URES_INT :
    254         printIndent(out, indent);
    255         if(key != NULL) {
    256             u_fprintf(out, "%s", key);
    257         }
    258         u_fprintf(out, ":int { %li } ", ures_getInt(resource, status));
    259 
    260         if(VERBOSE) {
    261             u_fprintf(out, " // INT");
    262         }
    263         u_fprintf(out, "\n");
    264         break;
    265     case URES_BINARY :
    266         {
    267             int32_t len = 0;
    268             const int8_t *data = (const int8_t *)ures_getBinary(resource, &len, status);
    269             if(trunc && len > truncsize) {
    270                 printIndent(out, indent);
    271                 u_fprintf(out, "// WARNING: this resource, size %li is truncated to %li\n", len, truncsize/2);
    272                 len = truncsize/2;
    273             }
    274             if(U_SUCCESS(*status)) {
    275                 printIndent(out, indent);
    276                 if(key != NULL) {
    277                     u_fprintf(out, "%s", key);
    278                 }
    279                 u_fprintf(out, ":binary { ");
    280                 for(i = 0; i<len; i++) {
    281                     printHex(out, data++);
    282                 }
    283                 u_fprintf(out, " }");
    284                 if(VERBOSE) {
    285                     u_fprintf(out, " // BINARY");
    286                 }
    287                 u_fprintf(out, "\n");
    288 
    289             } else {
    290                 reportError(status);
    291             }
    292         }
    293         break;
    294     case URES_INT_VECTOR :
    295       {
    296           int32_t len = 0;
    297           const int32_t *data = ures_getIntVector(resource, &len, status);
    298           if(U_SUCCESS(*status)) {
    299               printIndent(out, indent);
    300               if(key != NULL) {
    301                   u_fprintf(out, "%s", key);
    302               }
    303               u_fprintf(out, ":intvector { ");
    304               for(i = 0; i<len-1; i++) {
    305                   u_fprintf(out, "%d, ", data[i]);
    306               }
    307               if(len > 0) {
    308                   u_fprintf(out, "%d ", data[len-1]);
    309               }
    310               u_fprintf(out, "}");
    311               if(VERBOSE) {
    312                   u_fprintf(out, " // INTVECTOR");
    313               }
    314               u_fprintf(out, "\n");
    315 
    316           } else {
    317               reportError(status);
    318           }
    319       }
    320       break;
    321     case URES_TABLE :
    322     case URES_ARRAY :
    323         {
    324             UResourceBundle *t = NULL;
    325             ures_resetIterator(resource);
    326             printIndent(out, indent);
    327             if(key != NULL) {
    328                 u_fprintf(out, "%s ", key);
    329             }
    330             u_fprintf(out, "{");
    331             if(VERBOSE) {
    332                 if(ures_getType(resource) == URES_TABLE) {
    333                     u_fprintf(out, " // TABLE");
    334                 } else {
    335                     u_fprintf(out, " // ARRAY");
    336                 }
    337             }
    338             u_fprintf(out, "\n");
    339 
    340             while(ures_hasNext(resource)) {
    341                 t = ures_getNextResource(resource, t, status);
    342                 printOutBundle(out, t, indent+indentsize, status);
    343             }
    344 
    345             printIndent(out, indent);
    346             u_fprintf(out, "}\n");
    347             ures_close(t);
    348         }
    349         break;
    350     default:
    351         break;
    352     }
    353 
    354 }
    355 
    356 void reportError(UErrorCode *status) {
    357     u_fprintf(outerr, "Error %d(%s) : %U happened!\n", *status, u_errorName(*status), getErrorName(*status));
    358 }
    359 
    360 
    361 const UChar *getErrorName(UErrorCode errorNumber) {
    362     UErrorCode status = U_ZERO_ERROR;
    363     int32_t len = 0;
    364 
    365     UResourceBundle *error = ures_open(currdir, locale, &status);
    366 
    367     UResourceBundle *errorcodes = ures_getByKey(error, "errorcodes", NULL, &status);
    368 
    369     const UChar *result = ures_getStringByIndex(errorcodes, errorNumber, &len, &status);
    370 
    371     ures_close(errorcodes);
    372     ures_close(error);
    373 
    374     if(U_SUCCESS(status)) {
    375         return result;
    376     } else {
    377         return baderror;
    378     }
    379 
    380 }
    381