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