U_CAPI FileStream * U_EXPORT2 ucbuf_autodetect(const char* fileName, const char** cp,UConverter** conv, int32_t* signatureLength,UErrorCode* error){ FileStream* in=NULL; if(error==NULL || U_FAILURE(*error)){ return NULL; } if(conv==NULL || cp==NULL || fileName==NULL){ *error = U_ILLEGAL_ARGUMENT_ERROR; return NULL; } /* open the file */ in= T_FileStream_open(fileName,"rb"); if(in == NULL){ *error=U_FILE_ACCESS_ERROR; return NULL; } if(ucbuf_autodetect_fs(in,cp,conv,signatureLength,error)) { return in; } else { ucnv_close(*conv); *conv=NULL; T_FileStream_close(in); return NULL; } }
static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName) { int32_t result = 0; char cmd[SMALL_BUFFER_MAX_SIZE] = ""; if (!T_FileStream_file_exists(installDir)) { UErrorCode status = U_ZERO_ERROR; uprv_mkdir(installDir, &status); if (U_FAILURE(status)) { fprintf(stderr, "Error creating installation directory: %s\n", installDir); return -1; } } #ifndef U_WINDOWS_WITH_MSVC char buffer[SMALL_BUFFER_MAX_SIZE] = ""; FileStream *f = T_FileStream_open(fileListName, "r"); if (f != NULL) { for(;;) { if (T_FileStream_readLine(f, buffer, SMALL_BUFFER_MAX_SIZE) != NULL) { /* Remove new line character. */ buffer[uprv_strlen(buffer)-1] = 0; sprintf(cmd, "%s %s%s%s %s%s%s", pkgDataFlags[INSTALL_CMD], srcDir, PKGDATA_FILE_SEP_STRING, buffer, installDir, PKGDATA_FILE_SEP_STRING, buffer); result = system(cmd); if (result != 0) { fprintf(stderr, "Failed to install data file with command: %s\n", cmd); break; } } else { if (!T_FileStream_eof(f)) { fprintf(stderr, "Failed to read line from file: %s\n", fileListName); result = -1; } break; } } T_FileStream_close(f); } else { result = -1; fprintf(stderr, "Unable to open list file: %s\n", fileListName); } #else sprintf(cmd, "%s %s %s %s", WIN_INSTALL_CMD, srcDir, installDir, WIN_INSTALL_CMD_FLAGS); result = system(cmd); if (result != 0) { fprintf(stderr, "Failed to install data file with command: %s\n", cmd); } #endif return result; }
/* Writing Functions */ static void string_write_java(struct SResource *res,UErrorCode *status) { if(uprv_strcmp(srBundle->fKeys+res->fKey,"%%UCARULES")==0 ){ char fileName[1024] ={0}; const char* file = "UCARules.utf8"; FileStream* datFile = NULL; const char* type = "new ICUListResourceBundle.ResourceString("; char* dest = (char*) uprv_malloc( 8 * res->u.fString.fLength); int32_t len = 0; if(outDir){ uprv_strcat(fileName,outDir); if(outDir[uprv_strlen(outDir)-1]!=U_FILE_SEP_CHAR){ uprv_strcat(fileName,U_FILE_SEP_STRING); } } uprv_strcat(fileName,file);/* UCARULES.utf8 UTF-8 file */ write_tabs(out); T_FileStream_write(out, type, (int32_t)uprv_strlen(type)); T_FileStream_write(out, "\"", 1); T_FileStream_write(out, file, (int32_t)uprv_strlen(file)); T_FileStream_write(out, "\")\n", 3); datFile=T_FileStream_open(fileName,"w"); if(!dest){ *status=U_MEMORY_ALLOCATION_ERROR; } u_strToUTF8(dest,8*res->u.fString.fLength,&len,res->u.fString.fChars,res->u.fString.fLength,status); if(U_FAILURE(*status)){ T_FileStream_close(datFile); uprv_free(dest); return; } T_FileStream_write(datFile,dest,len); T_FileStream_close(datFile); uprv_free(dest); }else{ str_write_java(res->u.fString.fChars,res->u.fString.fLength,TRUE,status); if(uprv_strcmp(srBundle->fKeys+res->fKey,"Rule")==0){ UChar* buf = (UChar*) uprv_malloc(sizeof(UChar)*res->u.fString.fLength); uprv_memcpy(buf,res->u.fString.fChars,res->u.fString.fLength); uprv_free(buf); } } }
U_CAPI UNewDataMemory * U_EXPORT2 udata_create(const char *dir, const char *type, const char *name, const UDataInfo *pInfo, const char *comment, UErrorCode *pErrorCode) { UNewDataMemory *pData; uint16_t headerSize, commentLength; char filename[512]; uint8_t bytes[16]; int length; if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { return NULL; } else if(name==NULL || *name==0 || pInfo==NULL) { *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return NULL; } /* allocate the data structure */ pData=(UNewDataMemory *)uprv_malloc(sizeof(UNewDataMemory)); if(pData==NULL) { *pErrorCode=U_MEMORY_ALLOCATION_ERROR; return NULL; } /* Check that the full path won't be too long */ length = 0; /* Start with nothing */ if(dir != NULL && *dir !=0) /* Add directory length if one was given */ { length += strlen(dir); /* Add 1 if dir doesn't end with path sep */ if (dir[strlen(dir) - 1]!= U_FILE_SEP_CHAR) { length++; } } length += strlen(name); /* Add the filename length */ if(type != NULL && *type !=0) { /* Add directory length if given */ length += strlen(type); } /* LDH buffer Length error check */ if(length > (sizeof(filename) - 1)) { *pErrorCode = U_BUFFER_OVERFLOW_ERROR; uprv_free(pData); return NULL; } /* open the output file */ if(dir!=NULL && *dir!=0) { /* if dir has a value, we prepend it to the filename */ char *p=filename+strlen(dir); uprv_strcpy(filename, dir); if (*(p-1)!=U_FILE_SEP_CHAR) { *p++=U_FILE_SEP_CHAR; *p=0; } } else { /* otherwise, we'll output to the current dir */ filename[0]=0; } uprv_strcat(filename, name); if(type!=NULL && *type!=0) { uprv_strcat(filename, "."); uprv_strcat(filename, type); } pData->file=T_FileStream_open(filename, "wb"); if(pData->file==NULL) { uprv_free(pData); *pErrorCode=U_FILE_ACCESS_ERROR; return NULL; } /* write the header information */ headerSize=(uint16_t)(pInfo->size+4); if(comment!=NULL && *comment!=0) { commentLength=(uint16_t)(uprv_strlen(comment)+1); headerSize+=commentLength; } else { commentLength=0; } /* write the size of the header, take padding into account */ pData->headerSize=(uint16_t)((headerSize+15)&~0xf); pData->magic1=0xda; pData->magic2=0x27; T_FileStream_write(pData->file, &pData->headerSize, 4); /* write the information data */ T_FileStream_write(pData->file, pInfo, pInfo->size); /* write the comment */ if(commentLength>0) { T_FileStream_write(pData->file, comment, commentLength); } /* write padding bytes to align the data section to 16 bytes */ headerSize&=0xf; if(headerSize!=0) { headerSize=(uint16_t)(16-headerSize); uprv_memset(bytes, 0, headerSize); T_FileStream_write(pData->file, bytes, headerSize); } return pData; }
int main(int argc, char* argv[]) { UErrorCode status = U_ZERO_ERROR; const char *arg = NULL; const char *outputDir = NULL; /* NULL = no output directory, use current */ const char *inputDir = NULL; const char *encoding = ""; int i; U_MAIN_INIT_ARGS(argc, argv); argc = u_parseArgs(argc, argv, (int32_t)(sizeof(options)/sizeof(options[0])), options); /* error handling, printing usage message */ if(argc<0) { fprintf(stderr, "%s: error in command line argument \"%s\"\n", argv[0], argv[-argc]); } else if(argc<2) { argc = -1; } if(options[WRITE_POOL_BUNDLE].doesOccur && options[USE_POOL_BUNDLE].doesOccur) { fprintf(stderr, "%s: cannot combine --writePoolBundle and --usePoolBundle\n", argv[0]); argc = -1; } if(options[FORMAT_VERSION].doesOccur) { const char *s = options[FORMAT_VERSION].value; if(uprv_strlen(s) != 1 || (s[0] != '1' && s[0] != '2')) { fprintf(stderr, "%s: unsupported --formatVersion %s\n", argv[0], s); argc = -1; } else if(s[0] == '1' && (options[WRITE_POOL_BUNDLE].doesOccur || options[USE_POOL_BUNDLE].doesOccur) ) { fprintf(stderr, "%s: cannot combine --formatVersion 1 with --writePoolBundle or --usePoolBundle\n", argv[0]); argc = -1; } else { setFormatVersion(s[0] - '0'); } } if(options[VERSION].doesOccur) { fprintf(stderr, "%s version %s (ICU version %s).\n" "%s\n", argv[0], GENRB_VERSION, U_ICU_VERSION, U_COPYRIGHT_STRING); return U_ZERO_ERROR; } if(argc<0 || options[HELP1].doesOccur || options[HELP2].doesOccur) { /* * Broken into chunks because the C89 standard says the minimum * required supported string length is 509 bytes. */ fprintf(stderr, "Usage: %s [OPTIONS] [FILES]\n" "\tReads the list of resource bundle source files and creates\n" "\tbinary version of reosurce bundles (.res files)\n", argv[0]); fprintf(stderr, "Options:\n" "\t-h or -? or --help this usage text\n" "\t-q or --quiet do not display warnings\n" "\t-v or --verbose print extra information when processing files\n" "\t-V or --version prints out version number and exits\n" "\t-c or --copyright include copyright notice\n"); fprintf(stderr, "\t-e or --encoding encoding of source files\n" "\t-d of --destdir destination directory, followed by the path, defaults to %s\n" "\t-s or --sourcedir source directory for files followed by path, defaults to %s\n" "\t-i or --icudatadir directory for locating any needed intermediate data files,\n" "\t followed by path, defaults to %s\n", u_getDataDirectory(), u_getDataDirectory(), u_getDataDirectory()); fprintf(stderr, "\t-j or --write-java write a Java ListResourceBundle for ICU4J, followed by optional encoding\n" "\t defaults to ASCII and \\uXXXX format.\n"); /* This option is deprecated and should not be used ever. "\t-p or --package-name For ICU4J: package name for writing the ListResourceBundle for ICU4J,\n" "\t defaults to com.ibm.icu.impl.data\n"); */ fprintf(stderr, "\t-b or --bundle-name bundle name for writing the ListResourceBundle for ICU4J,\n" "\t defaults to LocaleElements\n" "\t-x or --write-xliff write an XLIFF file for the resource bundle. Followed by\n" "\t an optional output file name.\n" "\t-k or --strict use pedantic parsing of syntax\n" /*added by Jing*/ "\t-l or --language for XLIFF: language code compliant with BCP 47.\n"); fprintf(stderr, "\t-C or --noBinaryCollation do not generate binary collation image;\n" "\t makes .res file smaller but collator instantiation much slower;\n" "\t maintains ability to get tailoring rules\n" "\t-R or --omitCollationRules do not include collation (tailoring) rules;\n" "\t makes .res file smaller and maintains collator instantiation speed\n" "\t but tailoring rules will not be available (they are rarely used)\n"); fprintf(stderr, "\t --formatVersion write a .res file compatible with the requested formatVersion (single digit);\n" "\t for example, --formatVersion 1\n"); fprintf(stderr, "\t --writePoolBundle write a pool.res file with all of the keys of all input bundles\n" "\t --usePoolBundle [path-to-pool.res] point to keys from the pool.res keys pool bundle if they are available there;\n" "\t makes .res files smaller but dependent on the pool bundle\n" "\t (--writePoolBundle and --usePoolBundle cannot be combined)\n"); return argc < 0 ? U_ILLEGAL_ARGUMENT_ERROR : U_ZERO_ERROR; } if(options[VERBOSE].doesOccur) { setVerbose(TRUE); } if(options[QUIET].doesOccur) { setShowWarning(FALSE); } if(options[STRICT].doesOccur) { setStrict(TRUE); } if(options[COPYRIGHT].doesOccur){ setIncludeCopyright(TRUE); } if(options[SOURCEDIR].doesOccur) { inputDir = options[SOURCEDIR].value; } if(options[DESTDIR].doesOccur) { outputDir = options[DESTDIR].value; } /* This option is deprecated and should never be used. if(options[PACKAGE_NAME].doesOccur) { gPackageName = options[PACKAGE_NAME].value; if(!strcmp(gPackageName, "ICUDATA")) { gPackageName = U_ICUDATA_NAME; } if(gPackageName[0] == 0) { gPackageName = NULL; } }*/ if(options[ENCODING].doesOccur) { encoding = options[ENCODING].value; } if(options[ICUDATADIR].doesOccur) { u_setDataDirectory(options[ICUDATADIR].value); } /* Initialize ICU */ u_init(&status); if (U_FAILURE(status) && status != U_FILE_ACCESS_ERROR) { /* Note: u_init() will try to open ICU property data. * failures here are expected when building ICU from scratch. * ignore them. */ fprintf(stderr, "%s: can not initialize ICU. status = %s\n", argv[0], u_errorName(status)); exit(1); } status = U_ZERO_ERROR; if(options[WRITE_JAVA].doesOccur) { write_java = TRUE; outputEnc = options[WRITE_JAVA].value; } if(options[BUNDLE_NAME].doesOccur) { bundleName = options[BUNDLE_NAME].value; } if(options[WRITE_XLIFF].doesOccur) { write_xliff = TRUE; if(options[WRITE_XLIFF].value != NULL){ xliffOutputFileName = options[WRITE_XLIFF].value; } } initParser(options[NO_BINARY_COLLATION].doesOccur, options[NO_COLLATION_RULES].doesOccur); /*added by Jing*/ if(options[LANGUAGE].doesOccur) { language = options[LANGUAGE].value; } if(options[WRITE_POOL_BUNDLE].doesOccur) { newPoolBundle = bundle_open(NULL, TRUE, &status); if(U_FAILURE(status)) { fprintf(stderr, "unable to create an empty bundle for the pool keys: %s\n", u_errorName(status)); return status; } else { const char *poolResName = "pool.res"; char *nameWithoutSuffix = uprv_malloc(uprv_strlen(poolResName) + 1); if (nameWithoutSuffix == NULL) { fprintf(stderr, "out of memory error\n"); return U_MEMORY_ALLOCATION_ERROR; } uprv_strcpy(nameWithoutSuffix, poolResName); *uprv_strrchr(nameWithoutSuffix, '.') = 0; newPoolBundle->fLocale = nameWithoutSuffix; } } if(options[USE_POOL_BUNDLE].doesOccur) { const char *poolResName = "pool.res"; FileStream *poolFile; int32_t poolFileSize; int32_t indexLength; /* * TODO: Consolidate inputDir/filename handling from main() and processFile() * into a common function, and use it here as well. * Try to create toolutil functions for dealing with dir/filenames and * loading ICU data files without udata_open(). * Share code with icupkg? * Also, make_res_filename() seems to be unused. Review and remove. */ if (options[USE_POOL_BUNDLE].value!=NULL) { uprv_strcpy(theCurrentFileName, options[USE_POOL_BUNDLE].value); uprv_strcat(theCurrentFileName, U_FILE_SEP_STRING); } else if (inputDir) { uprv_strcpy(theCurrentFileName, inputDir); uprv_strcat(theCurrentFileName, U_FILE_SEP_STRING); } else { *theCurrentFileName = 0; } uprv_strcat(theCurrentFileName, poolResName); poolFile = T_FileStream_open(theCurrentFileName, "rb"); if (poolFile == NULL) { fprintf(stderr, "unable to open pool bundle file %s\n", theCurrentFileName); return 1; } poolFileSize = T_FileStream_size(poolFile); if (poolFileSize < 32) { fprintf(stderr, "the pool bundle file %s is too small\n", theCurrentFileName); return 1; } poolBundle.fBytes = (uint8_t *)uprv_malloc((poolFileSize + 15) & ~15); if (poolFileSize > 0 && poolBundle.fBytes == NULL) { fprintf(stderr, "unable to allocate memory for the pool bundle file %s\n", theCurrentFileName); return U_MEMORY_ALLOCATION_ERROR; } else { UDataSwapper *ds; const DataHeader *header; int32_t bytesRead = T_FileStream_read(poolFile, poolBundle.fBytes, poolFileSize); int32_t keysBottom; if (bytesRead != poolFileSize) { fprintf(stderr, "unable to read the pool bundle file %s\n", theCurrentFileName); return 1; } /* * Swap the pool bundle so that a single checked-in file can be used. * The swapper functions also test that the data looks like * a well-formed .res file. */ ds = udata_openSwapperForInputData(poolBundle.fBytes, bytesRead, U_IS_BIG_ENDIAN, U_CHARSET_FAMILY, &status); if (U_FAILURE(status)) { fprintf(stderr, "udata_openSwapperForInputData(pool bundle %s) failed: %s\n", theCurrentFileName, u_errorName(status)); return status; } ures_swap(ds, poolBundle.fBytes, bytesRead, poolBundle.fBytes, &status); udata_closeSwapper(ds); if (U_FAILURE(status)) { fprintf(stderr, "ures_swap(pool bundle %s) failed: %s\n", theCurrentFileName, u_errorName(status)); return status; } header = (const DataHeader *)poolBundle.fBytes; if (header->info.formatVersion[0]!=2) { fprintf(stderr, "invalid format of pool bundle file %s\n", theCurrentFileName); return U_INVALID_FORMAT_ERROR; } poolBundle.fKeys = (const char *)header + header->dataHeader.headerSize; poolBundle.fIndexes = (const int32_t *)poolBundle.fKeys + 1; indexLength = poolBundle.fIndexes[URES_INDEX_LENGTH] & 0xff; if (indexLength <= URES_INDEX_POOL_CHECKSUM) { fprintf(stderr, "insufficient indexes[] in pool bundle file %s\n", theCurrentFileName); return U_INVALID_FORMAT_ERROR; } keysBottom = (1 + indexLength) * 4; poolBundle.fKeys += keysBottom; poolBundle.fKeysLength = (poolBundle.fIndexes[URES_INDEX_KEYS_TOP] * 4) - keysBottom; poolBundle.fChecksum = poolBundle.fIndexes[URES_INDEX_POOL_CHECKSUM]; } for (i = 0; i < poolBundle.fKeysLength; ++i) { if (poolBundle.fKeys[i] == 0) { ++poolBundle.fKeysCount; } } T_FileStream_close(poolFile); setUsePoolBundle(TRUE); } if(options[INCLUDE_UNIHAN_COLL].doesOccur) { gIncludeUnihanColl = TRUE; } if((argc-1)!=1) { printf("genrb number of files: %d\n", argc - 1); } /* generate the binary files */ for(i = 1; i < argc; ++i) { status = U_ZERO_ERROR; arg = getLongPathname(argv[i]); if (inputDir) { uprv_strcpy(theCurrentFileName, inputDir); uprv_strcat(theCurrentFileName, U_FILE_SEP_STRING); } else { *theCurrentFileName = 0; } uprv_strcat(theCurrentFileName, arg); if (isVerbose()) { printf("Processing file \"%s\"\n", theCurrentFileName); } processFile(arg, encoding, inputDir, outputDir, gPackageName, &status); } uprv_free(poolBundle.fBytes); if(options[WRITE_POOL_BUNDLE].doesOccur) { char outputFileName[256]; bundle_write(newPoolBundle, outputDir, NULL, outputFileName, sizeof(outputFileName), &status); bundle_close(newPoolBundle, &status); if(U_FAILURE(status)) { fprintf(stderr, "unable to write the pool bundle: %s\n", u_errorName(status)); } } /* Dont return warnings as a failure */ if (U_SUCCESS(status)) { return 0; } return status; }
void pkg_sttc_writeReadme(struct UPKGOptions_ *o, const char *libName, UErrorCode *status) { char tmp[1024]; FileStream *out; if(U_FAILURE(*status)) { return; } /* Makefile pathname */ uprv_strcpy(tmp, o->targetDir); uprv_strcat(tmp, U_FILE_SEP_STRING "README_"); uprv_strcat(tmp, o->shortName); uprv_strcat(tmp, ".txt"); out = T_FileStream_open(tmp, "w"); if (!out) { fprintf(stderr, "err: couldn't create README file %s\n", tmp); *status = U_FILE_ACCESS_ERROR; return; } sprintf(tmp, "## README for \"%s\"'s static data (%s)\n" "## created by pkgdata, ICU Version %s\n", o->shortName, libName, U_ICU_VERSION); T_FileStream_writeLine(out, tmp); sprintf(tmp, "\n\nTo use this data in your application:\n\n" "1. At the top of your source file, add the following lines:\n" "\n" " #include \"unicode/utypes.h\"\n" " #include \"unicode/udata.h\"\n" " U_CFUNC char %s_dat[];\n", o->cShortName); T_FileStream_writeLine(out, tmp); sprintf(tmp, "2. *Early* in your application, call the following function:\n" "\n" " UErrorCode myError = U_ZERO_ERROR;\n" " udata_setAppData( \"%s\", (const void*) %s_dat, &myError);\n" " if(U_FAILURE(myError))\n" " {\n" " handle error condition ...\n" " }\n" "\n", o->cShortName, o->cShortName); T_FileStream_writeLine(out, tmp); sprintf(tmp, "3. Link your application against %s\n" "\n\n" "4. Now, you may access this data with a 'path' of \"%s\" as in the following example:\n" "\n" " ... ures_open( \"%s\", \"%s\", &err ); \n", libName, o->shortName, o->shortName, uloc_getDefault()); T_FileStream_writeLine(out, tmp); T_FileStream_close(out); }
FileStream * NormalizerConformanceTest::openNormalizationTestFile(const char *filename) { char unidataPath[2000]; const char *folder; FileStream *input; UErrorCode errorCode; // look inside ICU_DATA first folder=pathToDataDirectory(); if(folder!=NULL) { strcpy(unidataPath, folder); strcat(unidataPath, "unidata" U_FILE_SEP_STRING); strcat(unidataPath, filename); input=T_FileStream_open(unidataPath, "rb"); if(input!=NULL) { return input; } } // find icu/source/data/unidata relative to the test data errorCode=U_ZERO_ERROR; folder=loadTestData(errorCode); if(U_SUCCESS(errorCode)) { strcpy(unidataPath, folder); strcat(unidataPath, U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "unidata" U_FILE_SEP_STRING); strcat(unidataPath, filename); input=T_FileStream_open(unidataPath, "rb"); if(input!=NULL) { return input; } } // look in icu/source/test/testdata/out/build errorCode=U_ZERO_ERROR; folder=loadTestData(errorCode); if(U_SUCCESS(errorCode)) { strcpy(unidataPath, folder); strcat(unidataPath, U_FILE_SEP_STRING); strcat(unidataPath, filename); input=T_FileStream_open(unidataPath, "rb"); if(input!=NULL) { return input; } } // look in icu/source/test/testdata errorCode=U_ZERO_ERROR; folder=loadTestData(errorCode); if(U_SUCCESS(errorCode)) { strcpy(unidataPath, folder); strcat(unidataPath, U_FILE_SEP_STRING ".." U_FILE_SEP_STRING ".." U_FILE_SEP_STRING); strcat(unidataPath, filename); input=T_FileStream_open(unidataPath, "rb"); if(input!=NULL) { return input; } } // find icu/source/data/unidata relative to U_TOPSRCDIR #if defined(U_TOPSRCDIR) strcpy(unidataPath, U_TOPSRCDIR U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "unidata" U_FILE_SEP_STRING); strcat(unidataPath, filename); input=T_FileStream_open(unidataPath, "rb"); if(input!=NULL) { return input; } strcpy(unidataPath, U_TOPSRCDIR U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING); strcat(unidataPath, filename); input=T_FileStream_open(unidataPath, "rb"); if(input!=NULL) { return input; } #endif dataerrln("Failed to open %s", filename); return NULL; }
static void TestFileStream(void){ int32_t c = 0; int32_t c1=0; UErrorCode status = U_ZERO_ERROR; const char* testdatapath = loadTestData(&status); char* fileName = (char*) malloc(uprv_strlen(testdatapath) +10); FileStream* stream = NULL; /* these should not be closed */ FileStream* pStdin = T_FileStream_stdin(); FileStream* pStdout = T_FileStream_stdout(); FileStream* pStderr = T_FileStream_stderr(); const char* testline = "This is a test line"; int32_t bufLen = (int32_t)strlen(testline)+10; char* buf = (char*) malloc(bufLen); int32_t retLen = 0; if(pStdin==NULL){ log_err("failed to get T_FileStream_stdin()"); } if(pStdout==NULL){ log_err("failed to get T_FileStream_stdout()"); } if(pStderr==NULL){ log_err("failed to get T_FileStream_stderr()"); } uprv_strcpy(fileName,testdatapath); uprv_strcat(fileName,".dat"); stream = T_FileStream_open(fileName, "r"); if(stream==NULL){ log_data_err("T_FileStream_open failed to open %s\n",fileName); } else { if(!T_FileStream_file_exists(fileName)){ log_data_err("T_FileStream_file_exists failed to verify existence of %s \n",fileName); } retLen=T_FileStream_read(stream,&c,1); if(retLen==0){ log_data_err("T_FileStream_read failed to read from %s \n",fileName); } retLen=0; T_FileStream_rewind(stream); T_FileStream_read(stream,&c1,1); if(c!=c1){ log_data_err("T_FileStream_rewind failed to rewind %s \n",fileName); } T_FileStream_rewind(stream); c1 = T_FileStream_peek(stream); if(c!=c1){ log_data_err("T_FileStream_peek failed to peekd %s \n",fileName); } c = T_FileStream_getc(stream); T_FileStream_ungetc(c,stream); if(c!= T_FileStream_getc(stream)){ log_data_err("T_FileStream_ungetc failed to d %s \n",fileName); } if(T_FileStream_size(stream)<=0){ log_data_err("T_FileStream_size failed to d %s \n",fileName); } if(T_FileStream_error(stream)){ log_data_err("T_FileStream_error shouldn't have an error %s\n",fileName); } if(!T_FileStream_error(NULL)){ log_err("T_FileStream_error didn't get an error %s\n",fileName); } T_FileStream_putc(stream, 0x20); if(!T_FileStream_error(stream)){ /* Warning writing to a read-only file may not consistently fail on all platforms (e.g. HP-UX, FreeBSD, MacOSX) */ log_verbose("T_FileStream_error didn't get an error when writing to a readonly file %s\n",fileName); } T_FileStream_close(stream); } /* test writing function */ stream=NULL; uprv_strcpy(fileName,testdatapath); uprv_strcat(fileName,".tmp"); stream = T_FileStream_open(fileName,"w+"); if(stream == NULL){ log_data_err("Could not open %s for writing\n",fileName); } else { c= '$'; T_FileStream_putc(stream,c); T_FileStream_rewind(stream); if(c != T_FileStream_getc(stream)){ log_data_err("T_FileStream_putc failed %s\n",fileName); } T_FileStream_rewind(stream); T_FileStream_writeLine(stream,testline); T_FileStream_rewind(stream); T_FileStream_readLine(stream,buf,bufLen); if(uprv_strncmp(testline, buf,uprv_strlen(buf))!=0){ log_data_err("T_FileStream_writeLine failed %s\n",fileName); } T_FileStream_rewind(stream); T_FileStream_write(stream,testline,(int32_t)strlen(testline)); T_FileStream_rewind(stream); retLen = T_FileStream_read(stream, buf, bufLen); if(uprv_strncmp(testline, buf,retLen)!=0){ log_data_err("T_FileStream_write failed %s\n",fileName); } T_FileStream_close(stream); } if(!T_FileStream_remove(fileName)){ log_data_err("T_FileStream_remove failed to delete %s\n",fileName); } free(fileName); free(buf); }
U_CAPI void U_EXPORT2 writeCCode(const char *filename, const char *destdir, const char *optName, const char *optFilename, char *outFilePath) { uint32_t column = MAX_COLUMN; char buffer[4096], entry[64]; FileStream *in, *out; size_t i, length; in=T_FileStream_open(filename, "rb"); if(in==NULL) { fprintf(stderr, "genccode: unable to open input file %s\n", filename); exit(U_FILE_ACCESS_ERROR); } if(optName != NULL) { /* prepend 'icudt28_' */ strcpy(entry, optName); strcat(entry, "_"); } else { entry[0] = 0; } getOutFilename(filename, destdir, buffer, entry+uprv_strlen(entry), ".c", optFilename); if (outFilePath != NULL) { uprv_strcpy(outFilePath, buffer); } out=T_FileStream_open(buffer, "w"); if(out==NULL) { fprintf(stderr, "genccode: unable to open output file %s\n", buffer); exit(U_FILE_ACCESS_ERROR); } /* turn dashes or dots in the entry name into underscores */ length=uprv_strlen(entry); for(i=0; i<length; ++i) { if(entry[i]=='-' || entry[i]=='.') { entry[i]='_'; } } #if U_PLATFORM == U_PF_OS400 /* TODO: Fix this once the compiler implements this feature. Keep in sync with udatamem.c This is here because this platform can't currently put const data into the read-only pages of an object or shared library (service program). Only strings are allowed in read-only pages, so we use char * strings to store the data. In order to prevent the beginning of the data from ever matching the magic numbers we must still use the initial double. [grhoten 4/24/2003] */ sprintf(buffer, "#ifndef IN_GENERATED_CCODE\n" "#define IN_GENERATED_CCODE\n" "#define U_DISABLE_RENAMING 1\n" "#include \"unicode/umachine.h\"\n" "#endif\n" "U_CDECL_BEGIN\n" "const struct {\n" " double bogus;\n" " const char *bytes; \n" "} %s={ 0.0, \n", entry); T_FileStream_writeLine(out, buffer); for(;;) { length=T_FileStream_read(in, buffer, sizeof(buffer)); if(length==0) { break; } for(i=0; i<length; ++i) { column = write8str(out, (uint8_t)buffer[i], column); } } T_FileStream_writeLine(out, "\"\n};\nU_CDECL_END\n"); #else /* Function renaming shouldn't be done in data */ sprintf(buffer, "#ifndef IN_GENERATED_CCODE\n" "#define IN_GENERATED_CCODE\n" "#define U_DISABLE_RENAMING 1\n" "#include \"unicode/umachine.h\"\n" "#endif\n" "U_CDECL_BEGIN\n" "const struct {\n" " double bogus;\n" " uint8_t bytes[%ld]; \n" "} %s={ 0.0, {\n", (long)T_FileStream_size(in), entry); T_FileStream_writeLine(out, buffer); for(;;) { length=T_FileStream_read(in, buffer, sizeof(buffer)); if(length==0) { break; } for(i=0; i<length; ++i) { column = write8(out, (uint8_t)buffer[i], column); } } T_FileStream_writeLine(out, "\n}\n};\nU_CDECL_END\n"); #endif if(T_FileStream_error(in)) { fprintf(stderr, "genccode: file read error while generating from file %s\n", filename); exit(U_FILE_ACCESS_ERROR); } if(T_FileStream_error(out)) { fprintf(stderr, "genccode: file write error while generating from file %s\n", filename); exit(U_FILE_ACCESS_ERROR); } T_FileStream_close(out); T_FileStream_close(in); }
UXMLElement * UXMLParser::parseFile(const char *filename, UErrorCode &errorCode) { char bytes[4096], charsetBuffer[100]; FileStream *f; const char *charset, *pb; UnicodeString src; UConverter *cnv; UChar *buffer, *pu; int32_t fileLength, bytesLength, length, capacity; UBool flush; if(U_FAILURE(errorCode)) { return NULL; } f=T_FileStream_open(filename, "rb"); if(f==NULL) { errorCode=U_FILE_ACCESS_ERROR; return NULL; } bytesLength=T_FileStream_read(f, bytes, (int32_t)sizeof(bytes)); if(bytesLength<(int32_t)sizeof(bytes)) { // we have already read the entire file fileLength=bytesLength; } else { // get the file length fileLength=T_FileStream_size(f); } /* * get the charset: * 1. Unicode signature * 2. treat as ISO-8859-1 and read XML encoding="charser" * 3. default to UTF-8 */ charset=ucnv_detectUnicodeSignature(bytes, bytesLength, NULL, &errorCode); if(U_SUCCESS(errorCode) && charset!=NULL) { // open converter according to Unicode signature cnv=ucnv_open(charset, &errorCode); } else { // read as Latin-1 and parse the XML declaration and encoding cnv=ucnv_open("ISO-8859-1", &errorCode); if(U_FAILURE(errorCode)) { // unexpected error opening Latin-1 converter goto exit; } buffer=src.getBuffer(bytesLength); if(buffer==NULL) { // unexpected failure to reserve some string capacity errorCode=U_MEMORY_ALLOCATION_ERROR; goto exit; } pb=bytes; pu=buffer; ucnv_toUnicode( cnv, &pu, buffer+src.getCapacity(), &pb, bytes+bytesLength, NULL, TRUE, &errorCode); src.releaseBuffer(U_SUCCESS(errorCode) ? (int32_t)(pu-buffer) : 0); ucnv_close(cnv); cnv=NULL; if(U_FAILURE(errorCode)) { // unexpected error in conversion from Latin-1 src.remove(); goto exit; } // parse XML declaration if(mXMLDecl.reset(src).lookingAt(0, errorCode)) { int32_t declEnd=mXMLDecl.end(errorCode); // go beyond <?xml int32_t pos=src.indexOf((UChar)x_l)+1; mAttrValue.reset(src); while(pos<declEnd && mAttrValue.lookingAt(pos, errorCode)) { // loop runs once per attribute on this element. UnicodeString attName = mAttrValue.group(1, errorCode); UnicodeString attValue = mAttrValue.group(2, errorCode); // Trim the quotes from the att value. These are left over from the original regex // that parsed the attribue, which couldn't conveniently strip them. attValue.remove(0,1); // one char from the beginning attValue.truncate(attValue.length()-1); // and one from the end. if(attName==UNICODE_STRING("encoding", 8)) { length=attValue.extract(0, 0x7fffffff, charsetBuffer, (int32_t)sizeof(charsetBuffer)); charset=charsetBuffer; break; } pos = mAttrValue.end(2, errorCode); } if(charset==NULL) { // default to UTF-8 charset="UTF-8"; } cnv=ucnv_open(charset, &errorCode); } } if(U_FAILURE(errorCode)) { // unable to open the converter goto exit; } // convert the file contents capacity=fileLength; // estimated capacity src.getBuffer(capacity); src.releaseBuffer(0); // zero length flush=FALSE; for(;;) { // convert contents of bytes[bytesLength] pb=bytes; for(;;) { length=src.length(); buffer=src.getBuffer(capacity); if(buffer==NULL) { // unexpected failure to reserve some string capacity errorCode=U_MEMORY_ALLOCATION_ERROR; goto exit; } pu=buffer+length; ucnv_toUnicode( cnv, &pu, buffer+src.getCapacity(), &pb, bytes+bytesLength, NULL, FALSE, &errorCode); src.releaseBuffer(U_SUCCESS(errorCode) ? (int32_t)(pu-buffer) : 0); if(errorCode==U_BUFFER_OVERFLOW_ERROR) { errorCode=U_ZERO_ERROR; capacity=(3*src.getCapacity())/2; // increase capacity by 50% } else { break; } } if(U_FAILURE(errorCode)) { break; // conversion error } if(flush) { break; // completely converted the file } // read next block bytesLength=T_FileStream_read(f, bytes, (int32_t)sizeof(bytes)); if(bytesLength==0) { // reached end of file, convert once more to flush the converter flush=TRUE; } }; exit: ucnv_close(cnv); T_FileStream_close(f); if(U_SUCCESS(errorCode)) { return parse(src, errorCode); } else { return NULL; } }
/* 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, converterName, 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; }
/* * Opens the given fileName and reads in the information storing the data in flagBuffer. */ U_CAPI int32_t U_EXPORT2 parseFlagsFile(const char *fileName, char **flagBuffer, int32_t flagBufferSize, int32_t numOfFlags, UErrorCode *status) { char* buffer = uprv_malloc(sizeof(char) * currentBufferSize); UBool allocateMoreSpace = FALSE; int32_t i; int32_t result = 0; FileStream *f = T_FileStream_open(fileName, "r"); if (f == NULL) { *status = U_FILE_ACCESS_ERROR; return -1; } if (buffer == NULL) { *status = U_MEMORY_ALLOCATION_ERROR; return -1; } do { if (allocateMoreSpace) { allocateMoreSpace = FALSE; currentBufferSize *= 2; uprv_free(buffer); buffer = uprv_malloc(sizeof(char) * currentBufferSize); if (buffer == NULL) { *status = U_MEMORY_ALLOCATION_ERROR; return -1; } } for (i = 0; i < numOfFlags; i++) { if (T_FileStream_readLine(f, buffer, currentBufferSize) == NULL) { *status = U_FILE_ACCESS_ERROR; break; } if (uprv_strlen(buffer) == (currentBufferSize - 1) && buffer[currentBufferSize-2] != '\n') { /* Allocate more space for buffer if it didnot read the entrire line */ allocateMoreSpace = TRUE; T_FileStream_rewind(f); break; } else { extractFlag(buffer, currentBufferSize, flagBuffer[i], flagBufferSize, status); if (U_FAILURE(*status)) { if (*status == U_BUFFER_OVERFLOW_ERROR) { result = currentBufferSize; } else { result = -1; } break; } } } } while (allocateMoreSpace && U_SUCCESS(*status)); uprv_free(buffer); T_FileStream_close(f); if (U_SUCCESS(*status) && result == 0) { currentBufferSize = DEFAULT_BUFFER_SIZE; } return result; }
static void bin_write_java( struct SResource *res, UErrorCode *status) { const char* type = "new ICUListResourceBundle.CompressedBinary("; const char* ext; int32_t srcLen=res->u.fBinaryValue.fLength; if(srcLen>0 ){ uint16_t* target=NULL; uint16_t* saveTarget = NULL; int32_t tgtLen = 0; if(uprv_strcmp(srBundle->fKeys+res->fKey,"%%CollationBin")==0 || uprv_strcmp(srBundle->fKeys+res->fKey,"BreakDictionaryData")==0){ char fileName[1024] ={0}; char fn[1024] = {0}; FileStream* datFile = NULL; if(uprv_strcmp(srBundle->fKeys+res->fKey,"BreakDictionaryData")==0){ uprv_strcat(fileName,"BreakDictionaryData"); ext = ".brk"; }else{ uprv_strcat(fileName,"CollationElements"); ext=".col"; } if(uprv_strcmp(srBundle->fLocale,"root")!=0){ uprv_strcat(fileName,"_"); uprv_strcat(fileName,srBundle->fLocale); } uprv_strcat(fileName,ext); if(outDir ){ uprv_strcat(fn,outDir); if(outDir[uprv_strlen(outDir)-1]!=U_FILE_SEP_CHAR){ uprv_strcat(fn,U_FILE_SEP_STRING); } } uprv_strcat(fn,fileName); type = "new ICUListResourceBundle.ResourceBinary("; write_tabs(out); T_FileStream_write(out, type, (int32_t)uprv_strlen(type)); T_FileStream_write(out, "\"", 1); T_FileStream_write(out, fileName, (int32_t)uprv_strlen(fileName)); T_FileStream_write(out, "\"),\n", 4); datFile=T_FileStream_open(fn,"w"); T_FileStream_write(datFile, res->u.fBinaryValue.fData, res->u.fBinaryValue.fLength); T_FileStream_close(datFile); }else{ srcLen = res->u.fBinaryValue.fLength; tgtLen = srcLen * 2; target = (uint16_t*)malloc(sizeof(uint16_t) * tgtLen); saveTarget = target; if(target){ tgtLen = byteArrayToRLEString(res->u.fBinaryValue.fData, srcLen,target, tgtLen,status); if(U_FAILURE(*status)){ printf("Could not encode got error : %s \n", u_errorName(*status)); return; } #if DEBUG /***************** Test Roundtripping *********************/ { int32_t myTargetLen = rleStringToByteArray(target,tgtLen,NULL,0,status); uint8_t* myTarget = (uint8_t*) malloc(sizeof(uint8_t) * myTargetLen); /* test for NULL */ if(myTarget == NULL) { *status = U_MEMORY_ALLOCATION_ERROR; return; } int i=0; int32_t retVal=0; *status = U_ZERO_ERROR; retVal=rleStringToByteArray(target,tgtLen,myTarget,myTargetLen,status); if(U_SUCCESS(*status)){ for(i=0; i< srcLen;i++){ if(res->u.fBinaryValue.fData[i]!= myTarget[i]){ printf("the encoded string cannot be decoded Expected : 0x%02X Got : %: 0x%02X at %i\n",res->u.fBinaryValue.fData[i],myTarget[i], i); } } }else{ printf("Could not decode got error : %s \n", u_errorName(*status)); } free(myTarget); } #endif }else{ *status = U_MEMORY_ALLOCATION_ERROR; return; } write_tabs(out); T_FileStream_write(out, type, (int32_t)uprv_strlen(type)); T_FileStream_write(out, "\n", 1); tabCount++; write_tabs(out); str_write_java(target, tgtLen,FALSE, status); tabCount--; T_FileStream_write(out, "),\n", 3); free(target); } }else{ write_tabs(out); T_FileStream_write(out,type,uprv_strlen(type)); T_FileStream_write(out,"null),\n",7); } }
extern int main(int argc, char* argv[]) { int i, n; char pathBuf[512]; FileStream *in; UNewDataMemory *out; UErrorCode errorCode=U_ZERO_ERROR; U_MAIN_INIT_ARGS(argc, argv); /* preset then read command line options */ options[DESTDIR].value=options[SOURCEDIR].value=u_getDataDirectory(); 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]); } if(argc<0 || options[HELP1].doesOccur || options[HELP2].doesOccur) { fprintf(stderr, "usage: %s [-options] [convrtrs.txt]\n" "\tread convrtrs.txt and create " U_ICUDATA_NAME "_" DATA_NAME "." DATA_TYPE "\n" "options:\n" "\t-h or -? or --help this usage text\n" "\t-v or --verbose prints out extra information about the alias table\n" "\t-q or --quiet do not display warnings and progress\n" "\t-c or --copyright include a copyright notice\n" "\t-d or --destdir destination directory, followed by the path\n" "\t-s or --sourcedir source directory, followed by the path\n", argv[0]); return argc<0 ? U_ILLEGAL_ARGUMENT_ERROR : U_ZERO_ERROR; } if(options[VERBOSE].doesOccur) { verbose = TRUE; } if(options[QUIET].doesOccur) { quiet = TRUE; } if(argc>=2) { path=argv[1]; } else { path=options[SOURCEDIR].value; if(path!=NULL && *path!=0) { char *end; uprv_strcpy(pathBuf, path); end = uprv_strchr(pathBuf, 0); if(*(end-1)!=U_FILE_SEP_CHAR) { *(end++)=U_FILE_SEP_CHAR; } uprv_strcpy(end, "convrtrs.txt"); path=pathBuf; } else { path = "convrtrs.txt"; } } uprv_memset(stringStore, 0, sizeof(stringStore)); uprv_memset(tagStore, 0, sizeof(tagStore)); uprv_memset(converters, 0, sizeof(converters)); uprv_memset(tags, 0, sizeof(tags)); uprv_memset(aliasLists, 0, sizeof(aliasLists)); uprv_memset(knownAliases, 0, sizeof(aliasLists)); in=T_FileStream_open(path, "r"); if(in==NULL) { fprintf(stderr, "gencnval: unable to open input file %s\n", path); exit(U_FILE_ACCESS_ERROR); } parseFile(in); T_FileStream_close(in); /* create the output file */ out=udata_create(options[DESTDIR].value, DATA_TYPE, DATA_NAME, &dataInfo, options[COPYRIGHT].doesOccur ? U_COPYRIGHT_STRING : NULL, &errorCode); if(U_FAILURE(errorCode)) { fprintf(stderr, "gencnval: unable to open output file - error %s\n", u_errorName(errorCode)); exit(errorCode); } /* write the table of aliases based on a tag/converter name combination */ writeAliasTable(out); /* finish */ udata_finish(out, &errorCode); if(U_FAILURE(errorCode)) { fprintf(stderr, "gencnval: error finishing output file - %s\n", u_errorName(errorCode)); exit(errorCode); } /* clean up tags */ for (i = 0; i < MAX_TAG_COUNT; i++) { for (n = 0; n < MAX_CONV_COUNT; n++) { if (tags[i].aliasList[n].aliases!=NULL) { uprv_free(tags[i].aliasList[n].aliases); } } } return 0; }
U_CAPI void U_EXPORT2 createCommonDataFile(const char *destDir, const char *name, const char *entrypointName, const char *type, const char *source, const char *copyRight, const char *dataFile, uint32_t max_size, UBool sourceTOC, UBool verbose, char *gencmnFileName) { static char buffer[4096]; char *line; char *linePtr; char *s = NULL; UErrorCode errorCode=U_ZERO_ERROR; uint32_t i, fileOffset, basenameOffset, length, nread; FileStream *in, *file; line = (char *)uprv_malloc(sizeof(char) * LINE_BUFFER_SIZE); if (line == NULL) { fprintf(stderr, "gencmn: unable to allocate memory for line buffer of size %d\n", LINE_BUFFER_SIZE); exit(U_MEMORY_ALLOCATION_ERROR); } linePtr = line; maxSize = max_size; if (destDir == NULL) { destDir = u_getDataDirectory(); } if (name == NULL) { name = COMMON_DATA_NAME; } if (type == NULL) { type = DATA_TYPE; } if (source == NULL) { source = "."; } if (dataFile == NULL) { in = T_FileStream_stdin(); } else { in = T_FileStream_open(dataFile, "r"); if(in == NULL) { fprintf(stderr, "gencmn: unable to open input file %s\n", dataFile); exit(U_FILE_ACCESS_ERROR); } } if (verbose) { if(sourceTOC) { printf("generating %s_%s.c (table of contents source file)\n", name, type); } else { printf("generating %s.%s (common data file with table of contents)\n", name, type); } } /* read the list of files and get their lengths */ while((s != NULL && *s != 0) || (s=T_FileStream_readLine(in, (line=linePtr), LINE_BUFFER_SIZE))!=NULL) { /* remove trailing newline characters and parse space separated items */ if (s != NULL && *s != 0) { line=s; } else { s=line; } while(*s!=0) { if(*s==' ') { *s=0; ++s; break; } else 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), name, source, sourceTOC, verbose); } uprv_free(linePtr); if(in!=T_FileStream_stdin()) { T_FileStream_close(in); } if(fileCount==0) { fprintf(stderr, "gencmn: no files listed in %s\n", dataFile == NULL ? "<stdin>" : dataFile); return; } /* 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(destDir, type, name, &dataInfo, copyRight == NULL ? U_COPYRIGHT_STRING : copyRight, &errorCode); if(U_FAILURE(errorCode)) { fprintf(stderr, "gencmn: udata_create(-d %s -n %s -t %s) failed - %s\n", destDir, name, type, 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, destDir); s=filename+uprv_strlen(filename); if(s>filename && *(s-1)!=U_FILE_SEP_CHAR) { *s++=U_FILE_SEP_CHAR; } uprv_strcpy(s, name); if(*(type)!=0) { s+=uprv_strlen(s); *s++='_'; uprv_strcpy(s, type); } s+=uprv_strlen(s); uprv_strcpy(s, ".c"); /* open the output file */ out=T_FileStream_open(filename, "w"); if (gencmnFileName != NULL) { uprv_strcpy(gencmnFileName, filename); } if(out==NULL) { fprintf(stderr, "gencmn: unable to open .c output file %s\n", filename); exit(U_FILE_ACCESS_ERROR); } /* 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 (%d files) */\n", name, type, fileCount); 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); } }
U_CAPI UCHARBUF* U_EXPORT2 ucbuf_open(const char* fileName,const char** cp,UBool showWarning, UBool buffered, UErrorCode* error){ FileStream* in = NULL; int32_t fileSize=0; const char* knownCp; if(error==NULL || U_FAILURE(*error)){ return NULL; } if(cp==NULL || fileName==NULL){ *error = U_ILLEGAL_ARGUMENT_ERROR; return FALSE; } if (!uprv_strcmp(fileName, "-")) { in = T_FileStream_stdin(); }else{ in = T_FileStream_open(fileName, "rb"); } if(in!=NULL){ UCHARBUF* buf =(UCHARBUF*) uprv_malloc(sizeof(UCHARBUF)); fileSize = T_FileStream_size(in); if(buf == NULL){ *error = U_MEMORY_ALLOCATION_ERROR; T_FileStream_close(in); return NULL; } buf->in=in; buf->conv=NULL; buf->showWarning = showWarning; buf->isBuffered = buffered; buf->signatureLength=0; if(*cp==NULL || **cp=='\0'){ /* don't have code page name... try to autodetect */ ucbuf_autodetect_fs(in,cp,&buf->conv,&buf->signatureLength,error); }else if(ucbuf_isCPKnown(*cp)){ /* discard BOM */ ucbuf_autodetect_fs(in,&knownCp,&buf->conv,&buf->signatureLength,error); } if(U_SUCCESS(*error) && buf->conv==NULL) { buf->conv=ucnv_open(*cp,error); } if(U_FAILURE(*error)){ ucnv_close(buf->conv); uprv_free(buf); T_FileStream_close(in); return NULL; } if((buf->conv==NULL) && (buf->showWarning==TRUE)){ fprintf(stderr,"###WARNING: No converter defined. Using codepage of system.\n"); } buf->remaining=fileSize-buf->signatureLength; if(buf->isBuffered){ buf->bufCapacity=MAX_U_BUF; }else{ buf->bufCapacity=buf->remaining+buf->signatureLength+1/*for terminating nul*/; } buf->buffer=(UChar*) uprv_malloc(U_SIZEOF_UCHAR * buf->bufCapacity ); if (buf->buffer == NULL) { *error = U_MEMORY_ALLOCATION_ERROR; ucbuf_close(buf); return NULL; } buf->currentPos=buf->buffer; buf->bufLimit=buf->buffer; if(U_FAILURE(*error)){ fprintf(stderr, "Could not open codepage [%s]: %s\n", *cp, u_errorName(*error)); ucbuf_close(buf); return NULL; } ucbuf_fillucbuf(buf,error); if(U_FAILURE(*error)){ ucbuf_close(buf); return NULL; } return buf; } *error =U_FILE_ACCESS_ERROR; return NULL; }
static void addFile(const char *filename, const char *name, const char *source, UBool sourceTOC, UBool verbose) { char *s; uint32_t length; char *fullPath = NULL; if(fileCount==fileMax) { fileMax += CHUNK_FILE_COUNT; files = uprv_realloc(files, fileMax*sizeof(files[0])); /* note: never freed. */ if(files==NULL) { fprintf(stderr, "pkgdata/gencmn: Could not allocate %u bytes for %d files\n", (unsigned int)(fileMax*sizeof(files[0])), fileCount); exit(U_MEMORY_ALLOCATION_ERROR); } } if(!sourceTOC) { FileStream *file; if(uprv_pathIsAbsolute(filename)) { fprintf(stderr, "gencmn: Error: absolute path encountered. Old style paths are not supported. Use relative paths such as 'fur.res' or 'translit%cfur.res'.\n\tBad path: '%s'\n", U_FILE_SEP_CHAR, filename); exit(U_ILLEGAL_ARGUMENT_ERROR); } fullPath = pathToFullPath(filename, source); /* store the pathname */ length = (uint32_t)(uprv_strlen(filename) + 1 + uprv_strlen(name) + 1); s=allocString(length); uprv_strcpy(s, name); uprv_strcat(s, U_TREE_ENTRY_SEP_STRING); uprv_strcat(s, filename); /* get the basename */ fixDirToTreePath(s); files[fileCount].basename=s; files[fileCount].basenameLength=length; files[fileCount].pathname=fullPath; basenameTotal+=length; /* try to open the file */ file=T_FileStream_open(fullPath, "rb"); if(file==NULL) { fprintf(stderr, "gencmn: unable to open listed file %s\n", fullPath); exit(U_FILE_ACCESS_ERROR); } /* get the file length */ length=T_FileStream_size(file); if(T_FileStream_error(file) || length<=20) { fprintf(stderr, "gencmn: unable to get length of listed file %s\n", fullPath); exit(U_FILE_ACCESS_ERROR); } T_FileStream_close(file); /* do not add files that are longer than maxSize */ if(maxSize && length>maxSize) { if (verbose) { printf("%s ignored (size %ld > %ld)\n", fullPath, (long)length, (long)maxSize); } return; } files[fileCount].fileSize=length; } else { char *t; /* get and store the basename */ /* need to include the package name */ length = (uint32_t)(uprv_strlen(filename) + 1 + uprv_strlen(name) + 1); s=allocString(length); uprv_strcpy(s, name); uprv_strcat(s, U_TREE_ENTRY_SEP_STRING); uprv_strcat(s, filename); fixDirToTreePath(s); files[fileCount].basename=s; /* turn the basename into an entry point name and store in the pathname field */ t=files[fileCount].pathname=allocString(length); while(--length>0) { if(*s=='.' || *s=='-' || *s=='/') { *t='_'; } else { *t=*s; } ++s; ++t; } *t=0; } ++fileCount; }
U_CAPI void U_EXPORT2 writeAssemblyCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optFilename, char *outFilePath) { uint32_t column = MAX_COLUMN; char entry[64]; uint32_t buffer[1024]; char *bufferStr = (char *)buffer; FileStream *in, *out; size_t i, length; in=T_FileStream_open(filename, "rb"); if(in==NULL) { fprintf(stderr, "genccode: unable to open input file %s\n", filename); exit(U_FILE_ACCESS_ERROR); } getOutFilename(filename, destdir, bufferStr, entry, ".S", optFilename); out=T_FileStream_open(bufferStr, "w"); if(out==NULL) { fprintf(stderr, "genccode: unable to open output file %s\n", bufferStr); exit(U_FILE_ACCESS_ERROR); } if (outFilePath != NULL) { uprv_strcpy(outFilePath, bufferStr); } #ifdef WINDOWS_WITH_GNUC /* Need to fix the file seperator character when using MinGW. */ swapFileSepChar(outFilePath, U_FILE_SEP_CHAR, '/'); #endif if(optEntryPoint != NULL) { uprv_strcpy(entry, optEntryPoint); uprv_strcat(entry, "_dat"); } /* turn dashes or dots in the entry name into underscores */ length=uprv_strlen(entry); for(i=0; i<length; ++i) { if(entry[i]=='-' || entry[i]=='.') { entry[i]='_'; } } sprintf(bufferStr, assemblyHeader[assemblyHeaderIndex].header, entry, entry, entry, entry, entry, entry, entry, entry); T_FileStream_writeLine(out, bufferStr); T_FileStream_writeLine(out, assemblyHeader[assemblyHeaderIndex].beginLine); for(;;) { length=T_FileStream_read(in, buffer, sizeof(buffer)); if(length==0) { break; } if (length != sizeof(buffer)) { /* pad with extra 0's when at the end of the file */ for(i=0; i < (length % sizeof(uint32_t)); ++i) { buffer[length+i] = 0; } } for(i=0; i<(length/sizeof(buffer[0])); i++) { column = write32(out, buffer[i], column); } } T_FileStream_writeLine(out, "\n"); sprintf(bufferStr, assemblyHeader[assemblyHeaderIndex].footer, entry, entry, entry, entry, entry, entry, entry, entry); T_FileStream_writeLine(out, bufferStr); if(T_FileStream_error(in)) { fprintf(stderr, "genccode: file read error while generating from file %s\n", filename); exit(U_FILE_ACCESS_ERROR); } if(T_FileStream_error(out)) { fprintf(stderr, "genccode: file write error while generating from file %s\n", filename); exit(U_FILE_ACCESS_ERROR); } T_FileStream_close(out); T_FileStream_close(in); }
extern int main(int argc, char *argv[]) { const char *pname, *sourcePath, *destPath, *inFilename, *outFilename, *outComment; char outType; UBool isHelp, isModified, isPackage; int result = 0; Package *pkg, *listPkg, *addListPkg; U_MAIN_INIT_ARGS(argc, argv); /* get the program basename */ pname=findBasename(argv[0]); argc=u_parseArgs(argc, argv, UPRV_LENGTHOF(options), options); isHelp=options[OPT_HELP_H].doesOccur || options[OPT_HELP_QUESTION_MARK].doesOccur; if(isHelp) { printUsage(pname, TRUE); return U_ZERO_ERROR; } pkg=new Package; if(pkg==NULL) { fprintf(stderr, "icupkg: not enough memory\n"); return U_MEMORY_ALLOCATION_ERROR; } isModified=FALSE; int autoPrefix=0; if(options[OPT_AUTO_TOC_PREFIX].doesOccur) { pkg->setAutoPrefix(); ++autoPrefix; } if(options[OPT_AUTO_TOC_PREFIX_WITH_TYPE].doesOccur) { if(options[OPT_TOC_PREFIX].doesOccur) { fprintf(stderr, "icupkg: --auto_toc_prefix_with_type and also --toc_prefix\n"); printUsage(pname, FALSE); return U_ILLEGAL_ARGUMENT_ERROR; } pkg->setAutoPrefixWithType(); ++autoPrefix; } if(argc<2 || 3<argc || autoPrefix>1) { printUsage(pname, FALSE); return U_ILLEGAL_ARGUMENT_ERROR; } if(options[OPT_SOURCEDIR].doesOccur) { sourcePath=options[OPT_SOURCEDIR].value; } else { // work relative to the current working directory sourcePath=NULL; } if(options[OPT_DESTDIR].doesOccur) { destPath=options[OPT_DESTDIR].value; } else { // work relative to the current working directory destPath=NULL; } if(0==strcmp(argv[1], "new")) { if(autoPrefix) { fprintf(stderr, "icupkg: --auto_toc_prefix[_with_type] but no input package\n"); printUsage(pname, FALSE); return U_ILLEGAL_ARGUMENT_ERROR; } inFilename=NULL; isPackage=TRUE; } else { inFilename=argv[1]; if(isPackageName(inFilename)) { pkg->readPackage(inFilename); isPackage=TRUE; } else { /* swap a single file (icuswap replacement) rather than work on a package */ pkg->addFile(sourcePath, inFilename); isPackage=FALSE; } } if(argc>=3) { outFilename=argv[2]; if(0!=strcmp(argv[1], argv[2])) { isModified=TRUE; } } else if(isPackage) { outFilename=NULL; } else /* !isPackage */ { outFilename=inFilename; isModified=(UBool)(sourcePath!=destPath); } /* parse the output type option */ if(options[OPT_OUT_TYPE].doesOccur) { const char *type=options[OPT_OUT_TYPE].value; if(type[0]==0 || type[1]!=0) { /* the type must be exactly one letter */ printUsage(pname, FALSE); return U_ILLEGAL_ARGUMENT_ERROR; } outType=type[0]; switch(outType) { case 'l': case 'b': case 'e': break; default: printUsage(pname, FALSE); return U_ILLEGAL_ARGUMENT_ERROR; } /* * Set the isModified flag if the output type differs from the * input package type. * If we swap a single file, just assume that we are modifying it. * The Package class does not give us access to the item and its type. */ isModified|=(UBool)(!isPackage || outType!=pkg->getInType()); } else if(isPackage) { outType=pkg->getInType(); // default to input type } else /* !isPackage: swap single file */ { outType=0; /* tells extractItem() to not swap */ } if(options[OPT_WRITEPKG].doesOccur) { isModified=TRUE; } if(!isPackage) { /* * icuswap tool replacement: Only swap a single file. * Check that irrelevant options are not set. */ if( options[OPT_COMMENT].doesOccur || options[OPT_COPYRIGHT].doesOccur || options[OPT_MATCHMODE].doesOccur || options[OPT_REMOVE_LIST].doesOccur || options[OPT_ADD_LIST].doesOccur || options[OPT_EXTRACT_LIST].doesOccur || options[OPT_LIST_ITEMS].doesOccur ) { printUsage(pname, FALSE); return U_ILLEGAL_ARGUMENT_ERROR; } if(isModified) { pkg->extractItem(destPath, outFilename, 0, outType); } delete pkg; return result; } /* Work with a package. */ if(options[OPT_COMMENT].doesOccur) { outComment=options[OPT_COMMENT].value; } else if(options[OPT_COPYRIGHT].doesOccur) { outComment=U_COPYRIGHT_STRING; } else { outComment=NULL; } if(options[OPT_MATCHMODE].doesOccur) { if(0==strcmp(options[OPT_MATCHMODE].value, "noslash")) { pkg->setMatchMode(Package::MATCH_NOSLASH); } else { printUsage(pname, FALSE); return U_ILLEGAL_ARGUMENT_ERROR; } } /* remove items */ if(options[OPT_REMOVE_LIST].doesOccur) { listPkg=new Package(); if(listPkg==NULL) { fprintf(stderr, "icupkg: not enough memory\n"); exit(U_MEMORY_ALLOCATION_ERROR); } if(readList(NULL, options[OPT_REMOVE_LIST].value, FALSE, listPkg)) { pkg->removeItems(*listPkg); delete listPkg; isModified=TRUE; } else { printUsage(pname, FALSE); return U_ILLEGAL_ARGUMENT_ERROR; } } /* * add items * use a separate Package so that its memory and items stay around * as long as the main Package */ addListPkg=NULL; if(options[OPT_ADD_LIST].doesOccur) { addListPkg=new Package(); if(addListPkg==NULL) { fprintf(stderr, "icupkg: not enough memory\n"); exit(U_MEMORY_ALLOCATION_ERROR); } if(readList(sourcePath, options[OPT_ADD_LIST].value, TRUE, addListPkg)) { pkg->addItems(*addListPkg); // delete addListPkg; deferred until after writePackage() isModified=TRUE; } else { printUsage(pname, FALSE); return U_ILLEGAL_ARGUMENT_ERROR; } } /* extract items */ if(options[OPT_EXTRACT_LIST].doesOccur) { listPkg=new Package(); if(listPkg==NULL) { fprintf(stderr, "icupkg: not enough memory\n"); exit(U_MEMORY_ALLOCATION_ERROR); } if(readList(NULL, options[OPT_EXTRACT_LIST].value, FALSE, listPkg)) { pkg->extractItems(destPath, *listPkg, outType); delete listPkg; } else { printUsage(pname, FALSE); return U_ILLEGAL_ARGUMENT_ERROR; } } /* list items */ if(options[OPT_LIST_ITEMS].doesOccur) { int32_t i; if (options[OPT_LIST_FILE].doesOccur) { FileStream *out; out = T_FileStream_open(options[OPT_LIST_FILE].value, "w"); if (out != NULL) { for(i=0; i<pkg->getItemCount(); ++i) { T_FileStream_writeLine(out, pkg->getItem(i)->name); T_FileStream_writeLine(out, "\n"); } T_FileStream_close(out); } else { return U_ILLEGAL_ARGUMENT_ERROR; } } else { for(i=0; i<pkg->getItemCount(); ++i) { fprintf(stdout, "%s\n", pkg->getItem(i)->name); } } } /* check dependencies between items */ if(!pkg->checkDependencies()) { /* some dependencies are not fulfilled */ return U_MISSING_RESOURCE_ERROR; } /* write the output .dat package if there are any modifications */ if(isModified) { char outFilenameBuffer[1024]; // for auto-generated output filename, if necessary if(outFilename==NULL || outFilename[0]==0) { if(inFilename==NULL || inFilename[0]==0) { fprintf(stderr, "icupkg: unable to auto-generate an output filename if there is no input filename\n"); exit(U_ILLEGAL_ARGUMENT_ERROR); } /* * auto-generate a filename: * copy the inFilename, * and if the last basename character matches the input file's type, * then replace it with the output file's type */ char suffix[6]="?.dat"; char *s; suffix[0]=pkg->getInType(); strcpy(outFilenameBuffer, inFilename); s=strchr(outFilenameBuffer, 0); if((s-outFilenameBuffer)>5 && 0==memcmp(s-5, suffix, 5)) { *(s-5)=outType; } outFilename=outFilenameBuffer; } if(options[OPT_TOC_PREFIX].doesOccur) { pkg->setPrefix(options[OPT_TOC_PREFIX].value); } result = writePackageDatFile(outFilename, outComment, NULL, NULL, pkg, outType); } delete addListPkg; delete pkg; return result; }
U_CAPI void U_EXPORT2 u_parseDelimitedFile(const char *filename, char delimiter, char *fields[][2], int32_t fieldCount, UParseLineFn *lineFn, void *context, UErrorCode *pErrorCode) { FileStream *file; char line[300]; char *start, *limit; int32_t i, length; if(U_FAILURE(*pErrorCode)) { return; } if(fields==NULL || lineFn==NULL || fieldCount<=0) { *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return; } if(filename==NULL || *filename==0 || (*filename=='-' && filename[1]==0)) { filename=NULL; file=T_FileStream_stdin(); } else { file=T_FileStream_open(filename, "r"); } if(file==NULL) { *pErrorCode=U_FILE_ACCESS_ERROR; return; } while(T_FileStream_readLine(file, line, sizeof(line))!=NULL) { /* remove trailing newline characters */ length=(int32_t)(u_rtrim(line)-line); /* * detect a line with # @missing: * start parsing after that, or else from the beginning of the line * set the default warning for @missing lines */ start=(char *)getMissingLimit(line); if(start==line) { *pErrorCode=U_ZERO_ERROR; } else { *pErrorCode=U_USING_DEFAULT_WARNING; } /* skip this line if it is empty or a comment */ if(*start==0 || *start=='#') { continue; } /* remove in-line comments */ limit=uprv_strchr(start, '#'); if(limit!=NULL) { /* get white space before the pound sign */ while(limit>start && U_IS_INV_WHITESPACE(*(limit-1))) { --limit; } /* truncate the line */ *limit=0; } /* skip lines with only whitespace */ if(u_skipWhitespace(start)[0]==0) { continue; } /* for each field, call the corresponding field function */ for(i=0; i<fieldCount; ++i) { /* set the limit pointer of this field */ limit=start; while(*limit!=delimiter && *limit!=0) { ++limit; } /* set the field start and limit in the fields array */ fields[i][0]=start; fields[i][1]=limit; /* set start to the beginning of the next field, if any */ start=limit; if(*start!=0) { ++start; } else if(i+1<fieldCount) { *pErrorCode=U_PARSE_ERROR; limit=line+length; i=fieldCount; break; } } /* error in a field function? */ if(U_FAILURE(*pErrorCode)) { break; } /* call the field function */ lineFn(context, fields, fieldCount, pErrorCode); if(U_FAILURE(*pErrorCode)) { break; } } if(filename!=NULL) { T_FileStream_close(file); } }
int main(int argc, char* argv[]) { UErrorCode status = U_ZERO_ERROR; const char *arg = NULL; const char *outputDir = NULL; /* NULL = no output directory, use current */ const char *inputDir = NULL; const char *encoding = ""; int i; UBool illegalArg = FALSE; U_MAIN_INIT_ARGS(argc, argv); options[JAVA_PACKAGE].value = "com.ibm.icu.impl.data"; options[BUNDLE_NAME].value = "LocaleElements"; argc = u_parseArgs(argc, argv, UPRV_LENGTHOF(options), options); /* error handling, printing usage message */ if(argc<0) { fprintf(stderr, "%s: error in command line argument \"%s\"\n", argv[0], argv[-argc]); illegalArg = TRUE; } else if(argc<2) { illegalArg = TRUE; } if(options[WRITE_POOL_BUNDLE].doesOccur && options[USE_POOL_BUNDLE].doesOccur) { fprintf(stderr, "%s: cannot combine --writePoolBundle and --usePoolBundle\n", argv[0]); illegalArg = TRUE; } if(options[FORMAT_VERSION].doesOccur) { const char *s = options[FORMAT_VERSION].value; if(uprv_strlen(s) != 1 || (s[0] < '1' && '3' < s[0])) { fprintf(stderr, "%s: unsupported --formatVersion %s\n", argv[0], s); illegalArg = TRUE; } else if(s[0] == '1' && (options[WRITE_POOL_BUNDLE].doesOccur || options[USE_POOL_BUNDLE].doesOccur) ) { fprintf(stderr, "%s: cannot combine --formatVersion 1 with --writePoolBundle or --usePoolBundle\n", argv[0]); illegalArg = TRUE; } else { setFormatVersion(s[0] - '0'); } } if((options[JAVA_PACKAGE].doesOccur || options[BUNDLE_NAME].doesOccur) && !options[WRITE_JAVA].doesOccur) { fprintf(stderr, "%s error: command line argument --java-package or --bundle-name " "without --write-java\n", argv[0]); illegalArg = TRUE; } if(options[VERSION].doesOccur) { fprintf(stderr, "%s version %s (ICU version %s).\n" "%s\n", argv[0], GENRB_VERSION, U_ICU_VERSION, U_COPYRIGHT_STRING); if(!illegalArg) { return U_ZERO_ERROR; } } if(illegalArg || options[HELP1].doesOccur || options[HELP2].doesOccur) { /* * Broken into chunks because the C89 standard says the minimum * required supported string length is 509 bytes. */ fprintf(stderr, "Usage: %s [OPTIONS] [FILES]\n" "\tReads the list of resource bundle source files and creates\n" "\tbinary version of resource bundles (.res files)\n", argv[0]); fprintf(stderr, "Options:\n" "\t-h or -? or --help this usage text\n" "\t-q or --quiet do not display warnings\n" "\t-v or --verbose print extra information when processing files\n" "\t-V or --version prints out version number and exits\n" "\t-c or --copyright include copyright notice\n"); fprintf(stderr, "\t-e or --encoding encoding of source files\n" "\t-d of --destdir destination directory, followed by the path, defaults to %s\n" "\t-s or --sourcedir source directory for files followed by path, defaults to %s\n" "\t-i or --icudatadir directory for locating any needed intermediate data files,\n" "\t followed by path, defaults to %s\n", u_getDataDirectory(), u_getDataDirectory(), u_getDataDirectory()); fprintf(stderr, "\t-j or --write-java write a Java ListResourceBundle for ICU4J, followed by optional encoding\n" "\t defaults to ASCII and \\uXXXX format.\n" "\t --java-package For --write-java: package name for writing the ListResourceBundle,\n" "\t defaults to com.ibm.icu.impl.data\n"); fprintf(stderr, "\t-b or --bundle-name For --write-java: root resource bundle name for writing the ListResourceBundle,\n" "\t defaults to LocaleElements\n" "\t-x or --write-xliff write an XLIFF file for the resource bundle. Followed by\n" "\t an optional output file name.\n" "\t-k or --strict use pedantic parsing of syntax\n" /*added by Jing*/ "\t-l or --language for XLIFF: language code compliant with BCP 47.\n"); fprintf(stderr, "\t-C or --noBinaryCollation do not generate binary collation image;\n" "\t makes .res file smaller but collator instantiation much slower;\n" "\t maintains ability to get tailoring rules\n" "\t-R or --omitCollationRules do not include collation (tailoring) rules;\n" "\t makes .res file smaller and maintains collator instantiation speed\n" "\t but tailoring rules will not be available (they are rarely used)\n"); fprintf(stderr, "\t --formatVersion write a .res file compatible with the requested formatVersion (single digit);\n" "\t for example, --formatVersion 1\n"); fprintf(stderr, "\t --writePoolBundle write a pool.res file with all of the keys of all input bundles\n" "\t --usePoolBundle [path-to-pool.res] point to keys from the pool.res keys pool bundle if they are available there;\n" "\t makes .res files smaller but dependent on the pool bundle\n" "\t (--writePoolBundle and --usePoolBundle cannot be combined)\n"); return illegalArg ? U_ILLEGAL_ARGUMENT_ERROR : U_ZERO_ERROR; } if(options[VERBOSE].doesOccur) { setVerbose(TRUE); } if(options[QUIET].doesOccur) { setShowWarning(FALSE); } if(options[STRICT].doesOccur) { setStrict(TRUE); } if(options[COPYRIGHT].doesOccur){ setIncludeCopyright(TRUE); } if(options[SOURCEDIR].doesOccur) { inputDir = options[SOURCEDIR].value; } if(options[DESTDIR].doesOccur) { outputDir = options[DESTDIR].value; } if(options[ENCODING].doesOccur) { encoding = options[ENCODING].value; } if(options[ICUDATADIR].doesOccur) { u_setDataDirectory(options[ICUDATADIR].value); } /* Initialize ICU */ u_init(&status); if (U_FAILURE(status) && status != U_FILE_ACCESS_ERROR) { /* Note: u_init() will try to open ICU property data. * failures here are expected when building ICU from scratch. * ignore them. */ fprintf(stderr, "%s: can not initialize ICU. status = %s\n", argv[0], u_errorName(status)); exit(1); } status = U_ZERO_ERROR; if(options[WRITE_JAVA].doesOccur) { write_java = TRUE; outputEnc = options[WRITE_JAVA].value; } if(options[WRITE_XLIFF].doesOccur) { write_xliff = TRUE; if(options[WRITE_XLIFF].value != NULL){ xliffOutputFileName = options[WRITE_XLIFF].value; } } initParser(); /*added by Jing*/ if(options[LANGUAGE].doesOccur) { language = options[LANGUAGE].value; } LocalPointer<SRBRoot> newPoolBundle; if(options[WRITE_POOL_BUNDLE].doesOccur) { newPoolBundle.adoptInsteadAndCheckErrorCode(new SRBRoot(NULL, TRUE, status), status); if(U_FAILURE(status)) { fprintf(stderr, "unable to create an empty bundle for the pool keys: %s\n", u_errorName(status)); return status; } else { const char *poolResName = "pool.res"; char *nameWithoutSuffix = static_cast<char *>(uprv_malloc(uprv_strlen(poolResName) + 1)); if (nameWithoutSuffix == NULL) { fprintf(stderr, "out of memory error\n"); return U_MEMORY_ALLOCATION_ERROR; } uprv_strcpy(nameWithoutSuffix, poolResName); *uprv_strrchr(nameWithoutSuffix, '.') = 0; newPoolBundle->fLocale = nameWithoutSuffix; } } if(options[USE_POOL_BUNDLE].doesOccur) { const char *poolResName = "pool.res"; FileStream *poolFile; int32_t poolFileSize; int32_t indexLength; /* * TODO: Consolidate inputDir/filename handling from main() and processFile() * into a common function, and use it here as well. * Try to create toolutil functions for dealing with dir/filenames and * loading ICU data files without udata_open(). * Share code with icupkg? * Also, make_res_filename() seems to be unused. Review and remove. */ CharString poolFileName; if (options[USE_POOL_BUNDLE].value!=NULL) { poolFileName.append(options[USE_POOL_BUNDLE].value, status); } else if (inputDir) { poolFileName.append(inputDir, status); } poolFileName.appendPathPart(poolResName, status); if (U_FAILURE(status)) { return status; } poolFile = T_FileStream_open(poolFileName.data(), "rb"); if (poolFile == NULL) { fprintf(stderr, "unable to open pool bundle file %s\n", poolFileName.data()); return 1; } poolFileSize = T_FileStream_size(poolFile); if (poolFileSize < 32) { fprintf(stderr, "the pool bundle file %s is too small\n", poolFileName.data()); return 1; } poolBundle.fBytes = new uint8_t[(poolFileSize + 15) & ~15]; if (poolFileSize > 0 && poolBundle.fBytes == NULL) { fprintf(stderr, "unable to allocate memory for the pool bundle file %s\n", poolFileName.data()); return U_MEMORY_ALLOCATION_ERROR; } UDataSwapper *ds; const DataHeader *header; int32_t bytesRead = T_FileStream_read(poolFile, poolBundle.fBytes, poolFileSize); if (bytesRead != poolFileSize) { fprintf(stderr, "unable to read the pool bundle file %s\n", poolFileName.data()); return 1; } /* * Swap the pool bundle so that a single checked-in file can be used. * The swapper functions also test that the data looks like * a well-formed .res file. */ ds = udata_openSwapperForInputData(poolBundle.fBytes, bytesRead, U_IS_BIG_ENDIAN, U_CHARSET_FAMILY, &status); if (U_FAILURE(status)) { fprintf(stderr, "udata_openSwapperForInputData(pool bundle %s) failed: %s\n", poolFileName.data(), u_errorName(status)); return status; } ures_swap(ds, poolBundle.fBytes, bytesRead, poolBundle.fBytes, &status); udata_closeSwapper(ds); if (U_FAILURE(status)) { fprintf(stderr, "ures_swap(pool bundle %s) failed: %s\n", poolFileName.data(), u_errorName(status)); return status; } header = (const DataHeader *)poolBundle.fBytes; if (header->info.formatVersion[0] < 2) { fprintf(stderr, "invalid format of pool bundle file %s\n", poolFileName.data()); return U_INVALID_FORMAT_ERROR; } const int32_t *pRoot = (const int32_t *)( (const char *)header + header->dataHeader.headerSize); poolBundle.fIndexes = pRoot + 1; indexLength = poolBundle.fIndexes[URES_INDEX_LENGTH] & 0xff; if (indexLength <= URES_INDEX_POOL_CHECKSUM) { fprintf(stderr, "insufficient indexes[] in pool bundle file %s\n", poolFileName.data()); return U_INVALID_FORMAT_ERROR; } int32_t keysBottom = 1 + indexLength; int32_t keysTop = poolBundle.fIndexes[URES_INDEX_KEYS_TOP]; poolBundle.fKeys = (const char *)(pRoot + keysBottom); poolBundle.fKeysLength = (keysTop - keysBottom) * 4; poolBundle.fChecksum = poolBundle.fIndexes[URES_INDEX_POOL_CHECKSUM]; for (i = 0; i < poolBundle.fKeysLength; ++i) { if (poolBundle.fKeys[i] == 0) { ++poolBundle.fKeysCount; } } // 16BitUnits[] begins with strings-v2. // The strings-v2 may optionally be terminated by what looks like // an explicit string length that exceeds the number of remaining 16-bit units. int32_t stringUnitsLength = (poolBundle.fIndexes[URES_INDEX_16BIT_TOP] - keysTop) * 2; if (stringUnitsLength >= 2 && getFormatVersion() >= 3) { poolBundle.fStrings = new PseudoListResource(NULL, status); if (poolBundle.fStrings == NULL) { fprintf(stderr, "unable to allocate memory for the pool bundle strings %s\n", poolFileName.data()); return U_MEMORY_ALLOCATION_ERROR; } // The PseudoListResource constructor call did not allocate further memory. assert(U_SUCCESS(status)); const UChar *p = (const UChar *)(pRoot + keysTop); int32_t remaining = stringUnitsLength; do { int32_t first = *p; int8_t numCharsForLength; int32_t length; if (!U16_IS_TRAIL(first)) { // NUL-terminated numCharsForLength = 0; for (length = 0; length < remaining && p[length] != 0; ++length) {} } else if (first < 0xdfef) { numCharsForLength = 1; length = first & 0x3ff; } else if (first < 0xdfff && remaining >= 2) { numCharsForLength = 2; length = ((first - 0xdfef) << 16) | p[1]; } else if (first == 0xdfff && remaining >= 3) { numCharsForLength = 3; length = ((int32_t)p[1] << 16) | p[2]; } else { break; // overrun } // Check for overrun before changing remaining, // so that it is always accurate after the loop body. if ((numCharsForLength + length) >= remaining || p[numCharsForLength + length] != 0) { break; // overrun or explicitly terminated } int32_t poolStringIndex = stringUnitsLength - remaining; // Maximum pool string index when suffix-sharing the last character. int32_t maxStringIndex = poolStringIndex + numCharsForLength + length - 1; if (maxStringIndex >= RES_MAX_OFFSET) { // pool string index overrun break; } p += numCharsForLength; remaining -= numCharsForLength; if (length != 0) { StringResource *sr = new StringResource(poolStringIndex, numCharsForLength, p, length, status); if (sr == NULL) { fprintf(stderr, "unable to allocate memory for a pool bundle string %s\n", poolFileName.data()); return U_MEMORY_ALLOCATION_ERROR; } poolBundle.fStrings->add(sr); poolBundle.fStringIndexLimit = maxStringIndex + 1; // The StringResource constructor did not allocate further memory. assert(U_SUCCESS(status)); } p += length + 1; remaining -= length + 1; } while (remaining > 0); if (poolBundle.fStrings->fCount == 0) { delete poolBundle.fStrings; poolBundle.fStrings = NULL; } } T_FileStream_close(poolFile); setUsePoolBundle(TRUE); if (isVerbose() && poolBundle.fStrings != NULL) { printf("number of shared strings: %d\n", (int)poolBundle.fStrings->fCount); int32_t length = poolBundle.fStringIndexLimit + 1; // incl. last NUL printf("16-bit units for strings: %6d = %6d bytes\n", (int)length, (int)length * 2); } } if(!options[FORMAT_VERSION].doesOccur && getFormatVersion() == 3 && poolBundle.fStrings == NULL && !options[WRITE_POOL_BUNDLE].doesOccur) { // If we just default to formatVersion 3 // but there are no pool bundle strings to share // and we do not write a pool bundle, // then write formatVersion 2 which is just as good. setFormatVersion(2); } if(options[INCLUDE_UNIHAN_COLL].doesOccur) { puts("genrb option --includeUnihanColl ignored: \n" "CLDR 26/ICU 54 unihan data is small, except\n" "the ucadata-unihan.icu version of the collation root data\n" "is about 300kB larger than the ucadata-implicithan.icu version."); } if((argc-1)!=1) { printf("genrb number of files: %d\n", argc - 1); } /* generate the binary files */ for(i = 1; i < argc; ++i) { status = U_ZERO_ERROR; arg = getLongPathname(argv[i]); CharString theCurrentFileName; if (inputDir) { theCurrentFileName.append(inputDir, status); } theCurrentFileName.appendPathPart(arg, status); if (U_FAILURE(status)) { break; } gCurrentFileName = theCurrentFileName.data(); if (isVerbose()) { printf("Processing file \"%s\"\n", theCurrentFileName.data()); } processFile(arg, encoding, inputDir, outputDir, NULL, newPoolBundle.getAlias(), options[NO_BINARY_COLLATION].doesOccur, status); } poolBundle.close(); if(U_SUCCESS(status) && options[WRITE_POOL_BUNDLE].doesOccur) { char outputFileName[256]; newPoolBundle->write(outputDir, NULL, outputFileName, sizeof(outputFileName), status); if(U_FAILURE(status)) { fprintf(stderr, "unable to write the pool bundle: %s\n", u_errorName(status)); } } u_cleanup(); /* Dont return warnings as a failure */ if (U_SUCCESS(status)) { return 0; } return status; }
/* * Opens the given fileName and reads in the information storing the data in flagBuffer. */ U_CAPI int32_t U_EXPORT2 parseFlagsFile(const char *fileName, char **flagBuffer, int32_t flagBufferSize, const char ** flagNames, int32_t numOfFlags, UErrorCode *status) { char* buffer = NULL; char* tmpFlagBuffer = NULL; UBool allocateMoreSpace = FALSE; int32_t idx, i; int32_t result = 0; FileStream *f = T_FileStream_open(fileName, "r"); if (f == NULL) { *status = U_FILE_ACCESS_ERROR; goto parseFlagsFile_cleanup; } buffer = uprv_malloc(sizeof(char) * currentBufferSize); tmpFlagBuffer = uprv_malloc(sizeof(char) * flagBufferSize); if (buffer == NULL || tmpFlagBuffer == NULL) { *status = U_MEMORY_ALLOCATION_ERROR; goto parseFlagsFile_cleanup; } do { if (allocateMoreSpace) { allocateMoreSpace = FALSE; currentBufferSize *= 2; uprv_free(buffer); buffer = uprv_malloc(sizeof(char) * currentBufferSize); if (buffer == NULL) { *status = U_MEMORY_ALLOCATION_ERROR; goto parseFlagsFile_cleanup; } } for (i = 0; i < numOfFlags;) { if (T_FileStream_readLine(f, buffer, currentBufferSize) == NULL) { /* End of file reached. */ break; } if (buffer[0] == '#') { continue; } if (uprv_strlen(buffer) == (currentBufferSize - 1) && buffer[currentBufferSize-2] != '\n') { /* Allocate more space for buffer if it didnot read the entrire line */ allocateMoreSpace = TRUE; T_FileStream_rewind(f); break; } else { idx = extractFlag(buffer, currentBufferSize, tmpFlagBuffer, flagBufferSize, flagNames, numOfFlags, status); if (U_FAILURE(*status)) { if (*status == U_BUFFER_OVERFLOW_ERROR) { result = currentBufferSize; } else { result = -1; } break; } else { if (flagNames != NULL) { if (idx >= 0) { uprv_strcpy(flagBuffer[idx], tmpFlagBuffer); } else { /* No match found. Skip it. */ continue; } } else { uprv_strcpy(flagBuffer[i++], tmpFlagBuffer); } } } } } while (allocateMoreSpace && U_SUCCESS(*status)); parseFlagsFile_cleanup: uprv_free(tmpFlagBuffer); uprv_free(buffer); T_FileStream_close(f); if (U_FAILURE(*status)) { return -1; } if (U_SUCCESS(*status) && result == 0) { currentBufferSize = DEFAULT_BUFFER_SIZE; } return result; }
U_CAPI void U_EXPORT2 u_parseDelimitedFile(const char *filename, char delimiter, char *fields[][2], int32_t fieldCount, UParseLineFn *lineFn, void *context, UErrorCode *pErrorCode) { FileStream *file; char line[300]; char *start, *limit; int32_t i, length; if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { return; } if(fields==NULL || lineFn==NULL || fieldCount<=0) { *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return; } if(filename==NULL || *filename==0 || (*filename=='-' && filename[1]==0)) { filename=NULL; file=T_FileStream_stdin(); } else { file=T_FileStream_open(filename, "r"); } if(file==NULL) { *pErrorCode=U_FILE_ACCESS_ERROR; return; } while(T_FileStream_readLine(file, line, sizeof(line))!=NULL) { length=(int32_t)uprv_strlen(line); /* remove trailing newline characters */ while(length>0 && (line[length-1]=='\r' || line[length-1]=='\n')) { line[--length]=0; } /* skip this line if it is empty or a comment */ if(line[0]==0 || line[0]=='#') { continue; } /* remove in-line comments */ limit=uprv_strchr(line, '#'); if(limit!=NULL) { /* get white space before the pound sign */ while(limit>line && (*(limit-1)==' ' || *(limit-1)=='\t')) { --limit; } /* truncate the line */ *limit=0; } /* skip lines with only whitespace */ if(u_skipWhitespace(line)[0]==0) { continue; } /* for each field, call the corresponding field function */ start=line; for(i=0; i<fieldCount; ++i) { /* set the limit pointer of this field */ limit=start; while(*limit!=delimiter && *limit!=0) { ++limit; } /* set the field start and limit in the fields array */ fields[i][0]=start; fields[i][1]=limit; /* set start to the beginning of the next field, if any */ start=limit; if(*start!=0) { ++start; } else if(i+1<fieldCount) { *pErrorCode=U_PARSE_ERROR; limit=line+length; i=fieldCount; break; } } /* error in a field function? */ if(U_FAILURE(*pErrorCode)) { break; } /* call the field function */ lineFn(context, fields, fieldCount, pErrorCode); if(U_FAILURE(*pErrorCode)) { break; } } if(filename!=NULL) { T_FileStream_close(file); } }
void bundle_write_java(struct SRBRoot *bundle, const char *outputDir,const char* outputEnc, char *writtenFilename, int writtenFilenameLen, const char* packageName, const char* bundleName, UErrorCode *status) { char fileName[256] = {'\0'}; char className[256]={'\0'}; /*char constructor[1000] = { 0 };*/ /*UBool j1 =FALSE;*/ outDir = outputDir; start = TRUE; /* Reset the start indictor*/ bName = (bundleName==NULL) ? "LocaleElements" : bundleName; pName = (packageName==NULL)? "com.ibm.icu.impl.data" : packageName; uprv_strcpy(className, bName); srBundle = bundle; if(uprv_strcmp(srBundle->fLocale,"root")!=0){ uprv_strcat(className,"_"); uprv_strcat(className,srBundle->fLocale); } if(outputDir){ uprv_strcpy(fileName, outputDir); if(outputDir[uprv_strlen(outputDir)-1] !=U_FILE_SEP_CHAR){ uprv_strcat(fileName,U_FILE_SEP_STRING); } uprv_strcat(fileName,className); uprv_strcat(fileName,".java"); }else{ uprv_strcat(fileName,className); uprv_strcat(fileName,".java"); } if (writtenFilename) { uprv_strncpy(writtenFilename, fileName, writtenFilenameLen); } if (U_FAILURE(*status)) { return; } out= T_FileStream_open(fileName,"w"); if(out==NULL){ *status = U_FILE_ACCESS_ERROR; return; } if(getIncludeCopyright()){ T_FileStream_write(out, copyRight, (int32_t)uprv_strlen(copyRight)); T_FileStream_write(out, warningMsg, (int32_t)uprv_strlen(warningMsg)); } T_FileStream_write(out,"package ",(int32_t)uprv_strlen("package ")); T_FileStream_write(out,pName,(int32_t)uprv_strlen(pName)); T_FileStream_write(out,";\n\n",3); T_FileStream_write(out, javaClass, (int32_t)uprv_strlen(javaClass)); T_FileStream_write(out, className, (int32_t)uprv_strlen(className)); T_FileStream_write(out, javaClass1, (int32_t)uprv_strlen(javaClass1)); /* if(j1){ T_FileStream_write(out, javaClass1, (int32_t)uprv_strlen(javaClass1)); }else{ sprintf(constructor,javaClassICU,className); T_FileStream_write(out, constructor, (int32_t)uprv_strlen(constructor)); } */ if(outputEnc && *outputEnc!='\0'){ /* store the output encoding */ enc = outputEnc; conv=ucnv_open(enc,status); if(U_FAILURE(*status)){ return; } } res_write_java(bundle->fRoot, status); T_FileStream_write(out, closeClass, (int32_t)uprv_strlen(closeClass)); T_FileStream_close(out); ucnv_close(conv); }
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; }