aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--libfonts.h311
-rw-r--r--libfonts_deallocate_encoding.c38
-rw-r--r--libfonts_deallocate_encoding_mapping.c32
-rw-r--r--libfonts_deallocate_encoding_mapping_entry.c19
-rw-r--r--libfonts_deallocate_encoding_mapping_entry_index_to_name.c26
-rw-r--r--libfonts_parse_alias_line.c2
-rw-r--r--libfonts_parse_encoding_line.c439
8 files changed, 871 insertions, 1 deletions
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,
@@ -1847,6 +2086,78 @@ int libfonts_char_is_in_subset(uint32_t, const char *);
/**
+ * 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
*
* @param font The default font
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