| 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 | } |