1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | #include "fccharset.c" |
26 | #include "fcstr.c" |
27 | #include "fcserialize.c" |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
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 | |
134 | |
135 | |
136 | |
137 | |
138 | |
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))) |
| 1 | Loop condition is true. Entering loop body |
|
| 11 | Loop condition is true. Entering loop body |
|
| 19 | Loop condition is true. Entering loop body |
|
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) |
| 21 | Assuming 'included_file' is null |
|
| |
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)) |
| 23 | Within the expansion of the macro 'isspace':
|
a | Dereference of null pointer (loaded from variable 'included_file') |
|
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) |
| |
| 16 | Assuming 'c' is non-null |
|
| |
194 | c = FcCharSetCreate (); |
195 | for (ucs4 = start; ucs4 <= end; ucs4++) |
| 7 | Loop condition is true. Entering loop body |
|
| 10 | Loop condition is false. Execution continues on line 152 |
|
| 18 | Loop condition is false. Execution continues on line 152 |
|
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | } |