]>
Commit | Line | Data |
---|---|---|
c1382a3d | 1 | /* |
317b8492 | 2 | * fontconfig/fc-lang/fc-lang.c |
c1382a3d | 3 | * |
46b51147 | 4 | * Copyright © 2002 Keith Packard |
c1382a3d KP |
5 | * |
6 | * Permission to use, copy, modify, distribute, and sell this software and its | |
7 | * documentation for any purpose is hereby granted without fee, provided that | |
8 | * the above copyright notice appear in all copies and that both that | |
9 | * copyright notice and this permission notice appear in supporting | |
5aaf466d | 10 | * documentation, and that the name of the author(s) not be used in |
c1382a3d | 11 | * advertising or publicity pertaining to distribution of the software without |
5aaf466d | 12 | * specific, written prior permission. The authors make no |
c1382a3d KP |
13 | * representations about the suitability of this software for any purpose. It |
14 | * is provided "as is" without express or implied warranty. | |
15 | * | |
3074a73b | 16 | * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
c1382a3d | 17 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO |
3074a73b | 18 | * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
c1382a3d KP |
19 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, |
20 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |
21 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | |
22 | * PERFORMANCE OF THIS SOFTWARE. | |
23 | */ | |
24 | ||
c647f6f1 KP |
25 | #include "fccharset.c" |
26 | #include "fcstr.c" | |
e3096d90 | 27 | #include "fcserialize.c" |
c1382a3d KP |
28 | |
29 | /* | |
30 | * fc-lang | |
31 | * | |
32 | * Read a set of language orthographies and build C declarations for | |
33 | * charsets which can then be used to identify which languages are | |
c647f6f1 KP |
34 | * supported by a given font. Note that this uses some utilities |
35 | * from the fontconfig library, so the necessary file is simply | |
36 | * included in this compilation. A couple of extra utility | |
37 | * functions are also needed in slightly modified form | |
c1382a3d KP |
38 | */ |
39 | ||
c647f6f1 KP |
40 | void |
41 | FcMemAlloc (int kind, int size) | |
42 | { | |
43 | } | |
44 | ||
45 | void | |
46 | FcMemFree (int kind, int size) | |
47 | { | |
48 | } | |
49 | ||
afe5a671 KP |
50 | FcPrivate void |
51 | FcCacheObjectReference (void *object) | |
52 | { | |
53 | } | |
54 | ||
55 | FcPrivate void | |
56 | FcCacheObjectDereference (void *object) | |
57 | { | |
58 | } | |
59 | ||
18b6857c KP |
60 | int FcDebugVal; |
61 | ||
ff3f1f98 KP |
62 | FcChar8 * |
63 | FcConfigHome (void) | |
64 | { | |
8245771d | 65 | return (FcChar8 *) getenv ("HOME"); |
ff3f1f98 KP |
66 | } |
67 | ||
c1382a3d | 68 | static void |
67accef4 | 69 | fatal (const char *file, int lineno, const char *msg) |
c1382a3d | 70 | { |
67accef4 PL |
71 | if (lineno) |
72 | fprintf (stderr, "%s:%d: %s\n", file, lineno, msg); | |
73 | else | |
c7beacf9 | 74 | fprintf (stderr, "%s: %s\n", file, msg); |
c1382a3d KP |
75 | exit (1); |
76 | } | |
77 | ||
78 | static char * | |
0a023b24 | 79 | get_line (FILE *f, char *buf, int *lineno) |
c1382a3d KP |
80 | { |
81 | char *hash; | |
0a023b24 | 82 | char *line; |
cf5cf4ca | 83 | int end; |
0a023b24 BE |
84 | |
85 | next: | |
86 | line = buf; | |
c1382a3d KP |
87 | if (!fgets (line, 1024, f)) |
88 | return 0; | |
89 | ++(*lineno); | |
90 | hash = strchr (line, '#'); | |
91 | if (hash) | |
92 | *hash = '\0'; | |
cf5cf4ca | 93 | |
0a023b24 BE |
94 | while (line[0] && isspace (line[0])) |
95 | line++; | |
cf5cf4ca PL |
96 | end = strlen (line); |
97 | while (end > 0 && isspace (line[end-1])) | |
98 | line[--end] = '\0'; | |
99 | ||
0a023b24 BE |
100 | if (line[0] == '\0' || line[0] == '\n' || line[0] == '\r') |
101 | goto next; | |
102 | ||
c1382a3d KP |
103 | return line; |
104 | } | |
105 | ||
0d745819 | 106 | static char *dir = 0; |
394b2bf0 | 107 | |
6ae6acf3 | 108 | static FILE * |
394b2bf0 KP |
109 | scanopen (char *file) |
110 | { | |
111 | FILE *f; | |
112 | ||
113 | f = fopen (file, "r"); | |
114 | if (!f && dir) | |
115 | { | |
116 | char path[1024]; | |
117 | ||
118 | strcpy (path, dir); | |
119 | strcat (path, "/"); | |
120 | strcat (path, file); | |
121 | f = fopen (path, "r"); | |
122 | } | |
123 | return f; | |
124 | } | |
125 | ||
c1382a3d KP |
126 | /* |
127 | * build a single charset from a source file | |
128 | * | |
129 | * The file format is quite simple, either | |
130 | * a single hex value or a pair separated with a dash | |
131 | * | |
132 | * Comments begin with '#' | |
133 | */ | |
134 | ||
0a023b24 | 135 | static FcCharSet * |
18b6857c | 136 | scan (FILE *f, char *file, FcCharSetFreezer *freezer) |
c1382a3d | 137 | { |
18b6857c | 138 | FcCharSet *c = 0; |
ffd6668b | 139 | FcCharSet *n; |
0a023b24 | 140 | FcBool del; |
18b6857c | 141 | int start, end, ucs4; |
0a023b24 BE |
142 | char buf[1024]; |
143 | char *line; | |
18b6857c | 144 | int lineno = 0; |
c1382a3d | 145 | |
0a023b24 | 146 | while ((line = get_line (f, buf, &lineno))) |
c1382a3d KP |
147 | { |
148 | if (!strncmp (line, "include", 7)) | |
149 | { | |
f6993c88 BE |
150 | FILE *included_f; |
151 | char *included_file; | |
152 | included_file = strchr (line, ' '); | |
153 | if (!included_file) | |
154 | fatal (file, lineno, | |
04f7d3e7 | 155 | "invalid syntax, expected: include filename"); |
f6993c88 BE |
156 | while (isspace(*included_file)) |
157 | included_file++; | |
158 | included_f = scanopen (included_file); | |
159 | if (!included_f) | |
160 | fatal (included_file, 0, "can't open"); | |
161 | n = scan (included_f, included_file, freezer); | |
162 | fclose (included_f); | |
163 | if (!c) | |
164 | c = FcCharSetCreate (); | |
165 | if (!FcCharSetMerge (c, n, NULL)) | |
166 | fatal (file, lineno, "out of memory"); | |
167 | FcCharSetDestroy (n); | |
168 | continue; | |
c1382a3d | 169 | } |
0a023b24 BE |
170 | del = FcFalse; |
171 | if (line[0] == '-') | |
172 | { | |
173 | del = FcTrue; | |
174 | line++; | |
175 | } | |
c1382a3d KP |
176 | if (strchr (line, '-')) |
177 | { | |
178 | if (sscanf (line, "%x-%x", &start, &end) != 2) | |
179 | fatal (file, lineno, "parse error"); | |
180 | } | |
181 | else | |
182 | { | |
183 | if (sscanf (line, "%x", &start) != 1) | |
184 | fatal (file, lineno, "parse error"); | |
185 | end = start; | |
186 | } | |
187 | if (!c) | |
188 | c = FcCharSetCreate (); | |
189 | for (ucs4 = start; ucs4 <= end; ucs4++) | |
190 | { | |
0a023b24 | 191 | if (!((del ? FcCharSetDelChar : FcCharSetAddChar) (c, ucs4))) |
c1382a3d KP |
192 | fatal (file, lineno, "out of memory"); |
193 | } | |
194 | } | |
f0ee5761 | 195 | n = (FcCharSet *) FcCharSetFreeze (freezer, c); |
c1382a3d KP |
196 | FcCharSetDestroy (c); |
197 | return n; | |
198 | } | |
199 | ||
200 | /* | |
201 | * Convert a file name into a name suitable for C declarations | |
202 | */ | |
203 | static char * | |
204 | get_name (char *file) | |
205 | { | |
206 | char *name; | |
207 | char *dot; | |
208 | ||
209 | dot = strchr (file, '.'); | |
210 | if (!dot) | |
211 | dot = file + strlen(file); | |
212 | name = malloc (dot - file + 1); | |
213 | strncpy (name, file, dot - file); | |
214 | name[dot-file] = '\0'; | |
215 | return name; | |
216 | } | |
217 | ||
218 | /* | |
219 | * Convert a C name into a language name | |
220 | */ | |
221 | static char * | |
222 | get_lang (char *name) | |
223 | { | |
224 | char *lang = malloc (strlen (name) + 1); | |
225 | char *l = lang; | |
226 | char c; | |
227 | ||
228 | while ((c = *name++)) | |
229 | { | |
996580dc KP |
230 | if (isupper ((int) (unsigned char) c)) |
231 | c = tolower ((int) (unsigned char) c); | |
c1382a3d KP |
232 | if (c == '_') |
233 | c = '-'; | |
234 | if (c == ' ') | |
235 | continue; | |
236 | *l++ = c; | |
237 | } | |
238 | *l++ = '\0'; | |
239 | return lang; | |
240 | } | |
241 | ||
ffd6668b BE |
242 | typedef struct _Entry { |
243 | int id; | |
244 | char *file; | |
245 | } Entry; | |
246 | ||
d8d73958 KP |
247 | static int compare (const void *a, const void *b) |
248 | { | |
0a023b24 BE |
249 | const Entry *as = a, *bs = b; |
250 | return FcStrCmpIgnoreCase ((const FcChar8 *) as->file, (const FcChar8 *) bs->file); | |
d8d73958 KP |
251 | } |
252 | ||
234397b4 DD |
253 | #define MAX_LANG 1024 |
254 | #define MAX_LANG_SET_MAP ((MAX_LANG + 31) / 32) | |
255 | ||
ffd6668b BE |
256 | #define BitSet(map, i) ((map)[(entries[i].id)>>5] |= ((FcChar32) 1 << ((entries[i].id) & 0x1f))) |
257 | #define BitGet(map, i) ((map)[(entries[i].id)>>5] >> ((entries[i].id) & 0x1f)) & 1) | |
234397b4 | 258 | |
c1382a3d KP |
259 | int |
260 | main (int argc, char **argv) | |
261 | { | |
ffd6668b | 262 | static Entry entries[MAX_LANG]; |
0a023b24 | 263 | static FcCharSet *sets[MAX_LANG]; |
69a3fc78 | 264 | static int duplicate[MAX_LANG]; |
69a3fc78 PL |
265 | static int country[MAX_LANG]; |
266 | static char *names[MAX_LANG]; | |
267 | static char *langs[MAX_LANG]; | |
7ce19673 | 268 | static int off[MAX_LANG]; |
c1382a3d | 269 | FILE *f; |
234397b4 | 270 | int ncountry = 0; |
c1382a3d | 271 | int i = 0; |
7ce19673 | 272 | int nsets = 0; |
67accef4 | 273 | int argi; |
cd2ec1a9 | 274 | FcCharLeaf **leaves; |
c1382a3d | 275 | int total_leaves = 0; |
7ce19673 | 276 | int l, sl, tl, tn; |
69a3fc78 PL |
277 | static char line[1024]; |
278 | static FcChar32 map[MAX_LANG_SET_MAP]; | |
234397b4 | 279 | int num_lang_set_map; |
0eadb052 KP |
280 | int setRangeStart[26]; |
281 | int setRangeEnd[26]; | |
282 | FcChar8 setRangeChar; | |
18b6857c | 283 | FcCharSetFreezer *freezer; |
c1382a3d | 284 | |
18b6857c KP |
285 | freezer = FcCharSetFreezerCreate (); |
286 | if (!freezer) | |
287 | fatal (argv[0], 0, "out of memory"); | |
67accef4 PL |
288 | argi = 1; |
289 | while (argv[argi]) | |
234397b4 | 290 | { |
67accef4 | 291 | if (!strcmp (argv[argi], "-d")) |
394b2bf0 | 292 | { |
67accef4 PL |
293 | argi++; |
294 | dir = argv[argi++]; | |
394b2bf0 KP |
295 | continue; |
296 | } | |
234397b4 | 297 | if (i == MAX_LANG) |
67accef4 | 298 | fatal (argv[0], 0, "Too many languages"); |
ffd6668b BE |
299 | entries[i].id = i; |
300 | entries[i].file = argv[argi++]; | |
301 | i++; | |
234397b4 | 302 | } |
ffd6668b BE |
303 | entries[i].file = 0; |
304 | qsort (entries, i, sizeof (Entry), compare); | |
d8d73958 | 305 | i = 0; |
ffd6668b | 306 | while (entries[i].file) |
c1382a3d | 307 | { |
ffd6668b | 308 | f = scanopen (entries[i].file); |
c1382a3d | 309 | if (!f) |
ffd6668b BE |
310 | fatal (entries[i].file, 0, strerror (errno)); |
311 | sets[i] = scan (f, entries[i].file, freezer); | |
312 | names[i] = get_name (entries[i].file); | |
234397b4 DD |
313 | langs[i] = get_lang(names[i]); |
314 | if (strchr (langs[i], '-')) | |
315 | country[ncountry++] = i; | |
316 | ||
c1382a3d KP |
317 | total_leaves += sets[i]->num; |
318 | i++; | |
319 | fclose (f); | |
320 | } | |
7ce19673 | 321 | nsets = i; |
c1382a3d KP |
322 | sets[i] = 0; |
323 | leaves = malloc (total_leaves * sizeof (FcCharLeaf *)); | |
324 | tl = 0; | |
325 | /* | |
326 | * Find unique leaves | |
327 | */ | |
328 | for (i = 0; sets[i]; i++) | |
329 | { | |
c1382a3d KP |
330 | for (sl = 0; sl < sets[i]->num; sl++) |
331 | { | |
332 | for (l = 0; l < tl; l++) | |
7ce19673 | 333 | if (leaves[l] == FcCharSetLeaf(sets[i], sl)) |
c1382a3d KP |
334 | break; |
335 | if (l == tl) | |
7ce19673 | 336 | leaves[tl++] = FcCharSetLeaf(sets[i], sl); |
c1382a3d KP |
337 | } |
338 | } | |
339 | ||
340 | /* | |
341 | * Scan the input until the marker is found | |
342 | */ | |
343 | ||
344 | while (fgets (line, sizeof (line), stdin)) | |
345 | { | |
346 | if (!strncmp (line, "@@@", 3)) | |
347 | break; | |
348 | fputs (line, stdout); | |
349 | } | |
350 | ||
351 | printf ("/* total size: %d unique leaves: %d */\n\n", | |
352 | total_leaves, tl); | |
2903c146 KP |
353 | |
354 | /* | |
355 | * Find duplicate charsets | |
356 | */ | |
357 | duplicate[0] = -1; | |
358 | for (i = 1; sets[i]; i++) | |
359 | { | |
360 | int j; | |
361 | ||
362 | duplicate[i] = -1; | |
363 | for (j = 0; j < i; j++) | |
364 | if (sets[j] == sets[i]) | |
365 | { | |
366 | duplicate[i] = j; | |
367 | break; | |
368 | } | |
369 | } | |
370 | ||
7ce19673 KP |
371 | tn = 0; |
372 | for (i = 0; sets[i]; i++) { | |
373 | if (duplicate[i] >= 0) | |
374 | continue; | |
375 | off[i] = tn; | |
376 | tn += sets[i]->num; | |
377 | } | |
378 | ||
379 | printf ("#define LEAF0 (%d * sizeof (FcLangCharSet))\n", nsets); | |
380 | printf ("#define OFF0 (LEAF0 + %d * sizeof (FcCharLeaf))\n", tl); | |
78366844 | 381 | printf ("#define NUM0 (OFF0 + %d * sizeof (uintptr_t))\n", tn); |
7ce19673 | 382 | printf ("#define SET(n) (n * sizeof (FcLangCharSet) + offsetof (FcLangCharSet, charset))\n"); |
78366844 | 383 | printf ("#define OFF(s,o) (OFF0 + o * sizeof (uintptr_t) - SET(s))\n"); |
7ce19673 KP |
384 | printf ("#define NUM(s,n) (NUM0 + n * sizeof (FcChar16) - SET(s))\n"); |
385 | printf ("#define LEAF(o,l) (LEAF0 + l * sizeof (FcCharLeaf) - (OFF0 + o * sizeof (intptr_t)))\n"); | |
386 | printf ("#define fcLangCharSets (fcLangData.langCharSets)\n"); | |
ffd6668b | 387 | printf ("#define fcLangCharSetIndices (fcLangData.langIndices)\n"); |
d354a321 | 388 | printf ("#define fcLangCharSetIndicesInv (fcLangData.langIndicesInv)\n"); |
7ce19673 KP |
389 | printf ("\n"); |
390 | ||
391 | printf ("static const struct {\n" | |
392 | " FcLangCharSet langCharSets[%d];\n" | |
393 | " FcCharLeaf leaves[%d];\n" | |
78366844 | 394 | " uintptr_t leaf_offsets[%d];\n" |
7ce19673 | 395 | " FcChar16 numbers[%d];\n" |
ffd6668b | 396 | " FcChar%s langIndices[%d];\n" |
d354a321 | 397 | " FcChar%s langIndicesInv[%d];\n" |
7ce19673 | 398 | "} fcLangData = {\n", |
ffd6668b | 399 | nsets, tl, tn, tn, |
d354a321 | 400 | nsets < 256 ? "8 " : "16", nsets, nsets < 256 ? "8 " : "16", nsets); |
7ce19673 | 401 | |
0eadb052 | 402 | /* |
7ce19673 | 403 | * Dump sets |
0eadb052 | 404 | */ |
7ce19673 KP |
405 | |
406 | printf ("{\n"); | |
0eadb052 KP |
407 | for (i = 0; sets[i]; i++) |
408 | { | |
7ce19673 KP |
409 | int j = duplicate[i]; |
410 | ||
411 | if (j < 0) | |
412 | j = i; | |
413 | ||
e85789a9 | 414 | printf (" { \"%s\", " |
7ce19673 KP |
415 | " { FC_REF_CONSTANT, %d, OFF(%d,%d), NUM(%d,%d) } }, /* %d */\n", |
416 | langs[i], | |
417 | sets[j]->num, i, off[j], i, off[j], i); | |
0eadb052 | 418 | } |
7ce19673 | 419 | printf ("},\n"); |
0eadb052 | 420 | |
c1382a3d | 421 | /* |
7ce19673 | 422 | * Dump leaves |
c1382a3d | 423 | */ |
7ce19673 KP |
424 | printf ("{\n"); |
425 | for (l = 0; l < tl; l++) | |
c1382a3d | 426 | { |
7ce19673 KP |
427 | printf (" { { /* %d */", l); |
428 | for (i = 0; i < 256/32; i++) | |
82f35f8b | 429 | { |
7ce19673 KP |
430 | if (i % 4 == 0) |
431 | printf ("\n "); | |
432 | printf (" 0x%08x,", leaves[l]->map[i]); | |
82f35f8b | 433 | } |
7ce19673 | 434 | printf ("\n } },\n"); |
82f35f8b | 435 | } |
7ce19673 | 436 | printf ("},\n"); |
82f35f8b | 437 | |
7ce19673 KP |
438 | /* |
439 | * Dump leaves | |
440 | */ | |
441 | printf ("{\n"); | |
82f35f8b PL |
442 | for (i = 0; sets[i]; i++) |
443 | { | |
444 | int n; | |
445 | ||
446 | if (duplicate[i] >= 0) | |
447 | continue; | |
7ce19673 | 448 | printf (" /* %s */\n", names[i]); |
c1382a3d KP |
449 | for (n = 0; n < sets[i]->num; n++) |
450 | { | |
7ce19673 | 451 | if (n % 4 == 0) |
c1382a3d KP |
452 | printf (" "); |
453 | for (l = 0; l < tl; l++) | |
7ce19673 | 454 | if (leaves[l] == FcCharSetLeaf(sets[i], n)) |
c1382a3d KP |
455 | break; |
456 | if (l == tl) | |
457 | fatal (names[i], 0, "can't find leaf"); | |
7ce19673 KP |
458 | printf (" LEAF(%3d,%3d),", off[i], l); |
459 | if (n % 4 == 3) | |
c1382a3d KP |
460 | printf ("\n"); |
461 | } | |
7ce19673 | 462 | if (n % 4 != 0) |
c1382a3d | 463 | printf ("\n"); |
82f35f8b | 464 | } |
7ce19673 KP |
465 | printf ("},\n"); |
466 | ||
82f35f8b | 467 | |
7ce19673 | 468 | printf ("{\n"); |
82f35f8b PL |
469 | for (i = 0; sets[i]; i++) |
470 | { | |
471 | int n; | |
7ce19673 | 472 | |
a151aced PL |
473 | if (duplicate[i] >= 0) |
474 | continue; | |
7ce19673 | 475 | printf (" /* %s */\n", names[i]); |
c1382a3d KP |
476 | for (n = 0; n < sets[i]->num; n++) |
477 | { | |
478 | if (n % 8 == 0) | |
479 | printf (" "); | |
7ce19673 | 480 | printf (" 0x%04x,", FcCharSetNumbers (sets[i])[n]); |
c1382a3d KP |
481 | if (n % 8 == 7) |
482 | printf ("\n"); | |
483 | } | |
484 | if (n % 8 != 0) | |
485 | printf ("\n"); | |
c1382a3d | 486 | } |
ffd6668b BE |
487 | printf ("},\n"); |
488 | ||
d354a321 | 489 | /* langIndices */ |
ffd6668b BE |
490 | printf ("{\n"); |
491 | for (i = 0; sets[i]; i++) | |
492 | { | |
493 | printf (" %d, /* %s */\n", entries[i].id, names[i]); | |
494 | } | |
d354a321 BE |
495 | printf ("},\n"); |
496 | ||
497 | /* langIndicesInv */ | |
498 | printf ("{\n"); | |
499 | { | |
500 | static int entries_inv[MAX_LANG]; | |
501 | for (i = 0; sets[i]; i++) | |
502 | entries_inv[entries[i].id] = i; | |
503 | for (i = 0; sets[i]; i++) | |
504 | printf (" %d, /* %s */\n", entries_inv[i], names[entries_inv[i]]); | |
505 | } | |
7ce19673 | 506 | printf ("}\n"); |
d354a321 | 507 | |
c1382a3d | 508 | printf ("};\n\n"); |
d354a321 | 509 | |
234397b4 DD |
510 | printf ("#define NUM_LANG_CHAR_SET %d\n", i); |
511 | num_lang_set_map = (i + 31) / 32; | |
512 | printf ("#define NUM_LANG_SET_MAP %d\n", num_lang_set_map); | |
513 | /* | |
514 | * Dump indices with country codes | |
515 | */ | |
516 | if (ncountry) | |
517 | { | |
0d745819 | 518 | int c; |
234397b4 DD |
519 | int ncountry_ent = 0; |
520 | printf ("\n"); | |
521 | printf ("static const FcChar32 fcLangCountrySets[][NUM_LANG_SET_MAP] = {\n"); | |
522 | for (c = 0; c < ncountry; c++) | |
523 | { | |
524 | i = country[c]; | |
525 | if (i >= 0) | |
526 | { | |
0d745819 | 527 | int lang = strchr (langs[i], '-') - langs[i]; |
234397b4 DD |
528 | int d, k; |
529 | ||
530 | for (k = 0; k < num_lang_set_map; k++) | |
531 | map[k] = 0; | |
532 | ||
533 | BitSet (map, i); | |
534 | for (d = c + 1; d < ncountry; d++) | |
535 | { | |
536 | int j = country[d]; | |
bb36e676 | 537 | if (j >= 0 && !strncmp (langs[j], langs[i], lang + 1)) |
234397b4 DD |
538 | { |
539 | BitSet(map, j); | |
540 | country[d] = -1; | |
541 | } | |
542 | } | |
543 | printf (" {"); | |
544 | for (k = 0; k < num_lang_set_map; k++) | |
545 | printf (" 0x%08x,", map[k]); | |
546 | printf (" }, /* %*.*s */\n", | |
0d745819 | 547 | lang, lang, langs[i]); |
234397b4 DD |
548 | ++ncountry_ent; |
549 | } | |
550 | } | |
551 | printf ("};\n\n"); | |
552 | printf ("#define NUM_COUNTRY_SET %d\n", ncountry_ent); | |
553 | } | |
554 | ||
0eadb052 | 555 | |
7ce19673 KP |
556 | /* |
557 | * Find ranges for each letter for faster searching | |
558 | */ | |
559 | setRangeChar = 'a'; | |
560 | memset(setRangeStart, '\0', sizeof (setRangeStart)); | |
561 | memset(setRangeEnd, '\0', sizeof (setRangeEnd)); | |
562 | for (i = 0; sets[i]; i++) | |
563 | { | |
564 | char c = names[i][0]; | |
565 | ||
566 | while (setRangeChar <= c && c <= 'z') | |
567 | setRangeStart[setRangeChar++ - 'a'] = i; | |
568 | } | |
569 | for (setRangeChar = 'a'; setRangeChar < 'z'; setRangeChar++) | |
570 | setRangeEnd[setRangeChar - 'a'] = setRangeStart[setRangeChar+1-'a'] - 1; | |
571 | setRangeEnd[setRangeChar - 'a'] = i - 1; | |
572 | ||
0eadb052 KP |
573 | /* |
574 | * Dump sets start/finish for the fastpath | |
575 | */ | |
ffd6668b | 576 | printf ("\n"); |
0eadb052 | 577 | printf ("static const FcLangCharSetRange fcLangCharSetRanges[] = {\n"); |
ffd6668b | 578 | printf ("\n"); |
0eadb052 KP |
579 | for (setRangeChar = 'a'; setRangeChar <= 'z' ; setRangeChar++) |
580 | { | |
581 | printf (" { %d, %d }, /* %c */\n", | |
582 | setRangeStart[setRangeChar - 'a'], | |
583 | setRangeEnd[setRangeChar - 'a'], setRangeChar); | |
584 | } | |
585 | printf ("};\n\n"); | |
586 | ||
c1382a3d KP |
587 | while (fgets (line, sizeof (line), stdin)) |
588 | fputs (line, stdout); | |
589 | ||
590 | fflush (stdout); | |
591 | exit (ferror (stdout)); | |
592 | } |