From 9a6046f51934f8c34a58583b44cd1dc0c0b0b8d6 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Thu, 12 Jan 2023 21:57:47 +0100 Subject: m + add libfonts_parse_dir_line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- Makefile | 1 + libfonts.h | 59 +++++++++++++++++++-- libfonts_parse_alias_line.c | 10 +++- libfonts_parse_dir_line.c | 126 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 191 insertions(+), 5 deletions(-) create mode 100644 libfonts_parse_dir_line.c diff --git a/Makefile b/Makefile index 27be8f9..ce8850d 100644 --- a/Makefile +++ b/Makefile @@ -30,6 +30,7 @@ PUBLIC_OBJ =\ libfonts_get_output_rendering_settings.o\ libfonts_get_subpixel_order_class.o\ libfonts_parse_alias_line.o\ + libfonts_parse_dir_line.o\ libfonts_unget_subpixel_order_class.o\ libfonts_used_environs.o diff --git a/libfonts.h b/libfonts.h index 02be993..ce17e59 100644 --- a/libfonts.h +++ b/libfonts.h @@ -18,6 +18,23 @@ */ #define LIBFONTS_ALIAS_FILE_NAME "fonts.alias" +/** + * File name of file in font directories that is used + * enumerate all font files, and their font names, in + * in the directory + */ +#define LIBFONTS_DIR_FILE_NAME "fonts.dir" + +/** + * File name of file in font directories that is used + * enumerate all scalable font files, and their font + * names, in in the directory + * + * `LIBFONTS_SCALE_DIR_FILE_NAME` enumerates a subset + * of `LIBFONTS_DIR_FILE_NAME` + */ +#define LIBFONTS_SCALE_DIR_FILE_NAME "fonts.scale" + #if defined(__clang__) # pragma clang diagnostic push @@ -1740,8 +1757,8 @@ int libfonts_get_font_root_dirs(char ***, size_t *, struct libfonts_context *); * @param typep Output parameter fot the line's type * @param aliasp Output parameter for the new alias * @param namep Output parameter for the alias target, - * which can be ether a proper XFDL (font name), - * a XFDL with wildcards, or another alias + * which can be ether a proper XLFD (font name), + * a XLFD with wildcards, or another alias * @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 @@ -1749,14 +1766,50 @@ int libfonts_get_font_root_dirs(char ***, size_t *, struct libfonts_context *); * @return 0 on success, -1 on failure * * @throws ENOMEM Failed to allocate memory for `*aliasp` or `*namep` + * @throws EINVAL `line` is `NULL` * * Unless `*typep` is set to (or would be set to) `LIBFONTS_ALIAS_LINE_ALIAS_DEFINITION`, * `*aliasp` and `*namep` are set to `NULL`. On failure, `*aliasp` and `*namep` are set - * to `NULL` and `*typep` is seto to `LIBFONTS_ALIAS_LINE_BLANK`. `*endp` is updated even + * to `NULL` and `*typep` is set to `LIBFONTS_ALIAS_LINE_BLANK`. `*endp` is updated even * on failure. */ int libfonts_parse_alias_line(enum libfonts_alias_line_type *, char **, char **, const char *, char **); +/** + * Parse any other than the first line in a + * font enumeration file + * + * Font enumeration files are named either "fonts.dir" + * (`LIBFONTS_DIR_FILE_NAME`; for full enumeration) or + * "fonts.scale" (`LIBFONTS_SCALE_DIR_FILE_NAME`, for + * enumeration of scalable fonts only), and are located + * in any font directory, i.e. directories returned by + * `libfonts_get_font_root_dirs` subdirectors (and + * further decedents) + * + * The first line the file is a decimally formatted + * non-negative number of entries in the file, and + * should be ignored; and it cannot be parsed by this + * function + * + * @param filep Output parameter for the font file name (basename with suffix) + * @param namep Output parameter for the font's XLFD + * @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` + * @return 0 on success, -1 on failure + * + * @throws ENOMEM Failed to allocate memory for `*aliasp` or `*namep` + * @throws EINVAL `line` is `NULL` + * @throws (unmodified) Malformatted line (possibly the first line in the file) + * @throws (unmodified) Listed font file name contains a slash + * + * On failure, `*filep` and `*namep` are set to `NULL`. + * `*endp` is updated even on failure. + */ +int libfonts_parse_dir_line(char **, char **, const char *, char **); + /* TODO add font listing */ diff --git a/libfonts_parse_alias_line.c b/libfonts_parse_alias_line.c index 0496449..3e712e2 100644 --- a/libfonts_parse_alias_line.c +++ b/libfonts_parse_alias_line.c @@ -86,6 +86,11 @@ libfonts_parse_alias_line(enum libfonts_alias_line_type *typep, char **aliasp, c if (namep) *namep = NULL; + if (!line) { + errno = EINVAL; + goto fail; + } + while (isblank(*line)) line++; if (!*line) @@ -132,8 +137,9 @@ fail: *namep = NULL; } ret = -1; - while (*line && *line != '\n') - line++; + if (line) + while (*line && *line != '\n') + line++; out: if (endp) *endp = *(char **)(void *)&line; diff --git a/libfonts_parse_dir_line.c b/libfonts_parse_dir_line.c new file mode 100644 index 0000000..a339ce3 --- /dev/null +++ b/libfonts_parse_dir_line.c @@ -0,0 +1,126 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + + +static int +read_field(char **valuep, int allow_blank, const char *s, const char **endp) +{ + char endc; + size_t esc = 0; + size_t len; + const char *start; + const char *end; + char *v; + + if (*s == '"') { + endc = '"'; + s++; + } else if (allow_blank) { + endc = '\n'; + } else { + endc = ' '; + } + start = s; + + for (;;) { + if (!*s || *s != '\n' || *s == endc) + break; + if (*s == '\\') { + esc += 1; + s++; + if (!*s || *s == '\n') + goto badline; + } + s++; + } + end = s; + len = (size_t)(end - start) - esc; + if (endc == '"' && *s != '"') { + badline: + *endp = s; + return -1; + } + s += *s == '"'; + *endp = s; + + if (valuep) { + v = malloc(len + 1); + if (v) { + errno = ENOMEM; + return -1; + } + while (start != end) { + if (*start == '\\') + start++; + *v++ += *start++; + } + *v = '\0'; + *valuep = v; + } + + return 0; +} + +int +libfonts_parse_dir_line(char **filep, char **namep, const char *line, char **endp) +{ + int ret = 0; + + if (filep) + *filep = NULL; + if (namep) + *namep = NULL; + + if (!line) { + errno = EINVAL; + goto fail; + } + + if (read_field(filep, 0, line, &line)) + goto fail; + + if (*line != ' ') + goto badline; + line++; + + if (read_field(namep, 1, line, &line)) + goto fail; + + if (*line && *line != '\n') + goto badline; + + goto out; + +badline: +fail: + if (filep) { + free(*filep); + *filep = NULL; + } + if (namep) { + free(*namep); + *namep = NULL; + } + ret = -1; + if (line) + while (*line && *line != '\n') + line++; +out: + if (endp) + *endp = *(char **)(void *)&line; + return ret; +} + + +#else + + +int +main(void) +{ + return 0; /* XXX add test */ +} + + +#endif -- cgit v1.2.3-70-g09d2