// © 2017 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html // Copyright (C) 2008-2012 IBM Corporation and Others. All Rights Reserved. #include #include "xmlout.h" #include #include #include "uoptions.h" #include "unicode/putil.h" #include "unicode/ucol.h" #include "unicode/ucal.h" #include "unicode/uchar.h" #include "unicode/ures.h" #include "unicode/udat.h" #include "unicode/ustring.h" #if (U_ICU_VERSION_MAJOR_NUM > 2) || ((U_ICU_VERSION_MAJOR_NUM>1)&&(U_ICU_VERSION_MINOR_NUM>5)) #include "unicode/uclean.h" #endif static char *progName; static UOption options[]={ UOPTION_HELP_H, /* 0 */ UOPTION_HELP_QUESTION_MARK, /* 1 */ UOPTION_VERBOSE, /* 2 */ UOPTION_ICUDATADIR, /* 3 */ UOPTION_DESTDIR, /* 4 */ UOPTION_COPYRIGHT, /* 5 */ }; const char *u_errorNameShort(UErrorCode code) { switch(code) { case U_ZERO_ERROR: return "ok"; case U_MISSING_RESOURCE_ERROR: return "missing"; default: return u_errorName(code); } } void usageAndDie(int retCode) { printf("Usage: %s [-v] [-options] -o output-file dictionary-file\n", progName); printf("\tRead in word list and write out compact trie dictionary\n" "options:\n" "\t-h or -? or --help this usage text\n" "\t-V or --version show a version message\n" "\t-c or --copyright include a copyright notice\n" "\t-v or --verbose turn on verbose output\n" "\t-i or --icudatadir directory for locating any needed intermediate data files,\n" "\t followed by path, defaults to %s\n" "\t-d or --destdir destination directory, followed by the path\n", u_getDataDirectory()); exit (retCode); } /*U_CAPI void U_EXPORT2*/ static void _versionFromUString(UVersionInfo versionArray, const UChar *versionString) { if(versionArray==NULL) { return; } if(versionString!=NULL) { char verchars[U_MAX_VERSION_LENGTH+1]; u_UCharsToChars(versionString, verchars, U_MAX_VERSION_LENGTH); u_versionFromString(versionArray, verchars); } } /*U_CAPI void U_EXPORT2*/ static void _getCLDRVersionDirect(UVersionInfo versionArray, UErrorCode *status) { UResourceBundle *resindx; resindx = ures_openDirect(NULL, "supplementalData", status); if(!U_FAILURE(*status)) { // fprintf(stderr, "Err: could not open res_index, %s\n", u_errorName(status)); // fflush(stderr); // } else { const UChar *cldrver; int32_t len; cldrver = ures_getStringByKey(resindx, "cldrVersion", &len, status); if(!U_FAILURE(*status)) { // fprintf(stderr, "ERR: could not load CLDRVersion key: %s\n", u_errorName(*status)); // fflush(stderr); // } else { // UVersionInfo cldrVersion; _versionFromUString(versionArray, cldrver); // strcpy(tmp, "type=\"cldr\" version=\""); // u_versionToString(cldrVersion, tmp+strlen(tmp)); // strcat(tmp, "\""); // XMLElement icuData(xf, "feature", tmp, TRUE); } ures_close(resindx); } } /*U_CAPI void U_EXPORT2*/ static void _getCLDRVersionOld(UVersionInfo versionArray, UErrorCode *status) { UResourceBundle *resindx; resindx = ures_openDirect(NULL, "res_index", status); if(!U_FAILURE(*status)) { // fprintf(stderr, "Err: could not open res_index, %s\n", u_errorName(status)); // fflush(stderr); // } else { const UChar *cldrver; int32_t len; cldrver = ures_getStringByKey(resindx, "CLDRVersion", &len, status); if(!U_FAILURE(*status)) { // fprintf(stderr, "ERR: could not load CLDRVersion key: %s\n", u_errorName(*status)); // fflush(stderr); // } else { // UVersionInfo cldrVersion; _versionFromUString(versionArray, cldrver); // strcpy(tmp, "type=\"cldr\" version=\""); // u_versionToString(cldrVersion, tmp+strlen(tmp)); // strcat(tmp, "\""); // XMLElement icuData(xf, "feature", tmp, TRUE); } ures_close(resindx); } } int could_open(const char *locale, char *comments) { char tmp[200]; UResourceBundle *rb = NULL; UErrorCode status = U_ZERO_ERROR; rb = ures_open(NULL, locale, &status); if(U_FAILURE(status)) { sprintf(tmp, " open:%s", u_errorName(status)); strcat(comments, tmp); return 0; } else { ures_close(rb); sprintf(tmp, " open:%s", u_errorNameShort(status)); strcat(comments, tmp); return 1; } } int col_could_open(const char *locale, char *comments) { char tmp[200]; UCollator *rb = NULL; UErrorCode status = U_ZERO_ERROR; rb = ucol_open(locale, &status); if(U_FAILURE(status)) { sprintf(tmp, " open:%s", u_errorName(status)); /*strcat(comments, tmp); */ return 0; } else { ucol_close(rb); sprintf(tmp, " open:%s", u_errorNameShort(status)); /* strcat(comments, tmp); */ return 1; } } const char *UDateFormatSymbolType_name(UDateFormatSymbolType i) { switch(i) { case UDAT_ERAS: return "UDAT_ERAS"; break; /** The month names, for example February */ case UDAT_MONTHS: return "UDAT_MONTHS"; break; /** The short month names, for example Feb. */ case UDAT_SHORT_MONTHS: return "UDAT_SHORT_MONTHS"; break; /** The weekday names, for example Monday */ case UDAT_WEEKDAYS: return "UDAT_WEEKDAYS"; break; /** The short weekday names, for example Mon. */ case UDAT_SHORT_WEEKDAYS: return "UDAT_SHORT_WEEKDAYS"; break; /** The AM/PM names, for example AM */ case UDAT_AM_PMS: return "UDAT_AM_PMS"; break; /** The localized characters */ case UDAT_LOCALIZED_CHARS: return "UDAT_LOCALIZED_CHARS"; break; /** The long era names, for example Anno Domini */ #if U_ICU_VERSION_MAJOR_NUM>3 || U_ICU_VERSION_MAJOR_NUM>3 case UDAT_ERA_NAMES: return "UDAT_ERA_NAMES"; break; #endif #if U_ICU_VERSION_MAJOR_NUM>3 || U_ICU_VERSION_MAJOR_NUM>3 /** The narrow month names, for example F */ case UDAT_NARROW_MONTHS: return "UDAT_NARROW_MONTHS"; break; /** The narrow weekday names, for example N */ case UDAT_NARROW_WEEKDAYS: return "UDAT_NARROW_WEEKDAYS"; break; /** Standalone context versions of months */ case UDAT_STANDALONE_MONTHS: return "UDAT_STANDALONE_MONTHS"; break; case UDAT_STANDALONE_SHORT_MONTHS: return "UDAT_STANDALONE_SHORT_MONTHS"; break; case UDAT_STANDALONE_NARROW_MONTHS: return "UDAT_STANDALONE_NARROW_MONTHS"; break; /** Standalone context versions of weekdays */ case UDAT_STANDALONE_WEEKDAYS: return "UDAT_STANDALONE_WEEKDAYS"; break; case UDAT_STANDALONE_SHORT_WEEKDAYS: return "UDAT_STANDALONE_SHORT_WEEKDAYS"; break; case UDAT_STANDALONE_NARROW_WEEKDAYS: return "UDAT_STANDALONE_NARROW_WEEKDAYS"; break; #endif #if U_ICU_VERSION_MAJOR_NUM>3 || U_ICU_VERSION_MAJOR_NUM>4 /** The quarters, for example 1st Quarter */ case UDAT_QUARTERS: return "UDAT_QUARTERS"; break; /** The short quarter names, for example Q1 */ case UDAT_SHORT_QUARTERS: return "UDAT_SHORT_QUARTERS"; break; /** Standalone context versions of quarters */ case UDAT_STANDALONE_QUARTERS: return "UDAT_STANDALONE_QUARTERS"; break; case UDAT_STANDALONE_SHORT_QUARTERS: return "UDAT_STANDALONE_SHORT_QUARTERS"; break; #endif } return ""; } UDateFormatSymbolType scanArray[] = { UDAT_ERAS, /** The month names, for example February */ UDAT_MONTHS, /** The short month names, for example Feb. */ UDAT_SHORT_MONTHS, /** The weekday names, for example Monday */ UDAT_WEEKDAYS, /** The short weekday names, for example Mon. */ UDAT_SHORT_WEEKDAYS, /** The AM/PM names, for example AM */ // UDAT_AM_PMS, /** The localized characters */ // UDAT_LOCALIZED_CHARS, /** The long era names, for example Anno Domini */ // UDAT_ERA_NAMES, /** The narrow month names, for example F */ // UDAT_NARROW_MONTHS, }; int *starts = NULL; UChar ***rootdata = NULL; void initroot(UErrorCode *status) { UDateFormat *fmt; fmt = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, "root", NULL, -1,NULL,0, status); rootdata = (UChar***)malloc((sizeof(scanArray)/sizeof(scanArray[0]))*sizeof(rootdata[0])); starts = (int*)malloc((sizeof(scanArray)/sizeof(scanArray[0]))*sizeof(starts[0])); for(int i=0;U_SUCCESS(*status)&&i\n", locale, UDateFormatSymbolType_name(scanArray[i]), i, j, outbuf[0]); #endif sprintf(tmp, " missing: %s#%d-%s ", UDateFormatSymbolType_name(scanArray[i]), j, u_errorNameShort(*status)); *status = U_MISSING_RESOURCE_ERROR; strcat(comments, tmp); } } } finish: sprintf(tmp, " syms:%d/%d#%d:%s", tf, tc, tl, u_errorNameShort(*status)); strcat(comments,tmp); udat_close(fmt); free(s); } static void writeOkComments(XMLFile &xf, int ok, const char *comments, const char *locale) { char tmp[2000]; tmp[0]=0; if(ok) { if(!comments||!*comments) { strcpy(tmp,locale); strcat(tmp, " "); } else { sprintf(tmp, "%s ", locale, comments); } } else if(comments&&*comments) { sprintf(tmp, "", locale, comments); } if(tmp&&*tmp) { xf.writeln(tmp); } } int could_fmt_dow(const char *locale, char *comments) { char tmp[200]; // UResourceBundle *rb = NULL; UErrorCode status = U_ZERO_ERROR; date(NULL, UDAT_LONG, NULL, locale, comments, &status); if(U_FAILURE(status) || status != U_ZERO_ERROR) { sprintf(tmp, " fmt:%s", u_errorNameShort(status)); strcat(comments, tmp); return 0; } else { sprintf(tmp, " fmt:%s", u_errorNameShort(status)); strcat(comments, tmp); return 1; } } void probeCapability(XMLFile& xf, const char *locale) { char comments[1000]; int ok=1; int rc =0; //fprintf(stderr, "PROBE: %s\n", locale); comments[0]=0; if(!could_open(locale, comments)) { ok = 0; } #if (U_ICU_VERSION_MAJOR_NUM > 2) || ((U_ICU_VERSION_MAJOR_NUM>1)&&(U_ICU_VERSION_MINOR_NUM>2)) if(!could_fmt_dow(locale, comments)) { ok = 0; } #endif writeOkComments(xf,ok, comments,locale); } void probeColCapability(XMLFile& xf, const char *locale) { char comments[1000]; int ok=1; int rc =0; UErrorCode status = U_ZERO_ERROR; //fprintf(stderr, "PROBE: %s\n", locale); comments[0]=0; if(!col_could_open(locale, comments)) { ok = 0; } /* if(!col_could_fmt_dow(locale, comments)) { ok = 0; } */ writeOkComments(xf,ok, comments,locale); } int main (int argc, char ** argv) { U_MAIN_INIT_ARGS(argc, argv); progName = argv[0]; argc=u_parseArgs(argc, argv, sizeof(options)/sizeof(options[0]), options); // const char *loc; { UErrorCode status = U_ZERO_ERROR; #if (U_ICU_VERSION_MAJOR_NUM > 2) || ((U_ICU_VERSION_MAJOR_NUM>1)&&(U_ICU_VERSION_MINOR_NUM>5)) u_init(&status); #else ures_open(NULL, "en_US", &status); #endif fprintf(stderr, " Init: %s\n", u_errorName(status)); } { UErrorCode is = U_ZERO_ERROR; #if (U_ICU_VERSION_MAJOR_NUM > 2) || ((U_ICU_VERSION_MAJOR_NUM>1)&&(U_ICU_VERSION_MINOR_NUM>2)) initroot(&is); fprintf(stderr, "Init: %s\n", u_errorNameShort(is)); #endif } if(argc<0) { // Unrecognized option fprintf(stderr, "error in command line argument \"%s\"\n", argv[-argc]); usageAndDie(U_ILLEGAL_ARGUMENT_ERROR); } if(options[0].doesOccur || options[1].doesOccur) { // -? or -h for help. usageAndDie(0); } { char tmp[200]; XMLFile xf(stdout); { xf.writeln(""); XMLElement icuInfo(xf, "icuInfo"); XMLElement icuProducts(xf, "icuProducts"); XMLElement icuProduct(xf, "icuProduct", "type=\"icu4c\""); XMLElement releases(xf, "releases"); sprintf(tmp, "version=\"%s\"", U_ICU_VERSION); XMLElement release(xf, "release", tmp); XMLElement capabilities(xf, "capabilities"); { sprintf(tmp, "type=\"unicode\" version=\"%s\"", U_UNICODE_VERSION); XMLElement icuData(xf, "feature", tmp, TRUE); } { UCollator *col; char ucavers[200]; UVersionInfo vers; UErrorCode status = U_ZERO_ERROR; col = ucol_open("root", &status); #if (U_ICU_VERSION_MAJOR_NUM>2) || ((U_ICU_VERSION_MAJOR_NUM>1)&&(U_ICU_VERSION_MINOR_NUM>7)) ucol_getUCAVersion(col, vers); u_versionToString(vers, ucavers); #else strcpy(ucavers, "???"); #endif sprintf(tmp, "type=\"uca\" version=\"%s\"", ucavers); XMLElement icuData(xf, "feature", tmp, TRUE); ucol_close(col); } #if (U_ICU_VERSION_MAJOR_NUM>3) || ((U_ICU_VERSION_MAJOR_NUM > 2) && (U_ICU_VERSION_MINOR_NUM >7)) { const char *tzvers; UErrorCode status = U_ZERO_ERROR; tzvers = ucal_getTZDataVersion(&status); sprintf(tmp, "type=\"tz\" version=\"%s\"", tzvers); XMLElement icuData(xf, "feature", tmp, TRUE); } #endif { UErrorCode status = U_ZERO_ERROR; UVersionInfo cldrVersion; _getCLDRVersionDirect(cldrVersion, &status); if(U_FAILURE(status)) { UErrorCode subStatus = U_ZERO_ERROR; _getCLDRVersionOld(cldrVersion, &subStatus); if(U_SUCCESS(subStatus)) { status = subStatus; } } if(U_FAILURE(status)) { fprintf(stderr, "Err: could not get CLDR Version, %s\n", u_errorName(status)); fflush(stderr); } else { strcpy(tmp, "type=\"cldr\" version=\""); u_versionToString(cldrVersion, tmp+strlen(tmp)); strcat(tmp, "\""); XMLElement icuData(xf, "feature", tmp, TRUE); } } if(1) { int n = uloc_countAvailable(); sprintf(tmp, "type=\"formatting\" total=\"%d\" version=\"%s\"", n, "???"); XMLElement icuData(xf, "feature", tmp); // probeCapability(xf, "root"); for(int j=0;j