~ubuntu-branches/ubuntu/gutsy/icu/gutsy-updates

« back to all changes in this revision

Viewing changes to source/tools/gencmn/decmn.c

  • Committer: Package Import Robot
  • Author(s): Jay Berkenbilt
  • Date: 2005-11-19 11:29:31 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20051119112931-vcizkrp10tli4enw
Tags: 3.4-3
Explicitly build with g++ 3.4.  The current ICU fails its test suite
with 4.0 but not with 3.4.  Future versions should work properly with
4.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
*******************************************************************************
3
 
*
4
 
*   Copyright (C) 2000-2001, International Business Machines
5
 
*   Corporation and others.  All Rights Reserved.
6
 
*
7
 
*******************************************************************************
8
 
*   file name:  decmn.c
9
 
*   encoding:   US-ASCII
10
 
*   tab size:   8 (not used)
11
 
*   indentation:4
12
 
*
13
 
*   created on: 2001mar05
14
 
*   created by: Markus W. Scherer
15
 
*   changes by: Yves Arrouye
16
 
*
17
 
*   This tool takes an ICU common data file (icuxyz.dat),
18
 
*   outputs a list of components,
19
 
*   and writes one file per packaged data piece in the common file.
20
 
*   This can be used to add, remove, or replace data.
21
 
*/
22
 
 
23
 
#include <stdio.h>
24
 
#include <stdlib.h>
25
 
#include "unicode/utypes.h"
26
 
#include "unicode/udata.h"
27
 
#include "uoptions.h"
28
 
#include "cstring.h"
29
 
 
30
 
static uint8_t buffer[100000], buffer2[128*1024];
31
 
 
32
 
static const char *pname;
33
 
 
34
 
static UOption options[]={
35
 
/*0*/ UOPTION_HELP_H,
36
 
/*1*/ UOPTION_HELP_QUESTION_MARK,
37
 
/*2*/ UOPTION_DESTDIR,
38
 
/*3*/ UOPTION_DEF(0, 'n', UOPT_NO_ARG),
39
 
/*4*/ UOPTION_DEF("comment", 'C', UOPT_NO_ARG),
40
 
};
41
 
 
42
 
static int
43
 
compareFiles(const void *file1, const void *file2) {
44
 
    /* sort by file offset */
45
 
    int32_t diff=*((int32_t *)file1+1)-*((int32_t *)file2+1);
46
 
    if(diff!=0) {
47
 
        return (int)(diff>>15)|1;
48
 
    } else {
49
 
        return 0;
50
 
    }
51
 
}
52
 
 
53
 
static int
54
 
copyFile(FILE *in, int32_t offset, int32_t size, const char *dir, const char *name) {
55
 
    FILE *out;
56
 
    int32_t length;
57
 
    char path[512], *p;
58
 
 
59
 
    if(0!=fseek(in, offset, SEEK_SET)) {
60
 
        fprintf(stderr, "%s: cannot seek to position %ld for file \"%s\"\n", pname,
61
 
            (long)offset, name);
62
 
        return 4;
63
 
    }
64
 
 
65
 
    uprv_strcpy(path, dir);
66
 
    p = path + strlen(path);
67
 
    if (p[-1] != U_FILE_SEP_CHAR) {
68
 
        *p++ = U_FILE_SEP_CHAR;
69
 
    }
70
 
    uprv_strcpy(p, name);
71
 
 
72
 
    out=fopen(path, "wb");
73
 
    if(out==NULL) {
74
 
        fprintf(stderr, "%s: unable to open output file \"%s\"\n", pname, path);
75
 
        return 5;
76
 
    }
77
 
 
78
 
    /* copy the contents into the new, separate file */
79
 
    while(size>sizeof(buffer2)) {
80
 
        length=(int32_t)fread(buffer2, 1, sizeof(buffer2), in);
81
 
        if(length<=0) {
82
 
            fprintf(stderr, "%s: read error while copying output file \"%s\"\n", pname, path);
83
 
            fclose(out);
84
 
            return 4;
85
 
        }
86
 
        if(length!=(int32_t)fwrite(buffer2, 1, length, out)) {
87
 
            fprintf(stderr, "%s: write error while copying output file \"%s\"\n", pname, path);
88
 
            fclose(out);
89
 
            return 5;
90
 
        }
91
 
        size-=length;
92
 
    }
93
 
    while(size>0) {
94
 
        length=(int32_t)fread(buffer2, 1, size, in);
95
 
        if(length<=0) {
96
 
            fprintf(stderr, "%s: read error while copying output file \"%s\"\n", pname, path);
97
 
            fclose(out);
98
 
            return 4;
99
 
        }
100
 
        if(length!=(int32_t)fwrite(buffer2, 1, length, out)) {
101
 
            fprintf(stderr, "%s: write error while copying output file \"%s\"\n", pname, path);
102
 
            fclose(out);
103
 
            return 5;
104
 
        }
105
 
        size-=length;
106
 
    }
107
 
 
108
 
    fclose(out);
109
 
    return 0;
110
 
}
111
 
 
112
 
