- free(buf);
- mchars_free(mc);
-
- if (regp)
- regfree(regp);
-}
-
-/*
- * Track allocated buffer size for buf_redup().
- */
-static inline void
-buf_alloc(char **buf, size_t *bufsz, size_t sz)
-{
-
- if (sz < *bufsz)
- return;
-
- *bufsz = sz + 1024;
- if (NULL == (*buf = realloc(*buf, *bufsz))) {
- perror(NULL);
- exit(EXIT_FAILURE);
- }
-}
-
-/*
- * Like buf_redup() but throwing away the buffer size.
- */
-static void
-buf_dup(struct mchars *mc, char **buf, const char *val)
-{
- size_t bufsz;
-
- bufsz = 0;
- *buf = NULL;
- buf_redup(mc, buf, &bufsz, val);
-}
-
-/*
- * Normalise strings from the index and database.
- * These strings are escaped as defined by mandoc_char(7) along with
- * other goop in mandoc.h (e.g., soft hyphens).
- */
-static void
-buf_redup(struct mchars *mc, char **buf,
- size_t *bufsz, const char *val)
-{
- size_t sz;
- const char *seq, *cpp;
- int len, pos;
- enum mandoc_esc esc;
- const char rsv[] = { '\\', ASCII_NBRSP, ASCII_HYPH, '\0' };
-
- /* Pre-allocate by the length of the input */
-
- buf_alloc(buf, bufsz, strlen(val) + 1);
-
- pos = 0;
-
- while ('\0' != *val) {
- /*
- * Halt on the first escape sequence.
- * This also halts on the end of string, in which case
- * we just copy, fallthrough, and exit the loop.
- */
- if ((sz = strcspn(val, rsv)) > 0) {
- memcpy(&(*buf)[pos], val, sz);
- pos += (int)sz;
- val += (int)sz;
- }
-
- if (ASCII_HYPH == *val) {
- (*buf)[pos++] = '-';
- val++;
- continue;
- } else if (ASCII_NBRSP == *val) {
- (*buf)[pos++] = ' ';
- val++;
- continue;
- } else if ('\\' != *val)
- break;
-
- /* Read past the slash. */
-
- val++;
-
- /*
- * Parse the escape sequence and see if it's a
- * predefined character or special character.
- */
-
- esc = mandoc_escape(&val, &seq, &len);
- if (ESCAPE_ERROR == esc)
- break;
-
- cpp = ESCAPE_SPECIAL == esc ?
- mchars_spec2str(mc, seq, len, &sz) : NULL;
-
- if (NULL == cpp)
- continue;
-
- /* Copy the rendered glyph into the stream. */
-
- buf_alloc(buf, bufsz, sz);
-
- memcpy(&(*buf)[pos], cpp, sz);
- pos += (int)sz;
- }
-
- (*buf)[pos] = '\0';
-}
-
-static void
-state_output(const struct res *res, int sz)
-{
- int i;
-
- for (i = 0; i < sz; i++)
- printf("%s(%s%s%s) - %s\n", res[i].title,
- res[i].cat,
- *res[i].arch ? "/" : "",
- *res[i].arch ? res[i].arch : "",
- res[i].desc);
-}
-
-static void
-usage(void)
-{
-
- fprintf(stderr, "usage: %s "
- "[-eIr] "
- "[-a arch] "
- "[-c cat] "
- "[-s sort] "
- "[-t type[,...]] "
- "key\n", progname);
-}
-
-static int
-state_getrecord(struct state *p, recno_t rec, struct rec *rp)
-{
- DBT key, val;
- size_t sz;
- int rc;
-
- key.data = &rec;
- key.size = sizeof(recno_t);
-
- rc = (*p->idx->get)(p->idx, &key, &val, 0);
- if (rc < 0) {
- perror(p->idxf);
- return(0);
- } else if (rc > 0)
- goto err;
-
- rp->file = (char *)val.data;
- if ((sz = strlen(rp->file) + 1) >= val.size)
- goto err;
-
- rp->cat = (char *)val.data + (int)sz;
- if ((sz += strlen(rp->cat) + 1) >= val.size)
- goto err;
-
- rp->title = (char *)val.data + (int)sz;
- if ((sz += strlen(rp->title) + 1) >= val.size)
- goto err;
-
- rp->arch = (char *)val.data + (int)sz;
- if ((sz += strlen(rp->arch) + 1) >= val.size)
- goto err;
-
- rp->desc = (char *)val.data + (int)sz;
- rp->rec = rec;
- return(1);
-err:
- fprintf(stderr, "%s: Corrupt index\n", p->idxf);
- return(0);
-}
-
-static int
-sort_title(const void *p1, const void *p2)
-{
-
- return(strcmp(((const struct res *)p1)->title,
- ((const struct res *)p2)->title));
-}
-
-static int
-sort_cat(const void *p1, const void *p2)
-{
- int rc;
-
- rc = strcmp(((const struct res *)p1)->cat,
- ((const struct res *)p2)->cat);
-
- return(0 == rc ? sort_title(p1, p2) : rc);