185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/******************************************************************************
2103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius *   Copyright (C) 2008-2012, International Business Machines
385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho *   Corporation and others.  All Rights Reserved.
485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho *******************************************************************************
585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */
685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "unicode/utypes.h"
785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include <stdio.h>
985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include <stdlib.h>
1085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "unicode/utypes.h"
1185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "unicode/putil.h"
1285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "cmemory.h"
1385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "cstring.h"
1485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "filestrm.h"
1585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "toolutil.h"
1685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "unicode/uclean.h"
1785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "unewdata.h"
1885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "putilimp.h"
1985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "pkg_gencmn.h"
2085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
21b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#define STRING_STORE_SIZE 200000
2285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
2385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#define COMMON_DATA_NAME U_ICUDATA_NAME
2485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#define DATA_TYPE "dat"
2585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
2685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/* ICU package data file format (.dat files) ------------------------------- ***
2785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
2885bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoDescription of the data format after the usual ICU data file header
2985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho(UDataInfo etc.).
3085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
3185bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoFormat version 1
3285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
3385bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoA .dat package file contains a simple Table of Contents of item names,
3485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hofollowed by the items themselves:
3585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
3685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho1. ToC table
3785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
3885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Houint32_t count; - number of items
3985bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoUDataOffsetTOCEntry entry[count]; - pair of uint32_t values per item:
4085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    uint32_t nameOffset; - offset of the item name
4185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    uint32_t dataOffset; - offset of the item data
4285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoboth are byte offsets from the beginning of the data
4385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
4485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho2. item name strings
4585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
4685bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoAll item names are stored as char * strings in one block between the ToC table
4785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoand the data items.
4885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
4985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho3. data items
5085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
5185bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoThe data items are stored following the item names block.
5285bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoEach data item is 16-aligned.
5385bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoThe data items are stored in the sorted order of their names.
5485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
5585bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoTherefore, the top of the name strings block is the offset of the first item,
5685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hothe length of the last item is the difference between its offset and
5785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hothe .dat file length, and the length of all previous items is the difference
5885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hobetween its offset and the next one.
5985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
6085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho----------------------------------------------------------------------------- */
6185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
6285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/* UDataInfo cf. udata.h */
6385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic const UDataInfo dataInfo={
6485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    sizeof(UDataInfo),
6585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    0,
6685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
6785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    U_IS_BIG_ENDIAN,
6885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    U_CHARSET_FAMILY,
6985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    sizeof(UChar),
7085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    0,
7185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
7285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    {0x43, 0x6d, 0x6e, 0x44},     /* dataFormat="CmnD" */
7385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    {1, 0, 0, 0},                 /* formatVersion */
7485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    {3, 0, 0, 0}                  /* dataVersion */
7585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho};
7685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
7785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic uint32_t maxSize;
7885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
7985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic char stringStore[STRING_STORE_SIZE];
8085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic uint32_t stringTop=0, basenameTotal=0;
8185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
8285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hotypedef struct {
8385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    char *pathname, *basename;
8485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    uint32_t basenameLength, basenameOffset, fileSize, fileOffset;
8585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho} File;
8685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
8727f654740f2a26ad62a5c155af9199af9e69b889claireho#define CHUNK_FILE_COUNT 256
8827f654740f2a26ad62a5c155af9199af9e69b889clairehostatic File *files = NULL;
8985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic uint32_t fileCount=0;
9027f654740f2a26ad62a5c155af9199af9e69b889clairehostatic uint32_t fileMax = 0;
9127f654740f2a26ad62a5c155af9199af9e69b889claireho
9285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
9385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic char *symPrefix = NULL;
9485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
95103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#define LINE_BUFFER_SIZE 512
9685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/* prototypes --------------------------------------------------------------- */
9785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
9885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic void
9985bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoaddFile(const char *filename, const char *name, const char *source, UBool sourceTOC, UBool verbose);
10085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
10185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic char *
10285bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoallocString(uint32_t length);
10385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
10485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic int
10585bf2e2fbc60a9f938064abc8127d61da7d19882Claire HocompareFiles(const void *file1, const void *file2);
10685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
10785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic char *
10885bf2e2fbc60a9f938064abc8127d61da7d19882Claire HopathToFullPath(const char *path, const char *source);
10985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
11085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/* map non-tree separator (such as '\') to tree separator ('/') inplace. */
11185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic void
11285bf2e2fbc60a9f938064abc8127d61da7d19882Claire HofixDirToTreePath(char *s);
11385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/* -------------------------------------------------------------------------- */
11485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
11585bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoU_CAPI void U_EXPORT2
11685bf2e2fbc60a9f938064abc8127d61da7d19882Claire HocreateCommonDataFile(const char *destDir, const char *name, const char *entrypointName, const char *type, const char *source, const char *copyRight,
11785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                     const char *dataFile, uint32_t max_size, UBool sourceTOC, UBool verbose, char *gencmnFileName) {
11885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    static char buffer[4096];
119103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    char *line;
120103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    char *linePtr;
121103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    char *s = NULL;
12285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UErrorCode errorCode=U_ZERO_ERROR;
12385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    uint32_t i, fileOffset, basenameOffset, length, nread;
12485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    FileStream *in, *file;
12585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
126103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    line = (char *)uprv_malloc(sizeof(char) * LINE_BUFFER_SIZE);
127103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (line == NULL) {
128103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        fprintf(stderr, "gencmn: unable to allocate memory for line buffer of size %d\n", LINE_BUFFER_SIZE);
129103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        exit(U_MEMORY_ALLOCATION_ERROR);
130103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
131103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
132103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    linePtr = line;
133103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
13485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    maxSize = max_size;
13585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
13685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (destDir == NULL) {
13785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        destDir = u_getDataDirectory();
13885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
13985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (name == NULL) {
14085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        name = COMMON_DATA_NAME;
14185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
14285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (type == NULL) {
14385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        type = DATA_TYPE;
14485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
14585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (source == NULL) {
14685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        source = ".";
14785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
14885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
14985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (dataFile == NULL) {
15085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        in = T_FileStream_stdin();
15185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    } else {
15285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        in = T_FileStream_open(dataFile, "r");
15385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(in == NULL) {
15485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            fprintf(stderr, "gencmn: unable to open input file %s\n", dataFile);
15585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            exit(U_FILE_ACCESS_ERROR);
15685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
15785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
15885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
15985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (verbose) {
16085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(sourceTOC) {
16185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            printf("generating %s_%s.c (table of contents source file)\n", name, type);
16285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        } else {
16385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            printf("generating %s.%s (common data file with table of contents)\n", name, type);
16485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
16585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
16685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
16785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /* read the list of files and get their lengths */
168103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    while((s != NULL && *s != 0) || (s=T_FileStream_readLine(in, (line=linePtr),
169103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                                                             LINE_BUFFER_SIZE))!=NULL) {
170103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        /* remove trailing newline characters and parse space separated items */
171103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if (s != NULL && *s != 0) {
172103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            line=s;
173103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        } else {
174103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            s=line;
175103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
17685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        while(*s!=0) {
177103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            if(*s==' ') {
178103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                *s=0;
179103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                ++s;
180103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                break;
181103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            } else if(*s=='\r' || *s=='\n') {
18285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                *s=0;
18385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                break;
18485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
18585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            ++s;
18685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
18785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
18885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* check for comment */
18985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
19085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (*line == '#') {
19185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            continue;
19285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
19385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
19485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* add the file */
19585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR)
19685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        {
19785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho          char *t;
19885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho          while((t = uprv_strchr(line,U_FILE_ALT_SEP_CHAR))) {
19985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            *t = U_FILE_SEP_CHAR;
20085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho          }
20185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
20285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif
20385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        addFile(getLongPathname(line), name, source, sourceTOC, verbose);
20485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
20585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
20654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    uprv_free(linePtr);
207103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
20885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(in!=T_FileStream_stdin()) {
20985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        T_FileStream_close(in);
21085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
21185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
21285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(fileCount==0) {
21385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fprintf(stderr, "gencmn: no files listed in %s\n", dataFile == NULL ? "<stdin>" : dataFile);
21485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return;
21585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
21685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
21785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /* sort the files by basename */
21885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    qsort(files, fileCount, sizeof(File), compareFiles);
21985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
22085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(!sourceTOC) {
22185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UNewDataMemory *out;
22285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
22385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* determine the offsets of all basenames and files in this common one */
22485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        basenameOffset=4+8*fileCount;
22585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fileOffset=(basenameOffset+(basenameTotal+15))&~0xf;
22685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        for(i=0; i<fileCount; ++i) {
22785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            files[i].fileOffset=fileOffset;
22885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            fileOffset+=(files[i].fileSize+15)&~0xf;
22985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            files[i].basenameOffset=basenameOffset;
23085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            basenameOffset+=files[i].basenameLength;
23185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
23285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
23385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* create the output file */
23485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        out=udata_create(destDir, type, name,
23585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                         &dataInfo,
23685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                         copyRight == NULL ? U_COPYRIGHT_STRING : copyRight,
23785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                         &errorCode);
23885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(U_FAILURE(errorCode)) {
23985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            fprintf(stderr, "gencmn: udata_create(-d %s -n %s -t %s) failed - %s\n",
24085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                destDir, name, type,
24185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                u_errorName(errorCode));
24285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            exit(errorCode);
24385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
24485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
24585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* write the table of contents */
24685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        udata_write32(out, fileCount);
24785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        for(i=0; i<fileCount; ++i) {
24885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            udata_write32(out, files[i].basenameOffset);
24985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            udata_write32(out, files[i].fileOffset);
25085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
25185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
25285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* write the basenames */
25385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        for(i=0; i<fileCount; ++i) {
25485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            udata_writeString(out, files[i].basename, files[i].basenameLength);
25585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
25685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        length=4+8*fileCount+basenameTotal;
25785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
25885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* copy the files */
25985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        for(i=0; i<fileCount; ++i) {
26085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            /* pad to 16-align the next file */
26185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            length&=0xf;
26285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if(length!=0) {
26385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                udata_writePadding(out, 16-length);
26485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
26585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
26685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (verbose) {
26785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                printf("adding %s (%ld byte%s)\n", files[i].pathname, (long)files[i].fileSize, files[i].fileSize == 1 ? "" : "s");
26885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
26985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
27085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            /* copy the next file */
27185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            file=T_FileStream_open(files[i].pathname, "rb");
27285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if(file==NULL) {
27385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                fprintf(stderr, "gencmn: unable to open listed file %s\n", files[i].pathname);
27485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                exit(U_FILE_ACCESS_ERROR);
27585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
27685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            for(nread = 0;;) {
27785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                length=T_FileStream_read(file, buffer, sizeof(buffer));
27885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                if(length <= 0) {
27985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    break;
28085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                }
28185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                nread += length;
28285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                udata_writeBlock(out, buffer, length);
28385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
28485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            T_FileStream_close(file);
28585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            length=files[i].fileSize;
28685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
28785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (nread != files[i].fileSize) {
28885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho              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");
28985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                exit(U_FILE_ACCESS_ERROR);
29085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
29185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
29285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
29385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* pad to 16-align the last file (cleaner, avoids growing .dat files in icuswap) */
29485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        length&=0xf;
29585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(length!=0) {
29685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            udata_writePadding(out, 16-length);
29785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
29885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
29985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* finish */
30085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        udata_finish(out, &errorCode);
30185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(U_FAILURE(errorCode)) {
30285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            fprintf(stderr, "gencmn: udata_finish() failed - %s\n", u_errorName(errorCode));
30385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            exit(errorCode);
30485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
30585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    } else {
30685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* write a .c source file with the table of contents */
30785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        char *filename;
30885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        FileStream *out;
30985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
31085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* create the output filename */
31185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        filename=s=buffer;
31285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_strcpy(filename, destDir);
31385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        s=filename+uprv_strlen(filename);
31485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(s>filename && *(s-1)!=U_FILE_SEP_CHAR) {
31585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            *s++=U_FILE_SEP_CHAR;
31685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
31785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_strcpy(s, name);
31885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(*(type)!=0) {
31985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            s+=uprv_strlen(s);
32085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            *s++='_';
32185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            uprv_strcpy(s, type);
32285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
32385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        s+=uprv_strlen(s);
32485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_strcpy(s, ".c");
32585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
32685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* open the output file */
32785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        out=T_FileStream_open(filename, "w");
32885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (gencmnFileName != NULL) {
32985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            uprv_strcpy(gencmnFileName, filename);
33085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
33185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(out==NULL) {
33285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            fprintf(stderr, "gencmn: unable to open .c output file %s\n", filename);
33385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            exit(U_FILE_ACCESS_ERROR);
33485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
33585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
33685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* write the source file */
33785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        sprintf(buffer,
33885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "/*\n"
339103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            " * ICU common data table of contents for %s.%s\n"
34085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            " * Automatically generated by icu/source/tools/gencmn/gencmn .\n"
34185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            " */\n\n"
34285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "#include \"unicode/utypes.h\"\n"
34385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "#include \"unicode/udata.h\"\n"
34485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "\n"
345103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            "/* external symbol declarations for data (%d files) */\n",
346103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                name, type, fileCount);
34785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        T_FileStream_writeLine(out, buffer);
34885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
34985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        sprintf(buffer, "extern const char\n    %s%s[]", symPrefix?symPrefix:"", files[0].pathname);
35085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        T_FileStream_writeLine(out, buffer);
35185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        for(i=1; i<fileCount; ++i) {
35285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            sprintf(buffer, ",\n    %s%s[]", symPrefix?symPrefix:"", files[i].pathname);
35385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            T_FileStream_writeLine(out, buffer);
35485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
35585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        T_FileStream_writeLine(out, ";\n\n");
35685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
35785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        sprintf(
35885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            buffer,
35985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "U_EXPORT struct {\n"
36085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "    uint16_t headerSize;\n"
36185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "    uint8_t magic1, magic2;\n"
36285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "    UDataInfo info;\n"
36385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "    char padding[%lu];\n"
36485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "    uint32_t count, reserved;\n"
36585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "    struct {\n"
36685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "        const char *name;\n"
36785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "        const void *data;\n"
36885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "    } toc[%lu];\n"
36985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "} U_EXPORT2 %s_dat = {\n"
37085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "    32, 0xda, 0x27, {\n"
37185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "        %lu, 0,\n"
37285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "        %u, %u, %u, 0,\n"
37385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "        {0x54, 0x6f, 0x43, 0x50},\n"
37485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "        {1, 0, 0, 0},\n"
37585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "        {0, 0, 0, 0}\n"
37685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "    },\n"
37785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "    \"\", %lu, 0, {\n",
37885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            (unsigned long)32-4-sizeof(UDataInfo),
37985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            (unsigned long)fileCount,
38085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            entrypointName,
38185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            (unsigned long)sizeof(UDataInfo),
38285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            U_IS_BIG_ENDIAN,
38385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            U_CHARSET_FAMILY,
38485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            U_SIZEOF_UCHAR,
38585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            (unsigned long)fileCount
38685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        );
38785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        T_FileStream_writeLine(out, buffer);
38885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
38985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        sprintf(buffer, "        { \"%s\", %s%s }", files[0].basename, symPrefix?symPrefix:"", files[0].pathname);
39085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        T_FileStream_writeLine(out, buffer);
39185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        for(i=1; i<fileCount; ++i) {
39285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            sprintf(buffer, ",\n        { \"%s\", %s%s }", files[i].basename, symPrefix?symPrefix:"", files[i].pathname);
39385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            T_FileStream_writeLine(out, buffer);
39485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
39585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
39685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        T_FileStream_writeLine(out, "\n    }\n};\n");
39785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        T_FileStream_close(out);
39885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
39985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_free(symPrefix);
40085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
40185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
40285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
40385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic void
40485bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoaddFile(const char *filename, const char *name, const char *source, UBool sourceTOC, UBool verbose) {
40585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    char *s;
40685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    uint32_t length;
40785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    char *fullPath = NULL;
40885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
40927f654740f2a26ad62a5c155af9199af9e69b889claireho    if(fileCount==fileMax) {
41027f654740f2a26ad62a5c155af9199af9e69b889claireho      fileMax += CHUNK_FILE_COUNT;
41127f654740f2a26ad62a5c155af9199af9e69b889claireho      files = uprv_realloc(files, fileMax*sizeof(files[0])); /* note: never freed. */
41227f654740f2a26ad62a5c155af9199af9e69b889claireho      if(files==NULL) {
413103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        fprintf(stderr, "pkgdata/gencmn: Could not allocate %u bytes for %d files\n", (unsigned int)(fileMax*sizeof(files[0])), fileCount);
41427f654740f2a26ad62a5c155af9199af9e69b889claireho        exit(U_MEMORY_ALLOCATION_ERROR);
41527f654740f2a26ad62a5c155af9199af9e69b889claireho      }
41685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
41785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
41885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(!sourceTOC) {
41985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        FileStream *file;
42085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
42185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(uprv_pathIsAbsolute(filename)) {
42285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            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);
42385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            exit(U_ILLEGAL_ARGUMENT_ERROR);
42485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
42585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fullPath = pathToFullPath(filename, source);
42685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* store the pathname */
42785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        length = (uint32_t)(uprv_strlen(filename) + 1 + uprv_strlen(name) + 1);
42885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        s=allocString(length);
42985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_strcpy(s, name);
43085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_strcat(s, U_TREE_ENTRY_SEP_STRING);
43185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_strcat(s, filename);
43285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
43385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* get the basename */
43485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fixDirToTreePath(s);
43585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        files[fileCount].basename=s;
43685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        files[fileCount].basenameLength=length;
43785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
43885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        files[fileCount].pathname=fullPath;
43985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
44085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        basenameTotal+=length;
44185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
44285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* try to open the file */
44385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        file=T_FileStream_open(fullPath, "rb");
44485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(file==NULL) {
44585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            fprintf(stderr, "gencmn: unable to open listed file %s\n", fullPath);
44685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            exit(U_FILE_ACCESS_ERROR);
44785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
44885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
44985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* get the file length */
45085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        length=T_FileStream_size(file);
45185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(T_FileStream_error(file) || length<=20) {
45285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            fprintf(stderr, "gencmn: unable to get length of listed file %s\n", fullPath);
45385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            exit(U_FILE_ACCESS_ERROR);
45485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
45585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
45685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        T_FileStream_close(file);
45785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
45885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* do not add files that are longer than maxSize */
45985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(maxSize && length>maxSize) {
46085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (verbose) {
46185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                printf("%s ignored (size %ld > %ld)\n", fullPath, (long)length, (long)maxSize);
46285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
46385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return;
46485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
46585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        files[fileCount].fileSize=length;
46685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    } else {
46785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        char *t;
46885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* get and store the basename */
46985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* need to include the package name */
47085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        length = (uint32_t)(uprv_strlen(filename) + 1 + uprv_strlen(name) + 1);
47185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        s=allocString(length);
47285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_strcpy(s, name);
47385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_strcat(s, U_TREE_ENTRY_SEP_STRING);
47485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_strcat(s, filename);
47585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fixDirToTreePath(s);
47685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        files[fileCount].basename=s;
47785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* turn the basename into an entry point name and store in the pathname field */
47885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        t=files[fileCount].pathname=allocString(length);
47985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        while(--length>0) {
48085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if(*s=='.' || *s=='-' || *s=='/') {
48185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                *t='_';
48285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            } else {
48385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                *t=*s;
48485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
48585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            ++s;
48685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            ++t;
48785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
48885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        *t=0;
48985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
49085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    ++fileCount;
49185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
49285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
49385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic char *
49485bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoallocString(uint32_t length) {
49585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    uint32_t top=stringTop+length;
49685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    char *p;
49785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
49885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(top>STRING_STORE_SIZE) {
49985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fprintf(stderr, "gencmn: out of memory\n");
50085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        exit(U_MEMORY_ALLOCATION_ERROR);
50185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
50285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    p=stringStore+stringTop;
50385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    stringTop=top;
50485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return p;
50585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
50685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
50785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic char *
50885bf2e2fbc60a9f938064abc8127d61da7d19882Claire HopathToFullPath(const char *path, const char *source) {
50985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t length;
51085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t newLength;
51185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    char *fullPath;
51285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t n;
51385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
51485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    length = (uint32_t)(uprv_strlen(path) + 1);
51585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    newLength = (length + 1 + (int32_t)uprv_strlen(source));
51685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fullPath = uprv_malloc(newLength);
51785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(source != NULL) {
51885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_strcpy(fullPath, source);
51985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        uprv_strcat(fullPath, U_FILE_SEP_STRING);
52085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    } else {
52185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fullPath[0] = 0;
52285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
52385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    n = (int32_t)uprv_strlen(fullPath);
524103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    fullPath[n] = 0;       /* Suppress compiler warning for unused variable n    */
525103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                           /*  when conditional code below is not compiled.      */
52685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    uprv_strcat(fullPath, path);
52785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
52885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if (U_FILE_ALT_SEP_CHAR != U_TREE_ENTRY_SEP_CHAR)
52985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if (U_FILE_ALT_SEP_CHAR != U_FILE_SEP_CHAR)
53085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /* replace tree separator (such as '/') with file sep char (such as ':' or '\\') */
53185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    for(;fullPath[n];n++) {
53285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(fullPath[n] == U_FILE_ALT_SEP_CHAR) {
53385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            fullPath[n] = U_FILE_SEP_CHAR;
53485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
53585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
53685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif
53785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif
53885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if (U_FILE_SEP_CHAR != U_TREE_ENTRY_SEP_CHAR)
53985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /* replace tree separator (such as '/') with file sep char (such as ':' or '\\') */
54085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    for(;fullPath[n];n++) {
54185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if(fullPath[n] == U_TREE_ENTRY_SEP_CHAR) {
54285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            fullPath[n] = U_FILE_SEP_CHAR;
54385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
54485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
54585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif
54685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return fullPath;
54785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
54885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
54985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic int
55085bf2e2fbc60a9f938064abc8127d61da7d19882Claire HocompareFiles(const void *file1, const void *file2) {
55185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /* sort by basename */
55285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return uprv_strcmp(((File *)file1)->basename, ((File *)file2)->basename);
55385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
55485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
55585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic void
55685bf2e2fbc60a9f938064abc8127d61da7d19882Claire HofixDirToTreePath(char *s)
55785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho{
55885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#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))
55985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    char *t;
56085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif
56185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if (U_FILE_SEP_CHAR != U_TREE_ENTRY_SEP_CHAR)
56285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    for(t=s;t=uprv_strchr(t,U_FILE_SEP_CHAR);) {
56385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        *t = U_TREE_ENTRY_SEP_CHAR;
56485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
56585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif
56685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if (U_FILE_ALT_SEP_CHAR != U_FILE_SEP_CHAR) && (U_FILE_ALT_SEP_CHAR != U_TREE_ENTRY_SEP_CHAR)
56785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    for(t=s;t=uprv_strchr(t,U_FILE_ALT_SEP_CHAR);) {
56885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        *t = U_TREE_ENTRY_SEP_CHAR;
56985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
57085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif
57185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
572