intl/icu/source/tools/toolutil/pkg_gencmn.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /******************************************************************************
michael@0 2 * Copyright (C) 2008-2012, International Business Machines
michael@0 3 * Corporation and others. All Rights Reserved.
michael@0 4 *******************************************************************************
michael@0 5 */
michael@0 6 #include "unicode/utypes.h"
michael@0 7
michael@0 8 #include <stdio.h>
michael@0 9 #include <stdlib.h>
michael@0 10 #include "unicode/utypes.h"
michael@0 11 #include "unicode/putil.h"
michael@0 12 #include "cmemory.h"
michael@0 13 #include "cstring.h"
michael@0 14 #include "filestrm.h"
michael@0 15 #include "toolutil.h"
michael@0 16 #include "unicode/uclean.h"
michael@0 17 #include "unewdata.h"
michael@0 18 #include "putilimp.h"
michael@0 19 #include "pkg_gencmn.h"
michael@0 20
michael@0 21 #define STRING_STORE_SIZE 200000
michael@0 22
michael@0 23 #define COMMON_DATA_NAME U_ICUDATA_NAME
michael@0 24 #define DATA_TYPE "dat"
michael@0 25
michael@0 26 /* ICU package data file format (.dat files) ------------------------------- ***
michael@0 27
michael@0 28 Description of the data format after the usual ICU data file header
michael@0 29 (UDataInfo etc.).
michael@0 30
michael@0 31 Format version 1
michael@0 32
michael@0 33 A .dat package file contains a simple Table of Contents of item names,
michael@0 34 followed by the items themselves:
michael@0 35
michael@0 36 1. ToC table
michael@0 37
michael@0 38 uint32_t count; - number of items
michael@0 39 UDataOffsetTOCEntry entry[count]; - pair of uint32_t values per item:
michael@0 40 uint32_t nameOffset; - offset of the item name
michael@0 41 uint32_t dataOffset; - offset of the item data
michael@0 42 both are byte offsets from the beginning of the data
michael@0 43
michael@0 44 2. item name strings
michael@0 45
michael@0 46 All item names are stored as char * strings in one block between the ToC table
michael@0 47 and the data items.
michael@0 48
michael@0 49 3. data items
michael@0 50
michael@0 51 The data items are stored following the item names block.
michael@0 52 Each data item is 16-aligned.
michael@0 53 The data items are stored in the sorted order of their names.
michael@0 54
michael@0 55 Therefore, the top of the name strings block is the offset of the first item,
michael@0 56 the length of the last item is the difference between its offset and
michael@0 57 the .dat file length, and the length of all previous items is the difference
michael@0 58 between its offset and the next one.
michael@0 59
michael@0 60 ----------------------------------------------------------------------------- */
michael@0 61
michael@0 62 /* UDataInfo cf. udata.h */
michael@0 63 static const UDataInfo dataInfo={
michael@0 64 sizeof(UDataInfo),
michael@0 65 0,
michael@0 66
michael@0 67 U_IS_BIG_ENDIAN,
michael@0 68 U_CHARSET_FAMILY,
michael@0 69 sizeof(UChar),
michael@0 70 0,
michael@0 71
michael@0 72 {0x43, 0x6d, 0x6e, 0x44}, /* dataFormat="CmnD" */
michael@0 73 {1, 0, 0, 0}, /* formatVersion */
michael@0 74 {3, 0, 0, 0} /* dataVersion */
michael@0 75 };
michael@0 76
michael@0 77 static uint32_t maxSize;
michael@0 78
michael@0 79 static char stringStore[STRING_STORE_SIZE];
michael@0 80 static uint32_t stringTop=0, basenameTotal=0;
michael@0 81
michael@0 82 typedef struct {
michael@0 83 char *pathname, *basename;
michael@0 84 uint32_t basenameLength, basenameOffset, fileSize, fileOffset;
michael@0 85 } File;
michael@0 86
michael@0 87 #define CHUNK_FILE_COUNT 256
michael@0 88 static File *files = NULL;
michael@0 89 static uint32_t fileCount=0;
michael@0 90 static uint32_t fileMax = 0;
michael@0 91
michael@0 92
michael@0 93 static char *symPrefix = NULL;
michael@0 94
michael@0 95 #define LINE_BUFFER_SIZE 512
michael@0 96 /* prototypes --------------------------------------------------------------- */
michael@0 97
michael@0 98 static void
michael@0 99 addFile(const char *filename, const char *name, const char *source, UBool sourceTOC, UBool verbose);
michael@0 100
michael@0 101 static char *
michael@0 102 allocString(uint32_t length);
michael@0 103
michael@0 104 static int
michael@0 105 compareFiles(const void *file1, const void *file2);
michael@0 106
michael@0 107 static char *
michael@0 108 pathToFullPath(const char *path, const char *source);
michael@0 109
michael@0 110 /* map non-tree separator (such as '\') to tree separator ('/') inplace. */
michael@0 111 static void
michael@0 112 fixDirToTreePath(char *s);
michael@0 113 /* -------------------------------------------------------------------------- */
michael@0 114
michael@0 115 U_CAPI void U_EXPORT2
michael@0 116 createCommonDataFile(const char *destDir, const char *name, const char *entrypointName, const char *type, const char *source, const char *copyRight,
michael@0 117 const char *dataFile, uint32_t max_size, UBool sourceTOC, UBool verbose, char *gencmnFileName) {
michael@0 118 static char buffer[4096];
michael@0 119 char *line;
michael@0 120 char *linePtr;
michael@0 121 char *s = NULL;
michael@0 122 UErrorCode errorCode=U_ZERO_ERROR;
michael@0 123 uint32_t i, fileOffset, basenameOffset, length, nread;
michael@0 124 FileStream *in, *file;
michael@0 125
michael@0 126 line = (char *)uprv_malloc(sizeof(char) * LINE_BUFFER_SIZE);
michael@0 127 if (line == NULL) {
michael@0 128 fprintf(stderr, "gencmn: unable to allocate memory for line buffer of size %d\n", LINE_BUFFER_SIZE);
michael@0 129 exit(U_MEMORY_ALLOCATION_ERROR);
michael@0 130 }
michael@0 131
michael@0 132 linePtr = line;
michael@0 133
michael@0 134 maxSize = max_size;
michael@0 135
michael@0 136 if (destDir == NULL) {
michael@0 137 destDir = u_getDataDirectory();
michael@0 138 }
michael@0 139 if (name == NULL) {
michael@0 140 name = COMMON_DATA_NAME;
michael@0 141 }
michael@0 142 if (type == NULL) {
michael@0 143 type = DATA_TYPE;
michael@0 144 }
michael@0 145 if (source == NULL) {
michael@0 146 source = ".";
michael@0 147 }
michael@0 148
michael@0 149 if (dataFile == NULL) {
michael@0 150 in = T_FileStream_stdin();
michael@0 151 } else {
michael@0 152 in = T_FileStream_open(dataFile, "r");
michael@0 153 if(in == NULL) {
michael@0 154 fprintf(stderr, "gencmn: unable to open input file %s\n", dataFile);
michael@0 155 exit(U_FILE_ACCESS_ERROR);
michael@0 156 }
michael@0 157 }
michael@0 158
michael@0 159 if (verbose) {
michael@0 160 if(sourceTOC) {
michael@0 161 printf("generating %s_%s.c (table of contents source file)\n", name, type);
michael@0 162 } else {
michael@0 163 printf("generating %s.%s (common data file with table of contents)\n", name, type);
michael@0 164 }
michael@0 165 }
michael@0 166
michael@0 167 /* read the list of files and get their lengths */
michael@0 168 while((s != NULL && *s != 0) || (s=T_FileStream_readLine(in, (line=linePtr),
michael@0 169 LINE_BUFFER_SIZE))!=NULL) {
michael@0 170 /* remove trailing newline characters and parse space separated items */
michael@0 171 if (s != NULL && *s != 0) {
michael@0 172 line=s;
michael@0 173 } else {
michael@0 174 s=line;
michael@0 175 }
michael@0 176 while(*s!=0) {
michael@0 177 if(*s==' ') {
michael@0 178 *s=0;
michael@0 179 ++s;
michael@0 180 break;
michael@0 181 } else if(*s=='\r' || *s=='\n') {
michael@0 182 *s=0;
michael@0 183 break;
michael@0 184 }
michael@0 185 ++s;
michael@0 186 }
michael@0 187
michael@0 188 /* check for comment */
michael@0 189
michael@0 190 if (*line == '#') {
michael@0 191 continue;
michael@0 192 }
michael@0 193
michael@0 194 /* add the file */
michael@0 195 #if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR)
michael@0 196 {
michael@0 197 char *t;
michael@0 198 while((t = uprv_strchr(line,U_FILE_ALT_SEP_CHAR))) {
michael@0 199 *t = U_FILE_SEP_CHAR;
michael@0 200 }
michael@0 201 }
michael@0 202 #endif
michael@0 203 addFile(getLongPathname(line), name, source, sourceTOC, verbose);
michael@0 204 }
michael@0 205
michael@0 206 uprv_free(linePtr);
michael@0 207
michael@0 208 if(in!=T_FileStream_stdin()) {
michael@0 209 T_FileStream_close(in);
michael@0 210 }
michael@0 211
michael@0 212 if(fileCount==0) {
michael@0 213 fprintf(stderr, "gencmn: no files listed in %s\n", dataFile == NULL ? "<stdin>" : dataFile);
michael@0 214 return;
michael@0 215 }
michael@0 216
michael@0 217 /* sort the files by basename */
michael@0 218 qsort(files, fileCount, sizeof(File), compareFiles);
michael@0 219
michael@0 220 if(!sourceTOC) {
michael@0 221 UNewDataMemory *out;
michael@0 222
michael@0 223 /* determine the offsets of all basenames and files in this common one */
michael@0 224 basenameOffset=4+8*fileCount;
michael@0 225 fileOffset=(basenameOffset+(basenameTotal+15))&~0xf;
michael@0 226 for(i=0; i<fileCount; ++i) {
michael@0 227 files[i].fileOffset=fileOffset;
michael@0 228 fileOffset+=(files[i].fileSize+15)&~0xf;
michael@0 229 files[i].basenameOffset=basenameOffset;
michael@0 230 basenameOffset+=files[i].basenameLength;
michael@0 231 }
michael@0 232
michael@0 233 /* create the output file */
michael@0 234 out=udata_create(destDir, type, name,
michael@0 235 &dataInfo,
michael@0 236 copyRight == NULL ? U_COPYRIGHT_STRING : copyRight,
michael@0 237 &errorCode);
michael@0 238 if(U_FAILURE(errorCode)) {
michael@0 239 fprintf(stderr, "gencmn: udata_create(-d %s -n %s -t %s) failed - %s\n",
michael@0 240 destDir, name, type,
michael@0 241 u_errorName(errorCode));
michael@0 242 exit(errorCode);
michael@0 243 }
michael@0 244
michael@0 245 /* write the table of contents */
michael@0 246 udata_write32(out, fileCount);
michael@0 247 for(i=0; i<fileCount; ++i) {
michael@0 248 udata_write32(out, files[i].basenameOffset);
michael@0 249 udata_write32(out, files[i].fileOffset);
michael@0 250 }
michael@0 251
michael@0 252 /* write the basenames */
michael@0 253 for(i=0; i<fileCount; ++i) {
michael@0 254 udata_writeString(out, files[i].basename, files[i].basenameLength);
michael@0 255 }
michael@0 256 length=4+8*fileCount+basenameTotal;
michael@0 257
michael@0 258 /* copy the files */
michael@0 259 for(i=0; i<fileCount; ++i) {
michael@0 260 /* pad to 16-align the next file */
michael@0 261 length&=0xf;
michael@0 262 if(length!=0) {
michael@0 263 udata_writePadding(out, 16-length);
michael@0 264 }
michael@0 265
michael@0 266 if (verbose) {
michael@0 267 printf("adding %s (%ld byte%s)\n", files[i].pathname, (long)files[i].fileSize, files[i].fileSize == 1 ? "" : "s");
michael@0 268 }
michael@0 269
michael@0 270 /* copy the next file */
michael@0 271 file=T_FileStream_open(files[i].pathname, "rb");
michael@0 272 if(file==NULL) {
michael@0 273 fprintf(stderr, "gencmn: unable to open listed file %s\n", files[i].pathname);
michael@0 274 exit(U_FILE_ACCESS_ERROR);
michael@0 275 }
michael@0 276 for(nread = 0;;) {
michael@0 277 length=T_FileStream_read(file, buffer, sizeof(buffer));
michael@0 278 if(length <= 0) {
michael@0 279 break;
michael@0 280 }
michael@0 281 nread += length;
michael@0 282 udata_writeBlock(out, buffer, length);
michael@0 283 }
michael@0 284 T_FileStream_close(file);
michael@0 285 length=files[i].fileSize;
michael@0 286
michael@0 287 if (nread != files[i].fileSize) {
michael@0 288 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");
michael@0 289 exit(U_FILE_ACCESS_ERROR);
michael@0 290 }
michael@0 291 }
michael@0 292
michael@0 293 /* pad to 16-align the last file (cleaner, avoids growing .dat files in icuswap) */
michael@0 294 length&=0xf;
michael@0 295 if(length!=0) {
michael@0 296 udata_writePadding(out, 16-length);
michael@0 297 }
michael@0 298
michael@0 299 /* finish */
michael@0 300 udata_finish(out, &errorCode);
michael@0 301 if(U_FAILURE(errorCode)) {
michael@0 302 fprintf(stderr, "gencmn: udata_finish() failed - %s\n", u_errorName(errorCode));
michael@0 303 exit(errorCode);
michael@0 304 }
michael@0 305 } else {
michael@0 306 /* write a .c source file with the table of contents */
michael@0 307 char *filename;
michael@0 308 FileStream *out;
michael@0 309
michael@0 310 /* create the output filename */
michael@0 311 filename=s=buffer;
michael@0 312 uprv_strcpy(filename, destDir);
michael@0 313 s=filename+uprv_strlen(filename);
michael@0 314 if(s>filename && *(s-1)!=U_FILE_SEP_CHAR) {
michael@0 315 *s++=U_FILE_SEP_CHAR;
michael@0 316 }
michael@0 317 uprv_strcpy(s, name);
michael@0 318 if(*(type)!=0) {
michael@0 319 s+=uprv_strlen(s);
michael@0 320 *s++='_';
michael@0 321 uprv_strcpy(s, type);
michael@0 322 }
michael@0 323 s+=uprv_strlen(s);
michael@0 324 uprv_strcpy(s, ".c");
michael@0 325
michael@0 326 /* open the output file */
michael@0 327 out=T_FileStream_open(filename, "w");
michael@0 328 if (gencmnFileName != NULL) {
michael@0 329 uprv_strcpy(gencmnFileName, filename);
michael@0 330 }
michael@0 331 if(out==NULL) {
michael@0 332 fprintf(stderr, "gencmn: unable to open .c output file %s\n", filename);
michael@0 333 exit(U_FILE_ACCESS_ERROR);
michael@0 334 }
michael@0 335
michael@0 336 /* write the source file */
michael@0 337 sprintf(buffer,
michael@0 338 "/*\n"
michael@0 339 " * ICU common data table of contents for %s.%s\n"
michael@0 340 " * Automatically generated by icu/source/tools/gencmn/gencmn .\n"
michael@0 341 " */\n\n"
michael@0 342 "#include \"unicode/utypes.h\"\n"
michael@0 343 "#include \"unicode/udata.h\"\n"
michael@0 344 "\n"
michael@0 345 "/* external symbol declarations for data (%d files) */\n",
michael@0 346 name, type, fileCount);
michael@0 347 T_FileStream_writeLine(out, buffer);
michael@0 348
michael@0 349 sprintf(buffer, "extern const char\n %s%s[]", symPrefix?symPrefix:"", files[0].pathname);
michael@0 350 T_FileStream_writeLine(out, buffer);
michael@0 351 for(i=1; i<fileCount; ++i) {
michael@0 352 sprintf(buffer, ",\n %s%s[]", symPrefix?symPrefix:"", files[i].pathname);
michael@0 353 T_FileStream_writeLine(out, buffer);
michael@0 354 }
michael@0 355 T_FileStream_writeLine(out, ";\n\n");
michael@0 356
michael@0 357 sprintf(
michael@0 358 buffer,
michael@0 359 "U_EXPORT struct {\n"
michael@0 360 " uint16_t headerSize;\n"
michael@0 361 " uint8_t magic1, magic2;\n"
michael@0 362 " UDataInfo info;\n"
michael@0 363 " char padding[%lu];\n"
michael@0 364 " uint32_t count, reserved;\n"
michael@0 365 " struct {\n"
michael@0 366 " const char *name;\n"
michael@0 367 " const void *data;\n"
michael@0 368 " } toc[%lu];\n"
michael@0 369 "} U_EXPORT2 %s_dat = {\n"
michael@0 370 " 32, 0xda, 0x27, {\n"
michael@0 371 " %lu, 0,\n"
michael@0 372 " %u, %u, %u, 0,\n"
michael@0 373 " {0x54, 0x6f, 0x43, 0x50},\n"
michael@0 374 " {1, 0, 0, 0},\n"
michael@0 375 " {0, 0, 0, 0}\n"
michael@0 376 " },\n"
michael@0 377 " \"\", %lu, 0, {\n",
michael@0 378 (unsigned long)32-4-sizeof(UDataInfo),
michael@0 379 (unsigned long)fileCount,
michael@0 380 entrypointName,
michael@0 381 (unsigned long)sizeof(UDataInfo),
michael@0 382 U_IS_BIG_ENDIAN,
michael@0 383 U_CHARSET_FAMILY,
michael@0 384 U_SIZEOF_UCHAR,
michael@0 385 (unsigned long)fileCount
michael@0 386 );
michael@0 387 T_FileStream_writeLine(out, buffer);
michael@0 388
michael@0 389 sprintf(buffer, " { \"%s\", %s%s }", files[0].basename, symPrefix?symPrefix:"", files[0].pathname);
michael@0 390 T_FileStream_writeLine(out, buffer);
michael@0 391 for(i=1; i<fileCount; ++i) {
michael@0 392 sprintf(buffer, ",\n { \"%s\", %s%s }", files[i].basename, symPrefix?symPrefix:"", files[i].pathname);
michael@0 393 T_FileStream_writeLine(out, buffer);
michael@0 394 }
michael@0 395
michael@0 396 T_FileStream_writeLine(out, "\n }\n};\n");
michael@0 397 T_FileStream_close(out);
michael@0 398
michael@0 399 uprv_free(symPrefix);
michael@0 400 }
michael@0 401 }
michael@0 402
michael@0 403 static void
michael@0 404 addFile(const char *filename, const char *name, const char *source, UBool sourceTOC, UBool verbose) {
michael@0 405 char *s;
michael@0 406 uint32_t length;
michael@0 407 char *fullPath = NULL;
michael@0 408
michael@0 409 if(fileCount==fileMax) {
michael@0 410 fileMax += CHUNK_FILE_COUNT;
michael@0 411 files = uprv_realloc(files, fileMax*sizeof(files[0])); /* note: never freed. */
michael@0 412 if(files==NULL) {
michael@0 413 fprintf(stderr, "pkgdata/gencmn: Could not allocate %u bytes for %d files\n", (unsigned int)(fileMax*sizeof(files[0])), fileCount);
michael@0 414 exit(U_MEMORY_ALLOCATION_ERROR);
michael@0 415 }
michael@0 416 }
michael@0 417
michael@0 418 if(!sourceTOC) {
michael@0 419 FileStream *file;
michael@0 420
michael@0 421 if(uprv_pathIsAbsolute(filename)) {
michael@0 422 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);
michael@0 423 exit(U_ILLEGAL_ARGUMENT_ERROR);
michael@0 424 }
michael@0 425 fullPath = pathToFullPath(filename, source);
michael@0 426 /* store the pathname */
michael@0 427 length = (uint32_t)(uprv_strlen(filename) + 1 + uprv_strlen(name) + 1);
michael@0 428 s=allocString(length);
michael@0 429 uprv_strcpy(s, name);
michael@0 430 uprv_strcat(s, U_TREE_ENTRY_SEP_STRING);
michael@0 431 uprv_strcat(s, filename);
michael@0 432
michael@0 433 /* get the basename */
michael@0 434 fixDirToTreePath(s);
michael@0 435 files[fileCount].basename=s;
michael@0 436 files[fileCount].basenameLength=length;
michael@0 437
michael@0 438 files[fileCount].pathname=fullPath;
michael@0 439
michael@0 440 basenameTotal+=length;
michael@0 441
michael@0 442 /* try to open the file */
michael@0 443 file=T_FileStream_open(fullPath, "rb");
michael@0 444 if(file==NULL) {
michael@0 445 fprintf(stderr, "gencmn: unable to open listed file %s\n", fullPath);
michael@0 446 exit(U_FILE_ACCESS_ERROR);
michael@0 447 }
michael@0 448
michael@0 449 /* get the file length */
michael@0 450 length=T_FileStream_size(file);
michael@0 451 if(T_FileStream_error(file) || length<=20) {
michael@0 452 fprintf(stderr, "gencmn: unable to get length of listed file %s\n", fullPath);
michael@0 453 exit(U_FILE_ACCESS_ERROR);
michael@0 454 }
michael@0 455
michael@0 456 T_FileStream_close(file);
michael@0 457
michael@0 458 /* do not add files that are longer than maxSize */
michael@0 459 if(maxSize && length>maxSize) {
michael@0 460 if (verbose) {
michael@0 461 printf("%s ignored (size %ld > %ld)\n", fullPath, (long)length, (long)maxSize);
michael@0 462 }
michael@0 463 return;
michael@0 464 }
michael@0 465 files[fileCount].fileSize=length;
michael@0 466 } else {
michael@0 467 char *t;
michael@0 468 /* get and store the basename */
michael@0 469 /* need to include the package name */
michael@0 470 length = (uint32_t)(uprv_strlen(filename) + 1 + uprv_strlen(name) + 1);
michael@0 471 s=allocString(length);
michael@0 472 uprv_strcpy(s, name);
michael@0 473 uprv_strcat(s, U_TREE_ENTRY_SEP_STRING);
michael@0 474 uprv_strcat(s, filename);
michael@0 475 fixDirToTreePath(s);
michael@0 476 files[fileCount].basename=s;
michael@0 477 /* turn the basename into an entry point name and store in the pathname field */
michael@0 478 t=files[fileCount].pathname=allocString(length);
michael@0 479 while(--length>0) {
michael@0 480 if(*s=='.' || *s=='-' || *s=='/') {
michael@0 481 *t='_';
michael@0 482 } else {
michael@0 483 *t=*s;
michael@0 484 }
michael@0 485 ++s;
michael@0 486 ++t;
michael@0 487 }
michael@0 488 *t=0;
michael@0 489 }
michael@0 490 ++fileCount;
michael@0 491 }
michael@0 492
michael@0 493 static char *
michael@0 494 allocString(uint32_t length) {
michael@0 495 uint32_t top=stringTop+length;
michael@0 496 char *p;
michael@0 497
michael@0 498 if(top>STRING_STORE_SIZE) {
michael@0 499 fprintf(stderr, "gencmn: out of memory\n");
michael@0 500 exit(U_MEMORY_ALLOCATION_ERROR);
michael@0 501 }
michael@0 502 p=stringStore+stringTop;
michael@0 503 stringTop=top;
michael@0 504 return p;
michael@0 505 }
michael@0 506
michael@0 507 static char *
michael@0 508 pathToFullPath(const char *path, const char *source) {
michael@0 509 int32_t length;
michael@0 510 int32_t newLength;
michael@0 511 char *fullPath;
michael@0 512 int32_t n;
michael@0 513
michael@0 514 length = (uint32_t)(uprv_strlen(path) + 1);
michael@0 515 newLength = (length + 1 + (int32_t)uprv_strlen(source));
michael@0 516 fullPath = uprv_malloc(newLength);
michael@0 517 if(source != NULL) {
michael@0 518 uprv_strcpy(fullPath, source);
michael@0 519 uprv_strcat(fullPath, U_FILE_SEP_STRING);
michael@0 520 } else {
michael@0 521 fullPath[0] = 0;
michael@0 522 }
michael@0 523 n = (int32_t)uprv_strlen(fullPath);
michael@0 524 fullPath[n] = 0; /* Suppress compiler warning for unused variable n */
michael@0 525 /* when conditional code below is not compiled. */
michael@0 526 uprv_strcat(fullPath, path);
michael@0 527
michael@0 528 #if (U_FILE_ALT_SEP_CHAR != U_TREE_ENTRY_SEP_CHAR)
michael@0 529 #if (U_FILE_ALT_SEP_CHAR != U_FILE_SEP_CHAR)
michael@0 530 /* replace tree separator (such as '/') with file sep char (such as ':' or '\\') */
michael@0 531 for(;fullPath[n];n++) {
michael@0 532 if(fullPath[n] == U_FILE_ALT_SEP_CHAR) {
michael@0 533 fullPath[n] = U_FILE_SEP_CHAR;
michael@0 534 }
michael@0 535 }
michael@0 536 #endif
michael@0 537 #endif
michael@0 538 #if (U_FILE_SEP_CHAR != U_TREE_ENTRY_SEP_CHAR)
michael@0 539 /* replace tree separator (such as '/') with file sep char (such as ':' or '\\') */
michael@0 540 for(;fullPath[n];n++) {
michael@0 541 if(fullPath[n] == U_TREE_ENTRY_SEP_CHAR) {
michael@0 542 fullPath[n] = U_FILE_SEP_CHAR;
michael@0 543 }
michael@0 544 }
michael@0 545 #endif
michael@0 546 return fullPath;
michael@0 547 }
michael@0 548
michael@0 549 static int
michael@0 550 compareFiles(const void *file1, const void *file2) {
michael@0 551 /* sort by basename */
michael@0 552 return uprv_strcmp(((File *)file1)->basename, ((File *)file2)->basename);
michael@0 553 }
michael@0 554
michael@0 555 static void
michael@0 556 fixDirToTreePath(char *s)
michael@0 557 {
michael@0 558 #if (U_FILE_SEP_CHAR != U_TREE_ENTRY_SEP_CHAR) || ((U_FILE_ALT_SEP_CHAR != U_FILE_SEP_CHAR) && (U_FILE_ALT_SEP_CHAR != U_TREE_ENTRY_SEP_CHAR))
michael@0 559 char *t;
michael@0 560 #endif
michael@0 561 #if (U_FILE_SEP_CHAR != U_TREE_ENTRY_SEP_CHAR)
michael@0 562 for(t=s;t=uprv_strchr(t,U_FILE_SEP_CHAR);) {
michael@0 563 *t = U_TREE_ENTRY_SEP_CHAR;
michael@0 564 }
michael@0 565 #endif
michael@0 566 #if (U_FILE_ALT_SEP_CHAR != U_FILE_SEP_CHAR) && (U_FILE_ALT_SEP_CHAR != U_TREE_ENTRY_SEP_CHAR)
michael@0 567 for(t=s;t=uprv_strchr(t,U_FILE_ALT_SEP_CHAR);) {
michael@0 568 *t = U_TREE_ENTRY_SEP_CHAR;
michael@0 569 }
michael@0 570 #endif
michael@0 571 }

mercurial