1 // © 2017 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 *******************************************************************************
5 *
6 * Copyright (C) 1999-2012, International Business Machines
7 * Corporation and others. All Rights Reserved.
8 *
9 *******************************************************************************
10 * file name: genprops.cpp
11 * encoding: US-ASCII
12 * tab size: 8 (not used)
13 * indentation:4
14 *
15 * created on: 1999dec08
16 * created by: Markus W. Scherer
17 *
18 * This program parses the ppucd.txt preparsed Unicode Character Database file
19 * and writes several source and binary files into the ICU source tree.
20 */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include "unicode/utypes.h"
25 #include "unicode/localpointer.h"
26 #include "unicode/uniset.h"
27 #include "unicode/unistr.h"
28 #include "charstr.h"
29 #include "genprops.h"
30 #include "ppucd.h"
31 #include "toolutil.h"
32 #include "uoptions.h"
33
34 U_NAMESPACE_USE
35
36 UBool beVerbose=false;
37 UBool beQuiet=false;
38
PropsBuilder()39 PropsBuilder::PropsBuilder() {}
~PropsBuilder()40 PropsBuilder::~PropsBuilder() {}
setUnicodeVersion(const UVersionInfo)41 void PropsBuilder::setUnicodeVersion(const UVersionInfo) {}
setAlgNamesRange(UChar32,UChar32,const char *,const char *,UErrorCode &)42 void PropsBuilder::setAlgNamesRange(UChar32, UChar32,
43 const char *, const char *, UErrorCode &) {}
setProps(const UniProps &,const UnicodeSet &,UErrorCode &)44 void PropsBuilder::setProps(const UniProps &, const UnicodeSet &, UErrorCode &) {}
parseUnidataFiles(const char *,UErrorCode &)45 void PropsBuilder::parseUnidataFiles(const char *, UErrorCode &) {}
build(UErrorCode &)46 void PropsBuilder::build(UErrorCode &) {}
writeCSourceFile(const char *,UErrorCode &)47 void PropsBuilder::writeCSourceFile(const char *, UErrorCode &) {}
writeJavaSourceFile(const char *,UErrorCode &)48 void PropsBuilder::writeJavaSourceFile(const char *, UErrorCode &) {}
writeBinaryData(const char *,UBool,UErrorCode &)49 void PropsBuilder::writeBinaryData(const char *, UBool, UErrorCode &) {}
50
51 enum {
52 HELP_H,
53 HELP_QUESTION_MARK,
54 VERBOSE,
55 QUIET,
56 COPYRIGHT
57 };
58
59 /* Keep these values in sync with the above enums */
60 static UOption options[]={
61 UOPTION_HELP_H,
62 UOPTION_HELP_QUESTION_MARK,
63 UOPTION_VERBOSE,
64 UOPTION_QUIET,
65 UOPTION_COPYRIGHT
66 };
67
68 extern int
main(int argc,char * argv[])69 main(int argc, char* argv[]) {
70 U_MAIN_INIT_ARGS(argc, argv);
71 argc=u_parseArgs(argc, argv, LENGTHOF(options), options);
72
73 /* error handling, printing usage message */
74 if(argc<0) {
75 fprintf(stderr,
76 "error in command line argument \"%s\"\n",
77 argv[-argc]);
78 }
79 if(argc<2 || options[HELP_H].doesOccur || options[HELP_QUESTION_MARK].doesOccur) {
80 /*
81 * Broken into chunks because the C89 standard says the minimum
82 * required supported string length is 509 bytes.
83 */
84 fprintf(stderr,
85 "Usage: %s [-options] path/to/ICU/src/root\n"
86 "\n"
87 "Reads the preparsed UCD file path/to/ICU/src/root/source/data/unidata/ppucd.txt and\n"
88 "writes source and binary data files with the character properties.\n"
89 "(UCD=Unicode Character Database)\n"
90 "\n",
91 argv[0]);
92 fprintf(stderr,
93 "Options:\n"
94 "\t-h or -? or --help this usage text\n"
95 "\t-v or --verbose verbose output\n"
96 "\t-q or --quiet no output\n"
97 "\t-c or --copyright include a copyright notice\n");
98 return argc<2 ? U_ILLEGAL_ARGUMENT_ERROR : U_ZERO_ERROR;
99 }
100
101 /* get the options values */
102 beVerbose=options[VERBOSE].doesOccur;
103 beQuiet=options[QUIET].doesOccur;
104
105 /* initialize */
106 IcuToolErrorCode errorCode("genprops");
107 LocalPointer<PNamesBuilder> pnamesBuilder(createPNamesBuilder(errorCode));
108 LocalPointer<PropsBuilder> corePropsBuilder(createCorePropsBuilder(errorCode));
109 LocalPointer<PropsBuilder> bidiPropsBuilder(createBiDiPropsBuilder(errorCode));
110 LocalPointer<PropsBuilder> casePropsBuilder(createCasePropsBuilder(errorCode));
111 LocalPointer<PropsBuilder> layoutPropsBuilder(createLayoutPropsBuilder(errorCode));
112 LocalPointer<PropsBuilder> emojiPropsBuilder(createEmojiPropsBuilder(errorCode));
113 LocalPointer<PropsBuilder> namesPropsBuilder(createNamesPropsBuilder(errorCode));
114 if(errorCode.isFailure()) {
115 fprintf(stderr, "genprops: unable to create PropsBuilders - %s\n", errorCode.errorName());
116 return errorCode.reset();
117 }
118
119 CharString icuSrcRoot(argv[1], errorCode);
120
121 CharString icuSource(icuSrcRoot, errorCode);
122 icuSource.appendPathPart("source", errorCode);
123
124 CharString icuSourceData(icuSource, errorCode);
125 icuSourceData.appendPathPart("data", errorCode);
126
127 CharString unidataPath(icuSourceData, errorCode);
128 unidataPath.appendPathPart("unidata", errorCode);
129
130 CharString ppucdPath(unidataPath, errorCode);
131 ppucdPath.appendPathPart("ppucd.txt", errorCode);
132
133 PreparsedUCD ppucd(ppucdPath.data(), errorCode);
134 if(errorCode.isFailure()) {
135 fprintf(stderr, "genprops: unable to open %s - %s\n",
136 ppucdPath.data(), errorCode.errorName());
137 return errorCode.reset();
138 }
139
140 // The PNamesBuilder uses preparsed pnames_data.h.
141 pnamesBuilder->build(errorCode);
142 if(U_FAILURE(errorCode)) {
143 fprintf(stderr, "genprops: PNamesBuilder::build() failed - %s\n",
144 errorCode.errorName());
145 return errorCode.reset();
146 }
147 ppucd.setPropertyNames(pnamesBuilder->getPropertyNames());
148
149 PreparsedUCD::LineType lineType;
150 UnicodeSet newValues;
151 while((lineType=ppucd.readLine(errorCode))!=PreparsedUCD::NO_LINE) {
152 if(ppucd.lineHasPropertyValues()) {
153 const UniProps *props=ppucd.getProps(newValues, errorCode);
154 corePropsBuilder->setProps(*props, newValues, errorCode);
155 bidiPropsBuilder->setProps(*props, newValues, errorCode);
156 casePropsBuilder->setProps(*props, newValues, errorCode);
157 layoutPropsBuilder->setProps(*props, newValues, errorCode);
158 emojiPropsBuilder->setProps(*props, newValues, errorCode);
159 namesPropsBuilder->setProps(*props, newValues, errorCode);
160 } else if(lineType==PreparsedUCD::UNICODE_VERSION_LINE) {
161 const UVersionInfo &version=ppucd.getUnicodeVersion();
162 corePropsBuilder->setUnicodeVersion(version);
163 bidiPropsBuilder->setUnicodeVersion(version);
164 casePropsBuilder->setUnicodeVersion(version);
165 layoutPropsBuilder->setUnicodeVersion(version);
166 emojiPropsBuilder->setUnicodeVersion(version);
167 namesPropsBuilder->setUnicodeVersion(version);
168 } else if(lineType==PreparsedUCD::ALG_NAMES_RANGE_LINE) {
169 UChar32 start, end;
170 if(ppucd.getRangeForAlgNames(start, end, errorCode)) {
171 const char *type=ppucd.nextField();
172 const char *prefix=ppucd.nextField(); // NULL if type==hangul
173 namesPropsBuilder->setAlgNamesRange(start, end, type, prefix, errorCode);
174 }
175 }
176 if(errorCode.isFailure()) {
177 fprintf(stderr,
178 "genprops: error parsing or setting values from ppucd.txt line %ld - %s\n",
179 (long)ppucd.getLineNumber(), errorCode.errorName());
180 return errorCode.reset();
181 }
182 }
183
184 emojiPropsBuilder->parseUnidataFiles(unidataPath.data(), errorCode);
185
186 if (!beQuiet) { puts(""); }
187 corePropsBuilder->build(errorCode);
188 if (!beQuiet) { puts(""); }
189 bidiPropsBuilder->build(errorCode);
190 if (!beQuiet) { puts(""); }
191 casePropsBuilder->build(errorCode);
192 if (!beQuiet) { puts(""); }
193 layoutPropsBuilder->build(errorCode);
194 if (!beQuiet) { puts(""); }
195 emojiPropsBuilder->build(errorCode);
196 if (!beQuiet) { puts(""); }
197 namesPropsBuilder->build(errorCode);
198 if(errorCode.isFailure()) {
199 fprintf(stderr, "genprops error: failure finalizing the data - %s\n",
200 errorCode.errorName());
201 return errorCode.reset();
202 }
203
204 // Write the files with the generated data.
205 CharString sourceCommon(icuSource, errorCode);
206 sourceCommon.appendPathPart("common", errorCode);
207
208 CharString sourceDataIn(icuSourceData, errorCode);
209 sourceDataIn.appendPathPart("in", errorCode);
210
211 UBool withCopyright=options[COPYRIGHT].doesOccur;
212
213 pnamesBuilder->writeCSourceFile(sourceCommon.data(), errorCode);
214 pnamesBuilder->writeBinaryData(sourceDataIn.data(), withCopyright, errorCode);
215 corePropsBuilder->writeCSourceFile(sourceCommon.data(), errorCode);
216 corePropsBuilder->writeBinaryData(sourceDataIn.data(), withCopyright, errorCode);
217 bidiPropsBuilder->writeCSourceFile(sourceCommon.data(), errorCode);
218 bidiPropsBuilder->writeBinaryData(sourceDataIn.data(), withCopyright, errorCode);
219 casePropsBuilder->writeCSourceFile(sourceCommon.data(), errorCode);
220 casePropsBuilder->writeBinaryData(sourceDataIn.data(), withCopyright, errorCode);
221 namesPropsBuilder->writeBinaryData(sourceDataIn.data(), withCopyright, errorCode);
222 layoutPropsBuilder->writeBinaryData(sourceDataIn.data(), withCopyright, errorCode);
223 emojiPropsBuilder->writeBinaryData(sourceDataIn.data(), withCopyright, errorCode);
224
225 return errorCode;
226 }
227
228 /*
229 * Hey, Emacs, please set the following:
230 *
231 * Local Variables:
232 * indent-tabs-mode: nil
233 * End:
234 *
235 */
236