X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/18b3351a3791f19a63c0af05640719db8eb5d184..f377eee1983a7c9f33a9920b3bf16180dca909da:/cc-hash.c diff --git a/cc-hash.c b/cc-hash.c index 81a06a2..b0d8bb2 100644 --- a/cc-hash.c +++ b/cc-hash.c @@ -37,6 +37,7 @@ #include #include +#include #include #include @@ -165,6 +166,33 @@ const encodeops *getencoding(const char *ename) /*----- File hashing ------------------------------------------------------*/ +/* --- @gethash@ --- * + * + * Arguments: @const char *name@ = pointer to name string + * + * Returns: Pointer to appropriate hash class. + * + * Use: Chooses a hash function by name. + */ + +const gchash *gethash(const char *name) +{ + const gchash *const *g, *gg = 0; + size_t sz = strlen(name); + for (g = ghashtab; *g; g++) { + if (strncmp(name, (*g)->name, sz) == 0) { + if ((*g)->name[sz] == 0) { + gg = *g; + break; + } else if (gg) + return (0); + else + gg = *g; + } + } + return (gg); +} + /* --- @fhash@ --- * * * Arguments: @const gchash *gch@ = pointer to hash function to use @@ -208,6 +236,77 @@ int fhash(const gchash *gch, unsigned f, const char *file, void *buf) return (rc); } +/* --- @hfparse@ --- * + * + * Arguments: @hfpctx *hfp@ = pointer to the context structure + * + * Returns: A code indicating what happened. + * + * Use: Parses a line from the input file. + */ + +int hfparse(hfpctx *hfp) +{ + char *p, *q; + const gchash *gch; + const encodeops *ee; + dstr *d = hfp->dline; + size_t hsz; + + /* --- Fetch the input line and get ready to parse --- */ + + DRESET(d); + if (dstr_putline(d, hfp->fp) == EOF) return (HF_EOF); + p = d->buf; + + /* --- Parse magic comments --- */ + + if (*p == '#') { + p++; + if ((q = str_getword(&p)) == 0) return (HF_BAD); + if (strcmp(q, "hash") == 0) { + if ((q = str_getword(&p)) == 0) return (HF_BAD); + if ((gch = gethash(q)) == 0) return (HF_BAD); + hfp->gch = gch; + return (HF_HASH); + } else if (strcmp(q, "encoding") == 0) { + if ((q = str_getword(&p)) == 0) return (HF_BAD); + if ((ee = getencoding(q)) == 0) return (HF_BAD); + hfp->ee = ee; + return (HF_ENC); + } else if (strcmp(q, "escape") == 0) { + hfp->f |= HFF_ESCAPE; + return (HF_ESC); + } + return (HF_BAD); + } + + /* --- Otherwise it's a file line --- */ + + q = p; + while (*p && *p != ' ') p++; + if (!*p) return (HF_BAD); + *p++ = 0; + hsz = hfp->gch->hashsz; + if (hfp->ee->get(q, hfp->hbuf, hsz, 0) < hsz) return (HF_BAD); + switch (*p) { + case '*': hfp->f |= FHF_BINARY; break; + case ' ': hfp->f &= ~FHF_BINARY; break; + default: return (HF_BAD); + } + p++; + + DRESET(hfp->dfile); + if (hfp->f & HFF_ESCAPE) + getstring(&p, hfp->dfile, GSF_STRING); + else { + dstr_putm(hfp->dfile, p, d->len - (p - d->buf)); + dstr_putz(hfp->dfile); + } + + return (HF_FILE); +} + /*----- String I/O --------------------------------------------------------*/ /* --- @getstring@ --- *