From 1bc3cedf6d2df394ceca7b68d19cb17980045e97 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Thu, 19 Jan 2023 23:05:23 +0100 Subject: Add encoding parsing and m fix libfonts_parse_alias_line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- Makefile | 5 + libfonts.h | 311 +++++++++++++++ libfonts_deallocate_encoding.c | 38 ++ libfonts_deallocate_encoding_mapping.c | 32 ++ libfonts_deallocate_encoding_mapping_entry.c | 19 + ...allocate_encoding_mapping_entry_index_to_name.c | 26 ++ libfonts_parse_alias_line.c | 2 +- libfonts_parse_encoding_line.c | 439 +++++++++++++++++++++ 8 files changed, 871 insertions(+), 1 deletion(-) create mode 100644 libfonts_deallocate_encoding.c create mode 100644 libfonts_deallocate_encoding_mapping.c create mode 100644 libfonts_deallocate_encoding_mapping_entry.c create mode 100644 libfonts_deallocate_encoding_mapping_entry_index_to_name.c create mode 100644 libfonts_parse_encoding_line.c diff --git a/Makefile b/Makefile index 7f43c72..7e967fd 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,10 @@ LIB_NAME = fonts PUBLIC_OBJ =\ libfonts_calculate_subpixel_order.o\ libfonts_char_is_in_subset.o\ + libfonts_deallocate_encoding.o\ + libfonts_deallocate_encoding_mapping.o\ + libfonts_deallocate_encoding_mapping_entry.o\ + libfonts_deallocate_encoding_mapping_entry_index_to_name.o\ libfonts_decode_font_description.o\ libfonts_do_decoded_font_descriptions_match.o\ libfonts_do_font_descriptions_match.o\ @@ -32,6 +36,7 @@ PUBLIC_OBJ =\ libfonts_get_subpixel_order_class.o\ libfonts_parse_alias_line.o\ libfonts_parse_dir_line.o\ + libfonts_parse_encoding_line.o\ libfonts_unget_subpixel_order_class.o\ libfonts_used_environs.o diff --git a/libfonts.h b/libfonts.h index a79941e..b39989b 100644 --- a/libfonts.h +++ b/libfonts.h @@ -1663,6 +1663,245 @@ struct libfonts_font_description { char _buf[256]; }; + +/** + * Text encoding translation mapping entry type + */ +enum libfonts_encoding_mapping_entry_type { + /** + * Text encoding translation mapping entry that declares + * a contiguous character range as invalid (unless + * mapped later on) + */ + LIBFONTS_ENCODING_MAPPING_ENTRY_UNDEFINED_RANGE, + + /** + * Text encoding translation mapping entry that declares + * how a contiguous range of characters index are mapped + * into the target encoding + */ + LIBFONTS_ENCODING_MAPPING_ENTRY_REMAPPED_RANGE, + + /** + * Text encoding translation mapping entry that declares + * which name, in the target encoding, a character in the + * source encoding has + */ + LIBFONTS_ENCODING_MAPPING_ENTRY_INDEX_TO_NAME +}; + + +/** + * Text encoding translation mapping entry that declares + * a contiguous character range as invalid (unless + * mapped later on) + */ +struct libfonts_encoding_mapping_entry_undefined_range { + /** + * Text encoding translation mapping entry type + * + * Should be `LIBFONTS_ENCODING_MAPPING_ENTRY_UNDEFINED_RANGE` + * for this `struct` + */ + enum libfonts_encoding_mapping_entry_type type; + + /** + * The lowest character index in the invalidated range + */ + uint32_t low_source; + + /** + * The highest character index in the invalidated range + */ + uint32_t high_source; +}; + + +/** + * Text encoding translation mapping entry that declares + * how a contiguous range of characters index are mapped + * into the target encoding + * + * For each character index `i` in the range [`.low_source`, + * `.high_source`] in the source encoding, the index in the + * target encoding is `i - .low_source + .low_target` + */ +struct libfonts_encoding_mapping_entry_remapped_range { + /** + * Text encoding translation mapping entry type + * + * Should be `LIBFONTS_ENCODING_MAPPING_ENTRY_REMAPPED_RANGE` + * for this `struct` + */ + enum libfonts_encoding_mapping_entry_type type; + + /** + * The lowest character index, in the source + * encoding, in the range of affected characters + * in the mapped range + */ + uint32_t low_source; + + /** + * The highest character index, in the source + * encoding, in the range of affected characters + * in the mapped range + */ + uint32_t high_source; + + /** + * The lowest character index, in the target + * encoding, in the range of affected characters + * in the mapped range + */ + uint32_t low_target; +}; + + +/** + * Text encoding translation mapping entry that declares + * which name, in the target encoding, a character in the + * source encoding has + */ +struct libfonts_encoding_mapping_entry_index_to_name { + /** + * Text encoding translation mapping entry type + * + * Should be `LIBFONTS_ENCODING_MAPPING_ENTRY_INDEX_TO_NAME` + * for this `struct` + */ + enum libfonts_encoding_mapping_entry_type type; + + /** + * The index of the character in the source encoding + */ + uint32_t source; + + /** + * The name of the character in the target encoding + */ + char *target; +}; + + +/** + * Text encoding translation mapping entry + */ +union libfonts_encoding_mapping_entry { + /** + * Text encoding translation mapping entry type + */ + enum libfonts_encoding_mapping_entry_type type; + + /** + * Used if `.type` is `LIBFONTS_ENCODING_MAPPING_ENTRY_UNDEFINED_RANGE` + */ + struct libfonts_encoding_mapping_entry_undefined_range undefined_range; + + /** + * Used if `.type` is `LIBFONTS_ENCODING_MAPPING_ENTRY_REMAPPED_RANGE` + */ + struct libfonts_encoding_mapping_entry_remapped_range remapped_range; + + /** + * Used if `.type` is `LIBFONTS_ENCODING_MAPPING_ENTRY_INDEX_TO_NAME` + */ + struct libfonts_encoding_mapping_entry_index_to_name index_to_name; +}; + + +/** + * Structure containing text encoding a mapping + */ +struct libfonts_encoding_mapping { + /** + * The name of the target encoding + * + * Valid names are: + * - "unicode": mapping to USC-2, + * - "postscript": mapping to PostScript character names, and + * - "cmap $1 $2" where $1 and $2 are numbers for the Unicode + * "cmap" tables, using in TrueType: platform ID + * ($1) and encoding ($2); "cmap 3 4" is commonly + * used and would be the Windows platforms' Big5 + * encoding + */ + char *target; + + /** + * List of mapping entries + * + * Indentity mappings are normally not included + */ + union libfonts_encoding_mapping_entry *entries; + + /** + * The number of elements in `.entries` + */ + size_t nentries; +}; + + +/** + * Structure containing text encoding mappings + * and encoding information + */ +struct libfonts_encoding { + /** + * The canoncial name of the encoding + */ + char *name; + + /** + * List of alternative names for the encoding + */ + char **aliases; + + /** + * The number of elements in `.aliases` + */ + size_t naliases; + + /** + * List of coded translation mappings + */ + struct libfonts_encoding_mapping *mappings; + /* TODO add functions for creating tables in either direction */ + + /** + * The number of elements in `.mappings` + */ + size_t nmappings; + + /** + * The highest valid value of the first byte + * of a character, plus 1 + */ + uint16_t size_rows; + + /** + * The highest valid value of the second byte + * of a character, plus 1; or 0 if each character + * one has one byte + */ + uint16_t size_cols; + + /** + * The value of the first byte in the lowest + * valid character + */ + uint8_t first_index_row; + + /** + * The value of the second byte in the lowest + * valid character + * + * Only used if `.size_cols > 0` + */ + uint8_t first_index_col; +}; + + /** * Structure that can be used to spoof the * environment the library is executed in, @@ -1846,6 +2085,78 @@ int libfonts_char_is_in_subset(uint32_t, const char *); /* TODO add font listing */ +/** + * The deallocate memory allocate for a `struct libfonts_encoding_mapping_entry_index_to_name`, + * but do not deallocate the `struct libfonts_encoding_mapping_entry_index_to_name` itself + * + * @param this Pointer to the `struct libfonts_encoding_mapping_entry_index_to_name` + */ +void libfonts_deallocate_encoding_mapping_entry_index_to_name(struct libfonts_encoding_mapping_entry_index_to_name *); + +/** + * The deallocate memory allocate for a `union libfonts_encoding_mapping_entry`, + * but do not deallocate the `union libfonts_encoding_mapping_entry` itself + * + * @param this Pointer to the `struct libfonts_encoding_mapping_entry` + */ +inline void +libfonts_deallocate_encoding_mapping_entry(union libfonts_encoding_mapping_entry *this) +{ + if (this && this->type == LIBFONTS_ENCODING_MAPPING_ENTRY_INDEX_TO_NAME) + libfonts_deallocate_encoding_mapping_entry_index_to_name(&this->index_to_name); +} + +/** + * The deallocate memory allocate for a `struct libfonts_encoding_mapping`, + * but do not deallocate the `struct libfonts_encoding_mapping` itself + * + * @param this Pointer to the `struct libfonts_encoding_mapping` + */ +void libfonts_deallocate_encoding_mapping(struct libfonts_encoding_mapping *); + +/** + * The deallocate memory allocate for a `struct libfonts_encoding`, + * but do not deallocate the `struct libfonts_encoding` itself + * + * @param this Pointer to the `struct libfonts_encoding` + */ +void libfonts_deallocate_encoding(struct libfonts_encoding *); + +/** + * Parse line from an encoding file and add it to an encoding structure + * + * @param encodingp Pointer to a pointer to the encoding information being + * built from the encoding file; or a pointer to `NULL` + * if it shall be allocated by the function once the + * beginning of the encoding has been found. + * Unless `*encodingp` is `NULL`, it shall being as + * zero-initialised, except lists may be preallocated. + * @param statep Pointer to some memory that the function may use to + * keep track of its state; should point to 0 initially + * @param line The line to parse; parsing stops at the first newline + * or NUL byte + * @param endp Output parameter for the parsing end, i.e. the first + * newline or NUL byte in `line` + * @param ctx Optional `struct libfonts_context` + * @return 1 if the end of the encoding has been reached (the file + * may contain another one, which is not recommended), + * 0 on success otherwise, or -1 on failure + * + * @throws ENOMEM Failed to allocate required memory + * @throws EINVAL `encodingp` is `NULL` + * @throws EINVAL `*encodingp` is `NULL` but `*statep` indicates otherwise + * @throws EINVAL The contents of `*encodingp` is invalid for the value of `*statep` + * @throws EINVAL The contents of `*encodingp` is invalid + * @throws EINVAL `statep` is `NULL` + * @throws EINVAL `*statep` is invalid + * @throws EINVAL `line` is `NULL` + * + * No memory is deallocated on failure. + * `*endp` is updated even on failure. + */ +int libfonts_parse_encoding_line(struct libfonts_encoding **, int *, const char *, char **, struct libfonts_context *); + + /** * Get the font a default font name aliases to * diff --git a/libfonts_deallocate_encoding.c b/libfonts_deallocate_encoding.c new file mode 100644 index 0000000..6adbb5e --- /dev/null +++ b/libfonts_deallocate_encoding.c @@ -0,0 +1,38 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + + +void +libfonts_deallocate_encoding(struct libfonts_encoding *this) +{ + if (this) { + if (this->mappings) { + while (this->nmappings) + libfonts_deallocate_encoding_mapping(&this->mappings[--this->nmappings]); + free(this->mappings); + this->mappings = NULL; + } + if (this->aliases) { + while (this->naliases) + free(this->aliases[--this->naliases]); + free(this->aliases); + this->aliases = NULL; + } + free(this->name); + this->name = NULL; + } +} + + +#else + + +int +main(void) +{ + return 0; /* XXX add test */ +} + + +#endif diff --git a/libfonts_deallocate_encoding_mapping.c b/libfonts_deallocate_encoding_mapping.c new file mode 100644 index 0000000..e54fa5e --- /dev/null +++ b/libfonts_deallocate_encoding_mapping.c @@ -0,0 +1,32 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + + +void +libfonts_deallocate_encoding_mapping(struct libfonts_encoding_mapping *this) +{ + if (this) { + if (this->entries) { + while (this->nentries) + libfonts_deallocate_encoding_mapping_entry(&this->entries[--this->nentries]); + free(this->entries); + this->entries = NULL; + } + free(this->target); + this->target = NULL; + } +} + + +#else + + +int +main(void) +{ + return 0; /* XXX add test */ +} + + +#endif diff --git a/libfonts_deallocate_encoding_mapping_entry.c b/libfonts_deallocate_encoding_mapping_entry.c new file mode 100644 index 0000000..b032f45 --- /dev/null +++ b/libfonts_deallocate_encoding_mapping_entry.c @@ -0,0 +1,19 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + + +extern inline void libfonts_deallocate_encoding_mapping_entry(union libfonts_encoding_mapping_entry *); + + +#else + + +int +main(void) +{ + return 0; /* XXX add test */ +} + + +#endif diff --git a/libfonts_deallocate_encoding_mapping_entry_index_to_name.c b/libfonts_deallocate_encoding_mapping_entry_index_to_name.c new file mode 100644 index 0000000..ebabbf2 --- /dev/null +++ b/libfonts_deallocate_encoding_mapping_entry_index_to_name.c @@ -0,0 +1,26 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + + +void +libfonts_deallocate_encoding_mapping_entry_index_to_name(struct libfonts_encoding_mapping_entry_index_to_name *this) +{ + if (this) { + free(this->target); + this->target = NULL; + } +} + + +#else + + +int +main(void) +{ + return 0; /* XXX add test */ +} + + +#endif diff --git a/libfonts_parse_alias_line.c b/libfonts_parse_alias_line.c index 3e712e2..da9ad90 100644 --- a/libfonts_parse_alias_line.c +++ b/libfonts_parse_alias_line.c @@ -137,10 +137,10 @@ fail: *namep = NULL; } ret = -1; +out: if (line) while (*line && *line != '\n') line++; -out: if (endp) *endp = *(char **)(void *)&line; if (typep) diff --git a/libfonts_parse_encoding_line.c b/libfonts_parse_encoding_line.c new file mode 100644 index 0000000..a4d876b --- /dev/null +++ b/libfonts_parse_encoding_line.c @@ -0,0 +1,439 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + + +#define LEVEL_MASK 0x0003 +#define ENCODING_LEVEL 1 +#define MAPPING_LEVEL 2 +#define MAX_LEVEL MAPPING_LEVEL +#define HAVE_SIZE_BIT 0x4000 +#define HAVE_FIRST_INDEX_BIT 0x2000 +#define HAVE_FIRST_INDEX_BYTE_2_BIT 0x1000 +#define HAVE_BITS (HAVE_SIZE_BIT | HAVE_FIRST_INDEX_BIT | HAVE_FIRST_INDEX_BYTE_2_BIT) + +enum keyword { + NO_KEYWORD, + STARTENCODING, + ENDENCODING, + ALIAS, + SIZE, + FIRSTINDEX, + STARTMAPPING, + ENDMAPPING, + UNDEFINE +}; + +static char * +get_string(const char *s, const char **endp) +{ + size_t len; + const char *p; + char *r; + char *ret; + + for (len = 1, p = &s[1]; *p && *p != '\n' && *p != '#'; p++) + len += (!isblank(*p) || isblank(p[-1])); + + ret = malloc(len + 1); + if (!ret) + return NULL; + + r = ret; + for (*r++ = *s++; *s && *s != '\n' && *s != '#'; s++) { + if (!isblank(*s)) + *r++ = *s; + else if (isblank(s[-1])) + *r++ = ' '; + } + *r = '\0'; + return ret; +} + +static int +get_uints(uintmax_t *u1p, uintmax_t *u2p, uintmax_t *u3p, uintmax_t max, + const char *s, const char **endp, struct libfonts_context *ctx) +{ + int r = 0; + uintmax_t u, *up, digit; + + while (r < INT_MAX && isdigit(*s)) { + u = 0; + do { + digit = (uintmax_t)(*s & 15); + if (u > (max - digit) / 10) { + u = max; + while (isdigit(*++s)); + /* TODO warning */ + break; + } + u = u * 10 + digit; + } while (isdigit(*++s)); + + up = (r == 0 ? u1p : + r == 1 ? u2p : + r == 2 ? u3p : NULL); + if (up) + *up = u; + r += 1; + + if (!*s || *s == '\n' || *s == '#') + break; + while (isblank(*s)) + s++; + } + + *endp = s; + return r; +} + +int +libfonts_parse_encoding_line(struct libfonts_encoding **encodingp, int *statep, + const char *line, char **endp, struct libfonts_context *ctx) +{ + int ret = 0, r; + size_t keyword_len; + uintmax_t ju1, ju2, ju3; + enum keyword keyword; + struct libfonts_encoding_mapping *mapping; + void *new; + + if (!encodingp || + !statep || + !line || + (*statep & LEVEL_MASK) > MAX_LEVEL || + ((*statep & LEVEL_MASK) ? (*statep & ~(LEVEL_MASK | HAVE_BITS)) : *statep) || + (*statep && !*encodingp) || + ((*statep & LEVEL_MASK) == MAPPING_LEVEL && !(*encodingp)->nmappings) || + (*encodingp && ((!(*encodingp)->aliases && (*encodingp)->naliases) || + (!(*encodingp)->mappings && (*encodingp)->nmappings) || + (*encodingp)->size_rows > 0x100 || + (*encodingp)->size_cols > 0x100))) { + errno = EINVAL; + goto fail; + } + + while (isblank(*line)) + line++; + + if (!*line || *line == '#') + goto out; + + if (!strncasecmp(line, "STARTENCODING", keyword_len = sizeof("STARTENCODING") - 1)) + keyword = STARTENCODING; + else if (!strncasecmp(line, "ENDENCODING", keyword_len = sizeof("ENDENCODING") - 1)) + keyword = ENDENCODING; + else if (!strncasecmp(line, "ALIAS", keyword_len = sizeof("ALIAS") - 1)) + keyword = ALIAS; + else if (!strncasecmp(line, "SIZE", keyword_len = sizeof("SIZE") - 1)) + keyword = SIZE; + else if (!strncasecmp(line, "FIRSTINDEX", keyword_len = sizeof("FIRSTINDEX") - 1)) + keyword = FIRSTINDEX; + else if (!strncasecmp(line, "STARTMAPPING", keyword_len = sizeof("STARTMAPPING") - 1)) + keyword = STARTMAPPING; + else if (!strncasecmp(line, "ENDMAPPING", keyword_len = sizeof("ENDMAPPING") - 1)) + keyword = ENDMAPPING; + else if (!strncasecmp(line, "UNDEFINE", keyword_len = sizeof("UNDEFINE") - 1)) + keyword = UNDEFINE; + else if (!isdigit(*line)) + goto bad_keyword; + else + keyword = NO_KEYWORD; + + if (keyword != NO_KEYWORD) { + if (line[keyword_len] && !isblank(line[keyword_len])) { + /* TODO warning */ + goto out; + } + line = &line[keyword_len]; + while (isblank(*line)) + line++; + } + + switch (keyword) { + case STARTENCODING: + if (*statep != 0) { + /* TODO warning */ + break; + } + if (!*encodingp) { + *encodingp = calloc(1, sizeof(**encodingp)); + if (!*encodingp) + goto enomem; + } + (*encodingp)->size_rows = 256; + (*encodingp)->name = get_string(line, &line); + if (!(*encodingp)->name) + goto enomem; + if (!*(*encodingp)->name) { + /* TODO warning */ + } + *statep = ENCODING_LEVEL; + break; + + case ENDENCODING: + if ((*statep & LEVEL_MASK) == MAPPING_LEVEL) { + /* TODO warning */ + } else if ((*statep & LEVEL_MASK) != ENCODING_LEVEL) { + /* TODO warning */ + break; + } + if (*line && *line != '\n' && *line != '#') { + /* TODO warning */ + } + if ((*statep & HAVE_FIRST_INDEX_BYTE_2_BIT) && (*encodingp)->size_cols) { + /* TODO warning */ + (*encodingp)->first_index_col = 0; + } + ret = 1; + *statep = 0; + break; + + case ALIAS: + if ((*statep & LEVEL_MASK) != ENCODING_LEVEL) { + /* TODO warning */ + break; + } + if ((*encodingp)->naliases > SIZE_MAX / sizeof(*(*encodingp)->aliases) - 1) + goto enomem; + new = realloc((*encodingp)->aliases, ((*encodingp)->naliases + 1) * sizeof(*(*encodingp)->aliases)); + if (!new) + goto enomem; + (*encodingp)->aliases = new; + (*encodingp)->aliases[(*encodingp)->naliases] = get_string(line, &line); + if (!(*encodingp)->aliases[(*encodingp)->naliases]) + goto enomem; + if (!*(*encodingp)->aliases[(*encodingp)->naliases]) { + /* TODO warning */ + } + (*encodingp)->naliases += 1; + break; + + case SIZE: + if ((*statep & LEVEL_MASK) != ENCODING_LEVEL) { + /* TODO warning */ + break; + } else if (*statep & HAVE_SIZE_BIT) { + /* TODO warning */ + } + ju2 = 0; + r = get_uints(&ju1, &ju2, NULL, 0x100, line, &line, ctx); + if (r < 0) { + goto fail; + } else if (r == 0) { + /* TODO warning */ + break; + } else if (r > 2) { + /* TODO warning */ + break; + } else if (*line && *line != '\n' && *line != '#') { + /* TODO warning */ + break; + } + if (!ju1) { + /* TODO warning */ + break; + } + if (r > 1 && !ju2) { + /* TODO warning */ + break; + } + (*encodingp)->size_rows = (uint16_t)ju1; + (*encodingp)->size_cols = (uint16_t)ju2; + *statep |= HAVE_SIZE_BIT; + break; + + case FIRSTINDEX: + if ((*statep & LEVEL_MASK) != ENCODING_LEVEL) { + /* TODO warning */ + break; + } else if (*statep & HAVE_FIRST_INDEX_BIT) { + /* TODO warning */ + } + r = get_uints(&ju1, &ju2, NULL, 0xFF, line, &line, ctx); + if (r < 0) { + goto fail; + } else if (r == 0) { + /* TODO warning */ + break; + } else if (r == 1) { + ju2 = 0; + *statep &= ~HAVE_FIRST_INDEX_BIT; + } else if (r == 2) { + *statep |= HAVE_FIRST_INDEX_BYTE_2_BIT; + } else { + /* TODO warning */ + break; + } + if (*line && *line != '\n' && *line != '#') { + /* TODO warning */ + break; + } + (*encodingp)->first_index_row = (uint16_t)ju1; + (*encodingp)->first_index_col = (uint16_t)ju2; + *statep |= HAVE_FIRST_INDEX_BIT; + break; + + case STARTMAPPING: + if ((*statep & LEVEL_MASK) == MAPPING_LEVEL) { + /* TODO warning */ + } else if ((*statep & LEVEL_MASK) != ENCODING_LEVEL) { + /* TODO warning */ + break; + } + if ((*encodingp)->nmappings > SIZE_MAX / sizeof(*(*encodingp)->mappings) - 1) + goto enomem; + new = realloc((*encodingp)->mappings, ((*encodingp)->nmappings + 1) * sizeof(*(*encodingp)->mappings)); + if (!new) + goto enomem; + (*encodingp)->mappings = new; + (*encodingp)->mappings[(*encodingp)->nmappings].entries = NULL; + (*encodingp)->mappings[(*encodingp)->nmappings].nentries = 0; + (*encodingp)->mappings[(*encodingp)->nmappings].target = get_string(line, &line); + if (!(*encodingp)->mappings[(*encodingp)->nmappings].target) { + /* TODO warning */ + break; + } + if (!*(*encodingp)->mappings[(*encodingp)->nmappings].target) { + /* TODO warning */ + } + (*encodingp)->nmappings += 1; + *statep = (*statep & ~LEVEL_MASK) | MAPPING_LEVEL; + break; + + case ENDMAPPING: + if ((*statep & LEVEL_MASK) != MAPPING_LEVEL) { + /* TODO warning */ + break; + } + if (*line && *line != '\n' && *line != '#') { + /* TODO warning */ + } + *statep = (*statep & ~LEVEL_MASK) | ENCODING_LEVEL; + break; + + case UNDEFINE: + if ((*statep & LEVEL_MASK) != MAPPING_LEVEL) { + /* TODO warning */ + break; + } + r = get_uints(&ju1, &ju2, NULL, UINT32_C(0xFFFFFFFF), line, &line, ctx); + if (r < 0) { + goto fail; + } else if (r == 0) { + /* TODO warning */ + break; + } else if (r == 1) { + ju2 = ju1; + } else if (r > 2) { + /* TODO warning */ + break; + } + if (*line && *line != '\n' && *line != '#') { + /* TODO warning */ + break; + } + mapping = &(*encodingp)->mappings[(*encodingp)->nmappings - 1]; + if (mapping->nentries > SIZE_MAX / sizeof(*mapping->entries) - 1) + goto enomem; + new = realloc(mapping->entries, (mapping->nentries + 1) * sizeof(*mapping->entries)); + if (!new) + goto enomem; + mapping->entries = new; + mapping->entries[mapping->nentries].undefined_range.type = LIBFONTS_ENCODING_MAPPING_ENTRY_UNDEFINED_RANGE; + mapping->entries[mapping->nentries].undefined_range.low_source = (uint32_t)ju1; + mapping->entries[mapping->nentries].undefined_range.high_source = (uint32_t)ju2; + mapping->nentries += 1; + break; + + case NO_KEYWORD: + if ((*statep & LEVEL_MASK) != MAPPING_LEVEL) { + /* TODO warning */ + break; + } + r = get_uints(&ju1, &ju2, &ju3, UINT32_C(0xFFFFFFFF), line, &line, ctx); + if (r < 0) { + goto fail; + } else if (r == 0) { + /* TODO warning internal error */ + break; + } else if (r == 1) { + if (!*line || *line == '\n' || *line == '#') { + /* TODO warning */ + break; + } + } else if (r == 2) { + ju3 = ju2; + ju2 = ju1; + } else if (r == 3) { + if (ju2 < ju1) { + /* TODO warning */ + break; + } + } else { + /* TODO warning */ + break; + } + if (r != 1 && *line && *line != '\n' && *line != '#') { + /* TODO warning */ + break; + } + + mapping = &(*encodingp)->mappings[(*encodingp)->nmappings - 1]; + if (mapping->nentries > SIZE_MAX / sizeof(*mapping->entries) - 1) + goto enomem; + new = realloc(mapping->entries, (mapping->nentries + 1) * sizeof(*mapping->entries)); + if (!new) + goto enomem; + mapping->entries = new; + if (r != 1) { + mapping->entries[mapping->nentries].remapped_range.type = LIBFONTS_ENCODING_MAPPING_ENTRY_REMAPPED_RANGE; + mapping->entries[mapping->nentries].remapped_range.low_source = (uint32_t)ju1; + mapping->entries[mapping->nentries].remapped_range.high_source = (uint32_t)ju2; + mapping->entries[mapping->nentries].remapped_range.low_target = (uint32_t)ju3; + } else { + mapping->entries[mapping->nentries].index_to_name.type = LIBFONTS_ENCODING_MAPPING_ENTRY_INDEX_TO_NAME; + mapping->entries[mapping->nentries].index_to_name.source = (uint32_t)ju1; + mapping->entries[mapping->nentries].index_to_name.target = get_string(line, &line); + if (!mapping->entries[mapping->nentries].index_to_name.target) + goto enomem; + } + mapping->nentries += 1; + break; + + default: + /* TODO warning internal error */ + break; + } + +out: + if (line) + while (*line && *line != '\n') + line++; + if (endp) + *endp = *(char **)(void *)&line; + return ret; + +enomem: + errno = ENOMEM; +fail: + ret = -1; + goto out; + +bad_keyword: + /* TODO warning */ + goto out; +} + + +#else + + +int +main(void) +{ + return 0; /* XXX add test */ +} + + +#endif -- cgit v1.2.3-70-g09d2