diff --git a/icu4c/source/tools/pkgdata/pkgdata.cpp b/icu4c/source/tools/pkgdata/pkgdata.cpp index d9c2c62b8a2..a0e74830a47 100644 --- a/icu4c/source/tools/pkgdata/pkgdata.cpp +++ b/icu4c/source/tools/pkgdata/pkgdata.cpp @@ -751,46 +751,61 @@ static int32_t pkg_executeOptions(UPKGOptions *o) { static int32_t initializePkgDataFlags(UPKGOptions *o) { UErrorCode status = U_ZERO_ERROR; int32_t result = 0; + int32_t currentBufferSize = SMALL_BUFFER_MAX_SIZE; + /* Initialize pkgdataFlags */ pkgDataFlags = (char**)uprv_malloc(sizeof(char*) * PKGDATA_FLAGS_SIZE); - if (pkgDataFlags != NULL) { - for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) { - pkgDataFlags[i] = (char*)uprv_malloc(sizeof(char) * LARGE_BUFFER_MAX_SIZE); - if (pkgDataFlags[i] != NULL) { - pkgDataFlags[i][0] = 0; - } else { - fprintf(stderr,"Error allocating memory for pkgDataFlags.\n"); - return -1; - } - } - } else { - fprintf(stderr,"Error allocating memory for pkgDataFlags.\n"); - return -1; - } - if (o->options == NULL) { - return result; - } + /* If we run out of space, allocate more */ +#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN) + do { +#endif + if (pkgDataFlags != NULL) { + for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) { + pkgDataFlags[i] = (char*)uprv_malloc(sizeof(char) * currentBufferSize); + if (pkgDataFlags[i] != NULL) { + pkgDataFlags[i][0] = 0; + } else { + fprintf(stderr,"Error allocating memory for pkgDataFlags.\n"); + return -1; + } + } + } else { + fprintf(stderr,"Error allocating memory for pkgDataFlags.\n"); + return -1; + } + + if (o->options == NULL) { + return result; + } #if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN) - /* Read in options file. */ - if(o->verbose) { - fprintf(stdout, "# Reading options file %s\n", o->options); - } - parseFlagsFile(o->options, pkgDataFlags, LARGE_BUFFER_MAX_SIZE, (int32_t)PKGDATA_FLAGS_SIZE, &status); - if (U_FAILURE(status)) { - fprintf(stderr,"Unable to open or read \"%s\" option file. status = %s\n", o->options, u_errorName(status)); - return -1; - } -#endif - - if(o->verbose) { - fprintf(stdout, "# pkgDataFlags="); - for(int32_t i=0;i0)?',':' ',pkgDataFlags[i]); + /* Read in options file. */ + if(o->verbose) { + fprintf(stdout, "# Reading options file %s\n", o->options); } - fprintf(stdout, "\n"); - } + status = U_ZERO_ERROR; + parseFlagsFile(o->options, pkgDataFlags, currentBufferSize, (int32_t)PKGDATA_FLAGS_SIZE, &status); + if (status == U_BUFFER_OVERFLOW_ERROR) { + for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) { + uprv_free(pkgDataFlags[i]); + } + currentBufferSize *= 2; + } else if (U_FAILURE(status)) { + fprintf(stderr,"Unable to open or read \"%s\" option file. status = %s\n", o->options, u_errorName(status)); + return -1; + } +#endif + if(o->verbose) { + fprintf(stdout, "# pkgDataFlags="); + for(int32_t i=0;i0)?',':' ',pkgDataFlags[i]); + } + fprintf(stdout, "\n"); + } +#if !defined(WINDOWS_WITH_MSVC) || defined(USING_CYGWIN) + } while (status == U_BUFFER_OVERFLOW_ERROR); +#endif return result; } @@ -1183,13 +1198,23 @@ static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, c static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath) { char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = ""; - char cmd[LARGE_BUFFER_MAX_SIZE] = ""; + char *cmd; int32_t result = 0; + int32_t length = 0; + /* Remove the ending .s and replace it with .o for the new object file. */ uprv_strcpy(tempObjectFile, gencFilePath); tempObjectFile[uprv_strlen(tempObjectFile)-1] = 'o'; + length = uprv_strlen(pkgDataFlags[COMPILER]) + uprv_strlen(pkgDataFlags[LIBFLAGS]) + + uprv_strlen(tempObjectFile) + uprv_strlen(gencFilePath) + 10; + + cmd = (char *)uprv_malloc(sizeof(char) * length); + if (cmd == NULL) { + return -1; + } + /* Generate the object file. */ sprintf(cmd, "%s %s -o %s %s", pkgDataFlags[COMPILER], @@ -1198,6 +1223,7 @@ static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode gencFilePath); result = runCommand(cmd); + uprv_free(cmd); if (result != 0) { return result; } diff --git a/icu4c/source/tools/toolutil/flagparser.c b/icu4c/source/tools/toolutil/flagparser.c index a09de57e2aa..507f2cefadb 100644 --- a/icu4c/source/tools/toolutil/flagparser.c +++ b/icu4c/source/tools/toolutil/flagparser.c @@ -1,13 +1,15 @@ /****************************************************************************** - * Copyright (C) 2009, International Business Machines + * Copyright (C) 2009-2010, International Business Machines * Corporation and others. All Rights Reserved. ******************************************************************************* */ #include "flagparser.h" #include "filestrm.h" +#include "cstring.h" +#include "cmemory.h" -#define LARGE_BUFFER_MAX_SIZE 2048 +#define BUFFER_DEFAULT_SIZE 512 static void extractFlag(char* buffer, int32_t bufferSize, char* flag, int32_t flagSize, UErrorCode *status); static int32_t getFlagOffset(const char *buffer, int32_t bufferSize); @@ -17,7 +19,9 @@ static int32_t getFlagOffset(const char *buffer, int32_t bufferSize); */ U_CAPI void U_EXPORT2 parseFlagsFile(const char *fileName, char **flagBuffer, int32_t flagBufferSize, int32_t numOfFlags, UErrorCode *status) { - char buffer[LARGE_BUFFER_MAX_SIZE]; + int32_t currentBufferSize = BUFFER_DEFAULT_SIZE; + char* buffer = uprv_malloc(sizeof(char) * currentBufferSize); + UBool allocateMoreSpace = FALSE; int32_t i; FileStream *f = T_FileStream_open(fileName, "r"); @@ -26,18 +30,43 @@ parseFlagsFile(const char *fileName, char **flagBuffer, int32_t flagBufferSize, return; } - for (i = 0; i < numOfFlags; i++) { - if (T_FileStream_readLine(f, buffer, LARGE_BUFFER_MAX_SIZE) == NULL) { - *status = U_FILE_ACCESS_ERROR; - break; - } - - extractFlag(buffer, LARGE_BUFFER_MAX_SIZE, flagBuffer[i], flagBufferSize, status); - if (U_FAILURE(*status)) { - break; - } + if (buffer == NULL) { + *status = U_MEMORY_ALLOCATION_ERROR; + return; } + 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; + } + } + 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)) { + break; + } + } + } + } while (allocateMoreSpace && U_SUCCESS(*status)); + T_FileStream_close(f); }