| 573 | } |
| 574 | |
| 575 | void parse_derived_core_properties(const char *filename) |
| 576 | { |
| 577 | FILE *f; |
| 578 | char line[4096], *p, buf[256], *q; |
| 579 | uint32_t c0, c1, c; |
| 580 | int i; |
| 581 | |
| 582 | f = fopen(filename, "rb"); |
| 583 | if (!f) { |
| 584 | perror(filename); |
| 585 | exit(1); |
| 586 | } |
| 587 | |
| 588 | for(;;) { |
| 589 | if (!get_line(line, sizeof(line), f)) |
| 590 | break; |
| 591 | p = line; |
| 592 | while (isspace(*p)) |
| 593 | p++; |
| 594 | if (*p == '#' || *p == '@' || *p == '\0') |
| 595 | continue; |
| 596 | c0 = strtoul(p, (char **)&p, 16); |
| 597 | if (*p == '.' && p[1] == '.') { |
| 598 | p += 2; |
| 599 | c1 = strtoul(p, (char **)&p, 16); |
| 600 | } else { |
| 601 | c1 = c0; |
| 602 | } |
| 603 | assert(c1 <= CHARCODE_MAX); |
| 604 | p += strspn(p, " \t"); |
| 605 | if (*p == ';') { |
| 606 | p++; |
| 607 | p += strspn(p, " \t"); |
| 608 | q = buf; |
| 609 | static const char ignore[] = "\t #;"; // includes \0 |
| 610 | while (!memchr(ignore, *p, sizeof(ignore))) { |
| 611 | if ((q - buf) < sizeof(buf) - 1) |
| 612 | *q++ = *p; |
| 613 | p++; |
| 614 | } |
| 615 | *q = '\0'; |
| 616 | i = find_name(unicode_prop_name, |
| 617 | countof(unicode_prop_name), buf); |
| 618 | if (i < 0) { |
| 619 | if (!strcmp(buf, "Grapheme_Link")) |
| 620 | goto next; |
| 621 | fprintf(stderr, "Property not found: %s\n", buf); |
| 622 | exit(1); |
| 623 | } |
| 624 | for(c = c0; c <= c1; c++) { |
| 625 | set_prop(c, i, 1); |
| 626 | } |
| 627 | next: ; |
| 628 | } |
| 629 | } |
| 630 | fclose(f); |
| 631 | } |
| 632 | |