jdict

command line tool for looking up terms in yomidict dictionaries
git clone anongit@rnpnr.xyz:jdict.git
Log | Files | Refs | Feed | README | LICENSE

Commit: 0923ca5ba96e095fc674bab9091562ace8800a18
Parent: f344c7ef726eb97e83f04b77e5b67094b5b3b1cd
Author: Randy Palamar
Date:   Sun, 19 Jun 2022 08:58:55 -0600

handle incorrect stride values

this is done by trying to allocate more tokens and retrying the parse

Diffstat:
Mjdict.c | 45++++++++++++++++++++++++++++-----------------
1 file changed, 28 insertions(+), 17 deletions(-)

diff --git a/jdict.c b/jdict.c @@ -16,6 +16,7 @@ #include "config.h" #define YOMI_TOKS_PER_ENT 10 +#define YOMI_TOK_DELTA (YOMI_TOKS_PER_ENT * 100) typedef struct { char *term; @@ -71,11 +72,12 @@ make_ent(YomiTok *tok, char *data) } static DictEnt * -parse_term_bank(DictEnt *ents, size_t *nents, const char *tbank, YomiTok *toks, size_t ntoks) +parse_term_bank(DictEnt *ents, size_t *nents, const char *tbank, size_t stride) { int r, fd; - size_t flen, i; + size_t i, ntoks, flen; char *data; + YomiTok *toks = NULL; YomiParser p; DictEnt *e; @@ -85,10 +87,27 @@ parse_term_bank(DictEnt *ents, size_t *nents, const char *tbank, YomiTok *toks, data = mmap(NULL, flen, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); + /* allocate tokens */ + ntoks = stride * YOMI_TOKS_PER_ENT + 1; + if ((ntoks - 1) / YOMI_TOKS_PER_ENT != stride) + die("stride multiplication overflowed: %s\n", tbank); + toks = xreallocarray(toks, ntoks, sizeof(YomiTok)); + yomi_init(&p); - r = yomi_parse(&p, toks, ntoks, data, flen); - if (r < 0) - return NULL; + while ((r = yomi_parse(&p, toks, ntoks, data, flen)) < 0) { + switch (r) { + case YOMI_ERROR_NOMEM: + /* allocate more mem and try again */ + ntoks += YOMI_TOK_DELTA; + toks = xreallocarray(toks, ntoks, sizeof(YomiTok)); + break; + case YOMI_ERROR_INVAL: /* FALLTRHOUGH */ + case YOMI_ERROR_MALFO: + munmap(data, flen); + free(toks); + return NULL; + } + } ents = xreallocarray(ents, (*nents) + r/YOMI_TOKS_PER_ENT, sizeof(DictEnt)); for (i = 0; i < r; i++) { @@ -99,8 +118,8 @@ parse_term_bank(DictEnt *ents, size_t *nents, const char *tbank, YomiTok *toks, memcpy(&ents[(*nents)++], e, sizeof(DictEnt)); } } - munmap(data, flen); + free(toks); return ents; } @@ -109,18 +128,11 @@ static DictEnt * make_dict(const char *path, size_t stride, size_t *nents) { char tbank[PATH_MAX]; - size_t i, ntoks, nbanks = 0; + size_t i, nbanks = 0; DIR *dir; struct dirent *dent; - YomiTok *toks = NULL; DictEnt *dict = NULL; - ntoks = stride * YOMI_TOKS_PER_ENT + 1; - if ((ntoks - 1) / YOMI_TOKS_PER_ENT != stride) - die("stride multiplication overflowed: %s\n", path); - - toks = xreallocarray(toks, ntoks, sizeof(YomiTok)); - if (!(dir = opendir(path))) die("opendir(): failed to open: %s\n", path); @@ -135,11 +147,10 @@ make_dict(const char *path, size_t stride, size_t *nents) for (i = 1; i <= nbanks; i++) { snprintf(tbank, sizeof(tbank), "%s/term_bank_%d.json", path, (int)i); - dict = parse_term_bank(dict, nents, tbank, toks, ntoks); + dict = parse_term_bank(dict, nents, tbank, stride); if (dict == NULL) return NULL; } - free(toks); return dict; } @@ -214,7 +225,7 @@ find_and_print_defs(char **terms, size_t nterms, char **dicts, size_t ndicts) for (j = 0; j < nterms; j++) { ent = find_ent(terms[j], ents, nents); if (ent == NULL) { - printf("term not found:%s\n", terms[j]); + printf("term not found: %s\n", terms[j]); return -1; } print_ent(ent);