extern int
113
 
main(int argc, char *argv[]) {
114
 
    FILE *in;
115
 
    UDataInfo *info;
116
 
    uint8_t *base;
117
 
    int32_t *p;
118
 
    int32_t i, length, count, baseOffset;
119
 
    int result, ishelp = 0;
120
 
 
121
 
    U_MAIN_INIT_ARGS(argc, argv);
122
 
 
123
 
    pname = uprv_strchr(*argv, U_FILE_SEP_CHAR);
124
 
#ifdef WIN32
125
 
    if (!pname) {
126
 
        pname = uprv_strchr(*argv, '/');
127
 
    }
128
 
#endif
129
 
    if (pname) {
130
 
        ++pname;
131
 
    } else {
132
 
        pname = argv[0];
133
 
    }
134
 
 
135
 
    options[2].value = ".";
136
 
 
137
 
    argc = u_parseArgs(argc, argv, sizeof(options) / sizeof(*options), options);
138
 
    ishelp = options[0].doesOccur || options[1].doesOccur;
139
 
    if (ishelp || argc != 2) {
140
 
        fprintf(stderr,
141
 
                "%csage: %s [ -h, -?, --help ] [ -n ] [ -C, --comment ] [ -d, --destdir destination ] archive\n", ishelp ? 'U' : 'u', pname);
142
 
        if (ishelp) {
143
 
            fprintf(stderr, "\nOptions: -h, -?, --help    print this message and exit\n"
144
 
                    "         -n                do not create files\n"
145
 
                    "         -C, --comment     print the comment embedded in the file and exit\n"
146
 
                    "         -d, --destdir destination    create files in destination\n");
147
 
        }
148
 
 
149
 
        return ishelp ? 0 : 1;
150
 
    }
151
 
 
152
 
    in=fopen(argv[1], "rb");
153
 
    if(in==NULL) {
154
 
        fprintf(stderr, "%s: unable to open input file \"%s\"\n", pname, argv[1]);
155
 
        return 2;
156
 
    }
157
 
 
158
 
    /* read the beginning of the file */
159
 
    length=(int32_t)fread(buffer, 1, sizeof(buffer), in);
160
 
    if(length<20) {
161
 
        fprintf(stderr, "%s: input file too short\n", pname);
162
 
        fclose(in);
163
 
        return 3;
164
 
    }
165
 
 
166
 
    /* check the validity of the file */
167
 
    if(buffer[2]!=0xda || buffer[3]!=0x27) {
168
 
        fprintf(stderr, "%s: not an ICU data file\n", pname);
169
 
        fclose(in);
170
 
        return 3;
171
 
    }
172
 
 
173
 
    /* check the platform properties for the file */
174
 
    info=(UDataInfo *)(buffer+4);
175
 
    if(info->isBigEndian!=U_IS_BIG_ENDIAN) {
176
 
        fprintf(stderr, "%s: the file is in the wrong byte endianness\n", pname);
177
 
        fclose(in);
178
 
        return 3;
179
 
    }
180
 
    if(info->charsetFamily!=U_CHARSET_FAMILY) {
181
 
        fprintf(stderr, "%s: the file is not built for this machine's charset family\n", pname);
182
 
        fclose(in);
183
 
        return 3;
184
 
    }
185
 
 
186
 
    /* check that this is a common data file */
187
 
    if(info->dataFormat[0]!=0x43 || info->dataFormat[1]!=0x6d || info->dataFormat[2]!=0x6e || info->dataFormat[3]!=0x44) {
188
 
        fprintf(stderr, "%s: this file is not a common data (archive) file\n", pname);
189
 
        fclose(in);
190
 
        return 3;
191
 
    }
192
 
 
193
 
    /* check for version 1 */
194
 
    if(info->formatVersion[0]!=1) {
195
 
        fprintf(stderr, "%s: the format version %d.%d.%d.%d is not known\n", pname,
196
 
                info->formatVersion[0], info->formatVersion[1], info->formatVersion[2], info->formatVersion[3]);
197
 
        fclose(in);
198
 
        return 3;
199
 
    }
200
 
 
201
 
    /* do we want to show the comment, and is there a comment? */
202
 
    if (options[4].doesOccur && *(uint16_t *)buffer>4+info->size) {
203
 
        printf("%s\n", buffer+4+info->size);
204
 
        return 0;
205
 
    }
206
 
 
207
 
    /* output all filenames */
208
 
    baseOffset=*(uint16_t *)buffer;
209
 
    base=buffer+baseOffset;
210
 
    p=(int32_t *)base;
211
 
    count=*p++;
212
 
    /* printf("files[%ld]\n", (long)count); */
213
 
    for(i=0; i<count; ++i) {
214
 
        printf("%s%c%s\n", options[2].value, U_FILE_SEP_CHAR, base+*p);
215
 
        p+=2;
216
 
    }
217
 
    /* puts("endfiles"); */
218
 
 
219
 
    if (options[3].doesOccur) { /* Do not extract. */
220
 
        return 0;
221
 
    }
222
 
 
223
 
    /* sort all files by their offsets in the common file */
224
 
    qsort(base+4, count, 8, compareFiles);
225
 
 
226
 
    /* write all files except the last one */
227
 
    p=(int32_t *)(base+4);
228
 
    --count;
229
 
    for(i=0; i<count; ++i) {
230
 
        /* the size is the difference between this file's offset and the next one's */
231
 
        result=copyFile(in, baseOffset+p[1], p[3]-p[1], options[2].value, (const char *)(base+*p));
232
 
        if(result!=0) {
233
 
            fclose(in);
234
 
            return result;
235
 
        }
236
 
        p+=2;
237
 
    }
238
 
 
239
 
    /* write the last file */
240
 
    if(count>=0) {
241
 
        /* the size is the number of bytes to the end of the common file */
242
 
        if(0!=fseek(in, 0, SEEK_END)) {
243
 
            fprintf(stderr, "%s: unable to seek to the end of the common file\n", pname);
244
 
            return 4;
245
 
        }
246
 
        result=copyFile(in, baseOffset+p[1], (int32_t)ftell(in)-baseOffset-p[1], options[2].value, (const char *)(base+*p));
247
 
        if(result!=0) {
248
 
            fclose(in);
249
 
            return result;
250
 
        }
251
 
    }
252
 
 
253
 
    fclose(in);
254
 
    return 0;
255
 
}
256
 
 
257
 
/*
258
 
 * Hey, Emacs, please set the following:
259
 
 *
260
 
 * Local Variables:
261
 
 * indent-tabs-mode: nil
262
 
 * End:
263
 
 *
264
 
 */