/* return TRUE if a base table was read, FALSE for an extension table */ static UBool readFile(ConvData *data, const char* converterName, UErrorCode *pErrorCode) { char line[1024]; char *end; FileStream *convFile; UCMStates *baseStates; UBool dataIsBase; if(U_FAILURE(*pErrorCode)) { return FALSE; } data->ucm=ucm_open(); convFile=T_FileStream_open(converterName, "r"); if(convFile==NULL) { *pErrorCode=U_FILE_ACCESS_ERROR; return FALSE; } readHeader(data, convFile, pErrorCode); if(U_FAILURE(*pErrorCode)) { return FALSE; } if(data->ucm->baseName[0]==0) { dataIsBase=TRUE; baseStates=&data->ucm->states; ucm_processStates(baseStates, IGNORE_SISO_CHECK); } else { dataIsBase=FALSE; baseStates=NULL; } /* read the base table */ ucm_readTable(data->ucm, convFile, dataIsBase, baseStates, pErrorCode); if(U_FAILURE(*pErrorCode)) { return FALSE; } /* read an extension table if there is one */ while(T_FileStream_readLine(convFile, line, sizeof(line))) { end=uprv_strchr(line, 0); while(line<end && (*(end-1)=='\n' || *(end-1)=='\r' || *(end-1)==' ' || *(end-1)=='\t')) { --end; } *end=0; if(line[0]=='#' || u_skipWhitespace(line)==end) { continue; /* ignore empty and comment lines */ } if(0==uprv_strcmp(line, "CHARMAP")) { /* read the extension table */ ucm_readTable(data->ucm, convFile, FALSE, baseStates, pErrorCode); } else { fprintf(stderr, "unexpected text after the base mapping table\n"); } break; } T_FileStream_close(convFile); if(data->ucm->base->flagsType==UCM_FLAGS_MIXED || data->ucm->ext->flagsType==UCM_FLAGS_MIXED) { fprintf(stderr, "error: some entries have the mapping precision (with '|'), some do not\n"); *pErrorCode=U_INVALID_TABLE_FORMAT; } return dataIsBase; }
U_CFUNC Resource res_findResource(const ResourceData *pResData, Resource r, char** path, const char** key) { /* we pass in a path. CollationElements/Sequence or zoneStrings/3/2 etc. * iterates over a path and stops when a scalar resource is found. This * CAN be an alias. Path gets set to the part that has not yet been processed. */ char *pathP = *path, *nextSepP = *path; char *closeIndex = NULL; Resource t1 = r; Resource t2; int32_t indexR = 0; UResType type = RES_GET_TYPE(t1); /* if you come in with an empty path, you'll be getting back the same resource */ if(!uprv_strlen(pathP)) { return r; } /* one needs to have an aggregate resource in order to search in it */ if(!URES_IS_CONTAINER(type)) { return RES_BOGUS; } while(nextSepP && *pathP && t1 != RES_BOGUS && URES_IS_CONTAINER(type)) { /* Iteration stops if: the path has been consumed, we found a non-existing * resource (t1 == RES_BOGUS) or we found a scalar resource (including alias) */ nextSepP = uprv_strchr(pathP, RES_PATH_SEPARATOR); /* if there are more separators, terminate string * and set path to the remaining part of the string */ if(nextSepP != NULL) { *nextSepP = 0; /* overwrite the separator with a NUL to terminate the key */ *path = nextSepP+1; } else { *path = uprv_strchr(pathP, 0); } /* if the resource is a table */ /* try the key based access */ if(URES_IS_TABLE(type)) { *key = pathP; t2 = res_getTableItemByKey(pResData, t1, &indexR, key); if(t2 == RES_BOGUS) { /* if we fail to get the resource by key, maybe we got an index */ indexR = uprv_strtol(pathP, &closeIndex, 10); if(closeIndex != pathP) { /* if we indeed have an index, try to get the item by index */ t2 = res_getTableItemByIndex(pResData, t1, indexR, key); } } } else if(URES_IS_ARRAY(type)) { indexR = uprv_strtol(pathP, &closeIndex, 10); if(closeIndex != pathP) { t2 = res_getArrayItem(pResData, t1, indexR); } else { t2 = RES_BOGUS; /* have an array, but don't have a valid index */ } *key = NULL; } else { /* can't do much here, except setting t2 to bogus */ t2 = RES_BOGUS; } t1 = t2; type = RES_GET_TYPE(t1); /* position pathP to next resource key/index */ pathP = *path; } return t1; }
U_CAPI int32_t uprv_convertToPosix(uint32_t hostid, char *posixID, int32_t posixIDCapacity, UErrorCode* status) { uint16_t langID; uint32_t localeIndex; UBool bLookup = TRUE; const char *pPosixID = NULL; #ifdef USE_WINDOWS_LOCALE_API int32_t tmpLen = 0; char locName[157]; /* ULOC_FULLNAME_CAPACITY */ tmpLen = GetLocaleInfoA(hostid, LOCALE_SNAME, (LPSTR)locName, sizeof(locName)/sizeof(locName[0])); if (tmpLen > 1) { /* Windows locale name may contain sorting variant, such as "es-ES_tradnl". In such case, we need special mapping data found in the hardcoded table in this source file. */ char *p = uprv_strchr(locName, '_'); if (p) { /* Keep the base locale, without variant */ *p = 0; tmpLen = uprv_strlen(locName); } else { /* No hardcoded table lookup necessary */ bLookup = FALSE; } /* Change the tag separator from '-' to '_' */ p = locName; while (*p) { if (*p == '-') { *p = '_'; } p++; } FIX_LANGUAGE_ID_TAG(locName, tmpLen); pPosixID = locName; } #endif if (bLookup) { const char *pCandidate = NULL; langID = LANGUAGE_LCID(hostid); for (localeIndex = 0; localeIndex < gLocaleCount; localeIndex++) { if (langID == gPosixIDmap[localeIndex].regionMaps->hostID) { pCandidate = getPosixID(&gPosixIDmap[localeIndex], hostid); break; } } /* On Windows, when locale name has a variant, we still look up the hardcoded table. If a match in the hardcoded table is longer than the Windows locale name without variant, we use the one as the result */ if (pCandidate && (pPosixID == NULL || uprv_strlen(pCandidate) > uprv_strlen(pPosixID))) { pPosixID = pCandidate; } } if (pPosixID) { int32_t resLen = uprv_strlen(pPosixID); int32_t copyLen = resLen <= posixIDCapacity ? resLen : posixIDCapacity; uprv_memcpy(posixID, pPosixID, copyLen); if (resLen < posixIDCapacity) { posixID[resLen] = 0; if (*status == U_STRING_NOT_TERMINATED_WARNING) { *status = U_ZERO_ERROR; } } else if (resLen == posixIDCapacity) { *status = U_STRING_NOT_TERMINATED_WARNING; } else { *status = U_BUFFER_OVERFLOW_ERROR; } return resLen; } /* no match found */ *status = U_ILLEGAL_ARGUMENT_ERROR; return -1; }
static void U_CALLCONV numericLineFn(void *context, char *fields[][2], int32_t fieldCount, UErrorCode *pErrorCode) { Props newProps={ 0 }; char *s, *numberLimit; uint32_t start, end, value, oldProps32; char c; UBool isFraction; /* get the code point range */ u_parseCodePointRange(fields[0][0], &start, &end, pErrorCode); if(U_FAILURE(*pErrorCode)) { fprintf(stderr, "genprops: syntax error in DerivedNumericValues.txt field 0 at %s\n", fields[0][0]); exit(*pErrorCode); } /* * Ignore the * # @missing: 0000..10FFFF; NaN * line from Unicode 5.1's DerivedNumericValues.txt: * The following code cannot parse "NaN", and we don't want to overwrite * the numeric values for all characters after reading most * from UnicodeData.txt already. */ if(start==0 && end==0x10ffff) { return; } /* check if the numeric value is a fraction (this code does not handle any) */ isFraction=FALSE; s=uprv_strchr(fields[1][0], '.'); if(s!=NULL) { numberLimit=s+1; while('0'<=(c=*numberLimit++) && c<='9') { if(c!='0') { isFraction=TRUE; break; } } } if(isFraction) { value=0; } else { /* parse numeric value */ s=(char *)u_skipWhitespace(fields[1][0]); /* try large, single-significant-digit numbers, may otherwise overflow strtoul() */ if('1'<=s[0] && s[0]<='9' && s[1]=='0' && s[2]=='0') { /* large integers are encoded in a special way, see store.c */ uint8_t exp=0; value=s[0]-'0'; numberLimit=s; while(*(++numberLimit)=='0') { ++exp; } newProps.exponent=exp; } else { /* normal number parsing */ value=(uint32_t)uprv_strtoul(s, &numberLimit, 10); } if(numberLimit<=s || (*numberLimit!='.' && u_skipWhitespace(numberLimit)!=fields[1][1]) || value>=0x80000000) { fprintf(stderr, "genprops: syntax error in DerivedNumericValues.txt field 1 at %s\n", fields[0][0]); exit(U_PARSE_ERROR); } } /* * Unicode 4.0.1 removes the third column that used to list the numeric type. * Assume that either the data is the same as in UnicodeData.txt, * or else that the numeric type is "numeric". * This should work because we only expect to add numeric values for * Han characters; for those, UnicodeData.txt lists only ranges without * specific properties for single characters. */ /* set the new numeric value */ newProps.code=start; newProps.numericValue=(int32_t)value; /* newly parsed numeric value */ /* the exponent may have been set above */ for(; start<=end; ++start) { uint32_t newProps32; int32_t oldNtv; oldProps32=getProps(start); oldNtv=(int32_t)GET_NUMERIC_TYPE_VALUE(oldProps32); if(isFraction) { if(UPROPS_NTV_FRACTION_START<=oldNtv && oldNtv<UPROPS_NTV_LARGE_START) { /* this code point was already listed with its numeric value in UnicodeData.txt */ continue; } else { fprintf(stderr, "genprops: not prepared for new fractions in DerivedNumericValues.txt field 1 at %s\n", fields[1][0]); exit(U_PARSE_ERROR); } } /* * For simplicity, and because we only expect to set numeric values for Han characters, * for now we only allow to set these values for Lo characters. */ if(oldNtv==UPROPS_NTV_NONE && GET_CATEGORY(oldProps32)!=U_OTHER_LETTER) { fprintf(stderr, "genprops error: new numeric value for a character other than Lo in DerivedNumericValues.txt at %s\n", fields[0][0]); exit(U_PARSE_ERROR); } /* verify that we do not change an existing value (fractions were excluded above) */ if(oldNtv!=UPROPS_NTV_NONE) { /* the code point already has a value stored */ newProps.numericType=UPROPS_NTV_GET_TYPE(oldNtv); newProps32=makeProps(&newProps); if(oldNtv!=GET_NUMERIC_TYPE_VALUE(newProps32)) { fprintf(stderr, "genprops error: new numeric value differs from old one for U+%04lx\n", (long)start); exit(U_PARSE_ERROR); } /* same value, continue */ } else { /* the code point is getting a new numeric value */ newProps.numericType=(uint8_t)U_NT_NUMERIC; /* assumed numeric type, see Unicode 4.0.1 comment */ newProps32=makeProps(&newProps); if(beVerbose) { printf("adding U+%04x numeric type %d encoded-numeric-type-value 0x%03x from %s\n", (int)start, U_NT_NUMERIC, (int)GET_NUMERIC_TYPE_VALUE(newProps32), fields[0][0]); } addProps(start, newProps32|GET_CATEGORY(oldProps32)); } } }
extern int main(int argc, char* argv[]) { static char buffer[4096]; char line[512]; FileStream *in, *file; char *s; UErrorCode errorCode=U_ZERO_ERROR; uint32_t i, fileOffset, basenameOffset, length, nread; UBool sourceTOC, verbose; const char *entrypointName = NULL; U_MAIN_INIT_ARGS(argc, argv); /* preset then read command line options */ options[4].value=u_getDataDirectory(); options[6].value=COMMON_DATA_NAME; options[7].value=DATA_TYPE; options[10].value="."; argc=u_parseArgs(argc, argv, sizeof(options)/sizeof(options[0]), options); /* error handling, printing usage message */ if(argc<0) { fprintf(stderr, "error in command line argument \"%s\"\n", argv[-argc]); } else if(argc<2) { argc=-1; } if(argc<0 || options[0].doesOccur || options[1].doesOccur) { FILE *where = argc < 0 ? stderr : stdout; /* * Broken into chucks because the C89 standard says the minimum * required supported string length is 509 bytes. */ fprintf(where, "%csage: %s [ -h, -?, --help ] [ -v, --verbose ] [ -c, --copyright ] [ -C, --comment comment ] [ -d, --destdir dir ] [ -n, --name filename ] [ -t, --type filetype ] [ -S, --source tocfile ] [ -e, --entrypoint name ] maxsize listfile\n", argc < 0 ? 'u' : 'U', *argv); if (options[0].doesOccur || options[1].doesOccur) { fprintf(where, "\n" "Read the list file (default: standard input) and create a common data\n" "file from specified files. Omit any files larger than maxsize, if maxsize > 0.\n"); fprintf(where, "\n" "Options:\n" "\t-h, -?, --help this usage text\n" "\t-v, --verbose verbose output\n" "\t-c, --copyright include the ICU copyright notice\n" "\t-C, --comment comment include a comment string\n" "\t-d, --destdir dir destination directory\n"); fprintf(where, "\t-n, --name filename output filename, without .type extension\n" "\t (default: " COMMON_DATA_NAME ")\n" "\t-t, --type filetype type of the destination file\n" "\t (default: \"" DATA_TYPE "\")\n" "\t-S, --source tocfile write a .c source file with the table of\n" "\t contents\n" "\t-e, --entrypoint name override the c entrypoint name\n" "\t (default: \"<name>_<type>\")\n"); } return argc<0 ? U_ILLEGAL_ARGUMENT_ERROR : U_ZERO_ERROR; } sourceTOC=options[8].doesOccur; verbose = options[2].doesOccur; maxSize=(uint32_t)uprv_strtoul(argv[1], NULL, 0); if(argc==2) { in=T_FileStream_stdin(); } else { in=T_FileStream_open(argv[2], "r"); if(in==NULL) { fprintf(stderr, "gencmn: unable to open input file %s\n", argv[2]); exit(U_FILE_ACCESS_ERROR); } } if (verbose) { if(sourceTOC) { printf("generating %s_%s.c (table of contents source file)\n", options[6].value, options[7].value); } else { printf("generating %s.%s (common data file with table of contents)\n", options[6].value, options[7].value); } } /* read the list of files and get their lengths */ while(T_FileStream_readLine(in, line, sizeof(line))!=NULL) { /* remove trailing newline characters */ s=line; while(*s!=0) { if(*s=='\r' || *s=='\n') { *s=0; break; } ++s; } /* check for comment */ if (*line == '#') { continue; } /* add the file */ #if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR) { char *t; while((t = uprv_strchr(line,U_FILE_ALT_SEP_CHAR))) { *t = U_FILE_SEP_CHAR; } } #endif addFile(getLongPathname(line), sourceTOC, verbose); } if(in!=T_FileStream_stdin()) { T_FileStream_close(in); } if(fileCount==0) { fprintf(stderr, "gencmn: no files listed in %s\n", argc==2 ? "<stdin>" : argv[2]); return 0; } /* sort the files by basename */ qsort(files, fileCount, sizeof(File), compareFiles); if(!sourceTOC) { UNewDataMemory *out; /* determine the offsets of all basenames and files in this common one */ basenameOffset=4+8*fileCount; fileOffset=(basenameOffset+(basenameTotal+15))&~0xf; for(i=0; i<fileCount; ++i) { files[i].fileOffset=fileOffset; fileOffset+=(files[i].fileSize+15)&~0xf; files[i].basenameOffset=basenameOffset; basenameOffset+=files[i].basenameLength; } /* create the output file */ out=udata_create(options[4].value, options[7].value, options[6].value, &dataInfo, options[3].doesOccur ? U_COPYRIGHT_STRING : options[5].value, &errorCode); if(U_FAILURE(errorCode)) { fprintf(stderr, "gencmn: udata_create(-d %s -n %s -t %s) failed - %s\n", options[4].value, options[6].value, options[7].value, u_errorName(errorCode)); exit(errorCode); } /* write the table of contents */ udata_write32(out, fileCount); for(i=0; i<fileCount; ++i) { udata_write32(out, files[i].basenameOffset); udata_write32(out, files[i].fileOffset); } /* write the basenames */ for(i=0; i<fileCount; ++i) { udata_writeString(out, files[i].basename, files[i].basenameLength); } length=4+8*fileCount+basenameTotal; /* copy the files */ for(i=0; i<fileCount; ++i) { /* pad to 16-align the next file */ length&=0xf; if(length!=0) { udata_writePadding(out, 16-length); } if (verbose) { printf("adding %s (%ld byte%s)\n", files[i].pathname, (long)files[i].fileSize, files[i].fileSize == 1 ? "" : "s"); } /* copy the next file */ file=T_FileStream_open(files[i].pathname, "rb"); if(file==NULL) { fprintf(stderr, "gencmn: unable to open listed file %s\n", files[i].pathname); exit(U_FILE_ACCESS_ERROR); } for(nread = 0;;) { length=T_FileStream_read(file, buffer, sizeof(buffer)); if(length <= 0) { break; } nread += length; udata_writeBlock(out, buffer, length); } T_FileStream_close(file); length=files[i].fileSize; if (nread != files[i].fileSize) { fprintf(stderr, "gencmn: unable to read %s properly (got %ld/%ld byte%s)\n", files[i].pathname, (long)nread, (long)files[i].fileSize, files[i].fileSize == 1 ? "" : "s"); exit(U_FILE_ACCESS_ERROR); } } /* pad to 16-align the last file (cleaner, avoids growing .dat files in icuswap) */ length&=0xf; if(length!=0) { udata_writePadding(out, 16-length); } /* finish */ udata_finish(out, &errorCode); if(U_FAILURE(errorCode)) { fprintf(stderr, "gencmn: udata_finish() failed - %s\n", u_errorName(errorCode)); exit(errorCode); } } else { /* write a .c source file with the table of contents */ char *filename; FileStream *out; /* create the output filename */ filename=s=buffer; uprv_strcpy(filename, options[4].value); s=filename+uprv_strlen(filename); if(s>filename && *(s-1)!=U_FILE_SEP_CHAR) { *s++=U_FILE_SEP_CHAR; } uprv_strcpy(s, options[6].value); if(*(options[7].value)!=0) { s+=uprv_strlen(s); *s++='_'; uprv_strcpy(s, options[7].value); } s+=uprv_strlen(s); uprv_strcpy(s, ".c"); /* open the output file */ out=T_FileStream_open(filename, "w"); if(out==NULL) { fprintf(stderr, "gencmn: unable to open .c output file %s\n", filename); exit(U_FILE_ACCESS_ERROR); } /* If an entrypoint is specified, use it. */ if(options[9].doesOccur) { entrypointName = options[9].value; } else { entrypointName = options[6].value; } /* write the source file */ sprintf(buffer, "/*\n" " * ICU common data table of contents for %s.%s ,\n" " * Automatically generated by icu/source/tools/gencmn/gencmn .\n" " */\n\n" "#include \"unicode/utypes.h\"\n" "#include \"unicode/udata.h\"\n" "\n" "/* external symbol declarations for data */\n", options[6].value, options[7].value); T_FileStream_writeLine(out, buffer); sprintf(buffer, "extern const char\n %s%s[]", symPrefix?symPrefix:"", files[0].pathname); T_FileStream_writeLine(out, buffer); for(i=1; i<fileCount; ++i) { sprintf(buffer, ",\n %s%s[]", symPrefix?symPrefix:"", files[i].pathname); T_FileStream_writeLine(out, buffer); } T_FileStream_writeLine(out, ";\n\n"); sprintf( buffer, "U_EXPORT struct {\n" " uint16_t headerSize;\n" " uint8_t magic1, magic2;\n" " UDataInfo info;\n" " char padding[%lu];\n" " uint32_t count, reserved;\n" " struct {\n" " const char *name;\n" " const void *data;\n" " } toc[%lu];\n" "} U_EXPORT2 %s_dat = {\n" " 32, 0xda, 0x27, {\n" " %lu, 0,\n" " %u, %u, %u, 0,\n" " {0x54, 0x6f, 0x43, 0x50},\n" " {1, 0, 0, 0},\n" " {0, 0, 0, 0}\n" " },\n" " \"\", %lu, 0, {\n", (unsigned long)32-4-sizeof(UDataInfo), (unsigned long)fileCount, entrypointName, (unsigned long)sizeof(UDataInfo), U_IS_BIG_ENDIAN, U_CHARSET_FAMILY, U_SIZEOF_UCHAR, (unsigned long)fileCount ); T_FileStream_writeLine(out, buffer); sprintf(buffer, " { \"%s\", %s%s }", files[0].basename, symPrefix?symPrefix:"", files[0].pathname); T_FileStream_writeLine(out, buffer); for(i=1; i<fileCount; ++i) { sprintf(buffer, ",\n { \"%s\", %s%s }", files[i].basename, symPrefix?symPrefix:"", files[i].pathname); T_FileStream_writeLine(out, buffer); } T_FileStream_writeLine(out, "\n }\n};\n"); T_FileStream_close(out); uprv_free(symPrefix); } return 0; }
void pkg_mode_static(UPKGOptions *o, FileStream *makefile, UErrorCode *status) { char tmp[1024]; CharList *tail = NULL; CharList *objects = NULL; if(U_FAILURE(*status)) { return; } uprv_strcpy(tmp, LIB_STATIC_PREFIX); uprv_strcat(tmp, o->libName); uprv_strcat(tmp, UDATA_LIB_SUFFIX); o->outFiles = pkg_appendToList(o->outFiles, &tail, uprv_strdup(tmp)); if (!o->quiet) { pkg_sttc_writeReadme(o, tmp, status); } if(U_FAILURE(*status)) { return; } if(o->nooutput || o->verbose) { fprintf(stdout, "# Output file: %s%s%s\n", o->targetDir, U_FILE_SEP_STRING, tmp); } if(o->nooutput) { *status = U_ZERO_ERROR; return; } /* begin writing makefile ========================= */ T_FileStream_writeLine(makefile, "# Version numbers:\nVERSIONED="); if (o->version) { sprintf(tmp, ".%s", o->version); if (!uprv_strchr(o->version, '.')) { uprv_strcat(tmp, ".0"); } T_FileStream_writeLine(makefile, tmp); T_FileStream_writeLine(makefile, "\nDLL_LDFLAGS=$(LD_SONAME) $(RPATH_LDFLAGS)\n"); } else { T_FileStream_writeLine(makefile, "\nDLL_LDFLAGS=$(BIR_LDFLAGS)\n"); } T_FileStream_writeLine(makefile, "\n"); sprintf(tmp, "# File to make:\nTARGET=%s\n\n", o->outFiles->str); T_FileStream_writeLine(makefile, tmp); T_FileStream_writeLine(makefile, "LIB_TARGET=$(TARGET)\n"); uprv_strcpy(tmp, "all: $(TARG_PATH)$(LIB_TARGET)"); uprv_strcat(tmp, "\n\n"); T_FileStream_writeLine(makefile, tmp); #ifdef OS400 /* New for iSeries: All packaged data in one .c */ sprintf(tmp, "# Create a file which contains all .c data files/structures\n" "$(TEMP_DIR)/$(NAME)all.c: $(CMNLIST)\n\n"); T_FileStream_writeLine(makefile, tmp); #endif /* Write compile rules */ pkg_mak_writeObjRules(o, makefile, &objects, ".$(STATIC_O)"); /* use special .o suffix */ sprintf(tmp, "# List file for gencmn:\n" "CMNLIST=%s%s$(NAME)_static.lst\n\n", o->tmpDir, U_FILE_SEP_STRING); T_FileStream_writeLine(makefile, tmp); if(o->hadStdin == FALSE) { /* shortcut */ T_FileStream_writeLine(makefile, "$(CMNLIST): $(LISTFILES)\n" "\tcat $(LISTFILES) > $(CMNLIST)\n\n"); } else { T_FileStream_writeLine(makefile, "$(CMNLIST): \n" "\t@echo \"generating $@ (list of data files)\"\n" "\t@-$(RMV) $@\n" "\t@for file in $(DATAFILEPATHS); do \\\n" "\t echo $$file >> $@; \\\n" "\tdone;\n\n"); } pkg_mak_writeAssemblyHeader(makefile, o); sprintf(tmp,"$(TEMP_PATH)$(NAME)_dat.$(STATIC_O) : $(TEMP_PATH)$(NAME)_dat.c\n" "\t$(COMPILE.c) -o $@ $<\n\n"); T_FileStream_writeLine(makefile, tmp); T_FileStream_writeLine(makefile, "# 'TOCOBJ' contains C Table of Contents objects [if any]\n"); sprintf(tmp, "$(TEMP_PATH)$(NAME)_dat.c: $(CMNLIST)\n" "\t$(INVOKE) $(GENCMN) -e $(ENTRYPOINT) -n $(NAME) -S -s $(SRCDIR) -d $(TEMP_DIR) 0 $(CMNLIST)\n\n"); T_FileStream_writeLine(makefile, tmp); sprintf(tmp, "TOCOBJ= $(NAME)_dat.$(STATIC_O)\n\n"); T_FileStream_writeLine(makefile, tmp); #ifdef OS400 /* New for iSeries: All packaged data in one .c */ sprintf(tmp,"$(TEMP_PATH)$(NAME)all.$(STATIC_O) : $(TEMP_PATH)$(NAME)all.c\n" "\t$(COMPILE.c) -o $@ $<\n\n"); T_FileStream_writeLine(makefile, tmp); T_FileStream_writeLine(makefile, "# 'ALLDATAOBJ' contains all .c data structures\n"); sprintf(tmp, "ALLDATAOBJ= $(NAME)all%s \n\n", OBJ_SUFFIX); T_FileStream_writeLine(makefile, tmp); #endif sprintf(tmp, "TOCSYM= $(ENTRYPOINT)_dat \n\n"); /* entrypoint not always shortname! */ T_FileStream_writeLine(makefile, tmp); T_FileStream_writeLine(makefile, "BASE_OBJECTS= $(TOCOBJ) "); #ifdef OS400 T_FileStream_writeLine(makefile, "$(ALLDATAOBJ) "); #else pkg_writeCharListWrap(makefile, objects, " ", " \\\n",0); #endif pkg_mak_writeAssemblyFooter(makefile, o); T_FileStream_writeLine(makefile, "\n\n"); T_FileStream_writeLine(makefile, "OBJECTS=$(BASE_OBJECTS:%=$(TEMP_PATH)%)\n\n"); T_FileStream_writeLine(makefile,"$(TEMP_PATH)%.$(STATIC_O): $(TEMP_PATH)%.c\n\t $(COMPILE.c) -o $@ $<\n\n"); #if NO_IMPLICIT_AR T_FileStream_writeLine(makefile, "$(TARG_PATH)$(LIB_TARGET):$(TARG_PATH)$(LIB_TARGET) $(OBJECTS) $(LISTFILES)\n" "\t$(AR) $(ARFLAGS) $(TARG_PATH)$(LIB_TARGET) $(OBJECTS)\n" "\t$(RANLIB) $@\n\n"); #else T_FileStream_writeLine(makefile, "$(TARG_PATH)$(LIB_TARGET):$(TARG_PATH)$(LIB_TARGET)($(OBJECTS)) $(LISTFILES)\n" "\t$(RANLIB) $@\n\n"); #endif T_FileStream_writeLine(makefile, "CLEANFILES= $(CMNLIST) $(OBJECTS) $(TARG_PATH)$(LIB_TARGET) $(TARG_PATH)$(MIDDLE_STATIC_LIB_TARGET) $(TARG_PATH)$(TARGET)\n\nclean:\n\t-$(RMV) $(CLEANFILES) $(MAKEFILE)"); T_FileStream_writeLine(makefile, "\n\n"); T_FileStream_writeLine(makefile, "# static mode shouldn't need to be installed, but we will install the header and static library for them.\n"); T_FileStream_writeLine(makefile, "install: $(TARG_PATH)$(LIB_TARGET)\n" "\t$(INSTALL-L) $(TARG_PATH)$(LIB_TARGET) $(INSTALLTO)/$(LIB_TARGET)\n"); T_FileStream_writeLine(makefile, "\t$(RANLIB) $(INSTALLTO)/$(LIB_TARGET)\n"); if (o->version) { T_FileStream_writeLine(makefile, "\tcd $(INSTALLTO) && $(RM) $(MIDDLE_STATIC_LIB_TARGET) && ln -s $(LIB_TARGET) $(MIDDLE_STATIC_LIB_TARGET)\n\tcd $(INSTALLTO) && $(RM) $(STATIC_LIB_TARGET) && ln -s $(LIB_TARGET) $(STATIC_LIB_TARGET)\n"); T_FileStream_writeLine(makefile, "\t$(RANLIB) $(INSTALLTO)/$(STATIC_LIB_TARGET)\n\n"); } *status = U_ZERO_ERROR; }
U_CDECL_END static void U_CALLCONV initFromResourceBundle(UErrorCode& sts) { U_NAMESPACE_USE ucln_common_registerCleanup(UCLN_COMMON_LOCALE_KEY_TYPE, uloc_key_type_cleanup); gLocExtKeyMap = uhash_open(uhash_hashIChars, uhash_compareIChars, NULL, &sts); LocalUResourceBundlePointer keyTypeDataRes(ures_openDirect(NULL, "keyTypeData", &sts)); LocalUResourceBundlePointer keyMapRes(ures_getByKey(keyTypeDataRes.getAlias(), "keyMap", NULL, &sts)); LocalUResourceBundlePointer typeMapRes(ures_getByKey(keyTypeDataRes.getAlias(), "typeMap", NULL, &sts)); if (U_FAILURE(sts)) { return; } UErrorCode tmpSts = U_ZERO_ERROR; LocalUResourceBundlePointer typeAliasRes(ures_getByKey(keyTypeDataRes.getAlias(), "typeAlias", NULL, &tmpSts)); tmpSts = U_ZERO_ERROR; LocalUResourceBundlePointer bcpTypeAliasRes(ures_getByKey(keyTypeDataRes.getAlias(), "bcpTypeAlias", NULL, &tmpSts)); // initialize vectors storing dynamically allocated objects gKeyTypeStringPool = new UVector(uloc_deleteKeyTypeStringPoolEntry, NULL, sts); if (gKeyTypeStringPool == NULL) { if (U_SUCCESS(sts)) { sts = U_MEMORY_ALLOCATION_ERROR; } } if (U_FAILURE(sts)) { return; } gLocExtKeyDataEntries = new UVector(uloc_deleteKeyDataEntry, NULL, sts); if (gLocExtKeyDataEntries == NULL) { if (U_SUCCESS(sts)) { sts = U_MEMORY_ALLOCATION_ERROR; } } if (U_FAILURE(sts)) { return; } gLocExtTypeEntries = new UVector(uloc_deleteTypeEntry, NULL, sts); if (gLocExtTypeEntries == NULL) { if (U_SUCCESS(sts)) { sts = U_MEMORY_ALLOCATION_ERROR; } } if (U_FAILURE(sts)) { return; } // iterate through keyMap resource LocalUResourceBundlePointer keyMapEntry; while (ures_hasNext(keyMapRes.getAlias())) { keyMapEntry.adoptInstead(ures_getNextResource(keyMapRes.getAlias(), keyMapEntry.orphan(), &sts)); if (U_FAILURE(sts)) { break; } const char* legacyKeyId = ures_getKey(keyMapEntry.getAlias()); int32_t bcpKeyIdLen = 0; const UChar* uBcpKeyId = ures_getString(keyMapEntry.getAlias(), &bcpKeyIdLen, &sts); if (U_FAILURE(sts)) { break; } // empty value indicates that BCP key is same with the legacy key. const char* bcpKeyId = legacyKeyId; if (bcpKeyIdLen > 0) { char* bcpKeyIdBuf = (char*)uprv_malloc(bcpKeyIdLen + 1); if (bcpKeyIdBuf == NULL) { sts = U_MEMORY_ALLOCATION_ERROR; break; } u_UCharsToChars(uBcpKeyId, bcpKeyIdBuf, bcpKeyIdLen); bcpKeyIdBuf[bcpKeyIdLen] = 0; gKeyTypeStringPool->addElement(bcpKeyIdBuf, sts); if (U_FAILURE(sts)) { break; } bcpKeyId = bcpKeyIdBuf; } UBool isTZ = uprv_strcmp(legacyKeyId, "timezone") == 0; UHashtable* typeDataMap = uhash_open(uhash_hashIChars, uhash_compareIChars, NULL, &sts); if (U_FAILURE(sts)) { break; } uint32_t specialTypes = SPECIALTYPE_NONE; LocalUResourceBundlePointer typeAliasResByKey; LocalUResourceBundlePointer bcpTypeAliasResByKey; if (typeAliasRes.isValid()) { tmpSts = U_ZERO_ERROR; typeAliasResByKey.adoptInstead(ures_getByKey(typeAliasRes.getAlias(), legacyKeyId, NULL, &tmpSts)); if (U_FAILURE(tmpSts)) { typeAliasResByKey.orphan(); } } if (bcpTypeAliasRes.isValid()) { tmpSts = U_ZERO_ERROR; bcpTypeAliasResByKey.adoptInstead(ures_getByKey(bcpTypeAliasRes.getAlias(), bcpKeyId, NULL, &tmpSts)); if (U_FAILURE(tmpSts)) { bcpTypeAliasResByKey.orphan(); } } // look up type map for the key, and walk through the mapping data tmpSts = U_ZERO_ERROR; LocalUResourceBundlePointer typeMapResByKey(ures_getByKey(typeMapRes.getAlias(), legacyKeyId, NULL, &tmpSts)); if (U_FAILURE(tmpSts)) { // type map for each key must exist U_ASSERT(FALSE); } else { LocalUResourceBundlePointer typeMapEntry; while (ures_hasNext(typeMapResByKey.getAlias())) { typeMapEntry.adoptInstead(ures_getNextResource(typeMapResByKey.getAlias(), typeMapEntry.orphan(), &sts)); if (U_FAILURE(sts)) { break; } const char* legacyTypeId = ures_getKey(typeMapEntry.getAlias()); // special types if (uprv_strcmp(legacyTypeId, "CODEPOINTS") == 0) { specialTypes |= SPECIALTYPE_CODEPOINTS; continue; } if (uprv_strcmp(legacyTypeId, "REORDER_CODE") == 0) { specialTypes |= SPECIALTYPE_REORDER_CODE; continue; } if (uprv_strcmp(legacyTypeId, "RG_KEY_VALUE") == 0) { specialTypes |= SPECIALTYPE_RG_KEY_VALUE; continue; } if (isTZ) { // a timezone key uses a colon instead of a slash in the resource. // e.g. America:Los_Angeles if (uprv_strchr(legacyTypeId, ':') != NULL) { int32_t legacyTypeIdLen = uprv_strlen(legacyTypeId); char* legacyTypeIdBuf = (char*)uprv_malloc(legacyTypeIdLen + 1); if (legacyTypeIdBuf == NULL) { sts = U_MEMORY_ALLOCATION_ERROR; break; } const char* p = legacyTypeId; char* q = legacyTypeIdBuf; while (*p) { if (*p == ':') { *q++ = '/'; } else { *q++ = *p; } p++; } *q = 0; gKeyTypeStringPool->addElement(legacyTypeIdBuf, sts); if (U_FAILURE(sts)) { break; } legacyTypeId = legacyTypeIdBuf; } } int32_t bcpTypeIdLen = 0; const UChar* uBcpTypeId = ures_getString(typeMapEntry.getAlias(), &bcpTypeIdLen, &sts); if (U_FAILURE(sts)) { break; } // empty value indicates that BCP type is same with the legacy type. const char* bcpTypeId = legacyTypeId; if (bcpTypeIdLen > 0) { char* bcpTypeIdBuf = (char*)uprv_malloc(bcpTypeIdLen + 1); if (bcpTypeIdBuf == NULL) { sts = U_MEMORY_ALLOCATION_ERROR; break; } u_UCharsToChars(uBcpTypeId, bcpTypeIdBuf, bcpTypeIdLen); bcpTypeIdBuf[bcpTypeIdLen] = 0; gKeyTypeStringPool->addElement(bcpTypeIdBuf, sts); if (U_FAILURE(sts)) { break; } bcpTypeId = bcpTypeIdBuf; } // Note: legacy type value should never be // equivalent to bcp type value of a different // type under the same key. So we use a single // map for lookup. LocExtType* t = (LocExtType*)uprv_malloc(sizeof(LocExtType)); if (t == NULL) { sts = U_MEMORY_ALLOCATION_ERROR; break; } t->bcpId = bcpTypeId; t->legacyId = legacyTypeId; gLocExtTypeEntries->addElement((void*)t, sts); if (U_FAILURE(sts)) { break; } uhash_put(typeDataMap, (void*)legacyTypeId, t, &sts); if (bcpTypeId != legacyTypeId) { // different type value uhash_put(typeDataMap, (void*)bcpTypeId, t, &sts); } if (U_FAILURE(sts)) { break; } // also put aliases in the map if (typeAliasResByKey.isValid()) { LocalUResourceBundlePointer typeAliasDataEntry; ures_resetIterator(typeAliasResByKey.getAlias()); while (ures_hasNext(typeAliasResByKey.getAlias()) && U_SUCCESS(sts)) { int32_t toLen; typeAliasDataEntry.adoptInstead(ures_getNextResource(typeAliasResByKey.getAlias(), typeAliasDataEntry.orphan(), &sts)); const UChar* to = ures_getString(typeAliasDataEntry.getAlias(), &toLen, &sts); if (U_FAILURE(sts)) { break; } // check if this is an alias of canoncal legacy type if (uprv_compareInvAscii(NULL, legacyTypeId, -1, to, toLen) == 0) { const char* from = ures_getKey(typeAliasDataEntry.getAlias()); if (isTZ) { // replace colon with slash if necessary if (uprv_strchr(from, ':') != NULL) { int32_t fromLen = uprv_strlen(from); char* fromBuf = (char*)uprv_malloc(fromLen + 1); if (fromBuf == NULL) { sts = U_MEMORY_ALLOCATION_ERROR; break; } const char* p = from; char* q = fromBuf; while (*p) { if (*p == ':') { *q++ = '/'; } else { *q++ = *p; } p++; } *q = 0; gKeyTypeStringPool->addElement(fromBuf, sts); if (U_FAILURE(sts)) { break; } from = fromBuf; } } uhash_put(typeDataMap, (void*)from, t, &sts); } } if (U_FAILURE(sts)) { break; } } if (bcpTypeAliasResByKey.isValid()) { LocalUResourceBundlePointer bcpTypeAliasDataEntry; ures_resetIterator(bcpTypeAliasResByKey.getAlias()); while (ures_hasNext(bcpTypeAliasResByKey.getAlias()) && U_SUCCESS(sts)) { int32_t toLen; bcpTypeAliasDataEntry.adoptInstead(ures_getNextResource(bcpTypeAliasResByKey.getAlias(), bcpTypeAliasDataEntry.orphan(), &sts)); const UChar* to = ures_getString(bcpTypeAliasDataEntry.getAlias(), &toLen, &sts); if (U_FAILURE(sts)) { break; } // check if this is an alias of bcp type if (uprv_compareInvAscii(NULL, bcpTypeId, -1, to, toLen) == 0) { const char* from = ures_getKey(bcpTypeAliasDataEntry.getAlias()); uhash_put(typeDataMap, (void*)from, t, &sts); } } if (U_FAILURE(sts)) { break; } } } } if (U_FAILURE(sts)) { break; } LocExtKeyData* keyData = (LocExtKeyData*)uprv_malloc(sizeof(LocExtKeyData)); if (keyData == NULL) { sts = U_MEMORY_ALLOCATION_ERROR; break; } keyData->bcpId = bcpKeyId; keyData->legacyId = legacyKeyId; keyData->specialTypes = specialTypes; keyData->typeMap = typeDataMap; gLocExtKeyDataEntries->addElement((void*)keyData, sts); if (U_FAILURE(sts)) { break; } uhash_put(gLocExtKeyMap, (void*)legacyKeyId, keyData, &sts); if (legacyKeyId != bcpKeyId) { // different key value uhash_put(gLocExtKeyMap, (void*)bcpKeyId, keyData, &sts); } if (U_FAILURE(sts)) { break; } } }