=================================================================== RCS file: /cvs/texi2mdoc/util.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- texi2mdoc/util.c 2015/02/20 09:58:50 1.1 +++ texi2mdoc/util.c 2015/02/20 12:25:25 1.2 @@ -1,4 +1,4 @@ -/* $Id: util.c,v 1.1 2015/02/20 09:58:50 kristaps Exp $ */ +/* $Id: util.c,v 1.2 2015/02/20 12:25:25 kristaps Exp $ */ /* * Copyright (c) 2015 Kristaps Dzonsons * @@ -801,3 +801,138 @@ parsefile(struct texi *p, const char *fname, int parse texifilepop(p); } +/* + * Look up the value to a stored pair's value starting in "buf" from + * start to end. + * Return the pointer to the value memory, which can be NULL if the + * pointer key does not exist. + * The pointer can point to NULL if the value has been unset. + */ +static char ** +valuequery(const struct texi *p, + const char *buf, size_t start, size_t end) +{ + size_t i, sz, len; + + assert(end >= start); + /* Ignore zero-length. */ + if (0 == (len = (end - start))) + return(NULL); + for (i = 0; i < p->valsz; i++) { + sz = strlen(p->vals[i].key); + if (sz != len) + continue; + if (0 == strncmp(p->vals[i].key, &buf[start], len)) + return(&p->vals[i].value); + } + return(NULL); +} + +/* + * Parse a key until the end of line, e.g., @clear foo\n, and return the + * pointer to its value via valuequery(). + */ +static char ** +valuelquery(struct texi *p, const char *buf, size_t sz, size_t *pos) +{ + size_t start, end; + char **ret; + + while (*pos < sz && isws(buf[*pos])) + advance(p, buf, pos); + if (*pos == sz) + return(NULL); + for (start = end = *pos; end < sz; end++) + if ('\n' == buf[end]) + break; + advanceto(p, buf, pos, end); + if (*pos < sz) { + assert('\n' == buf[*pos]); + advance(p, buf, pos); + } + if (NULL == (ret = valuequery(p, buf, start, end))) + return(NULL); + return(ret); +} + +void +valuelclear(struct texi *p, const char *buf, size_t sz, size_t *pos) +{ + char **ret; + + if (NULL == (ret = valuelquery(p, buf, sz, pos))) + return; + free(*ret); + *ret = NULL; +} + +const char * +valuellookup(struct texi *p, const char *buf, size_t sz, size_t *pos) +{ + char **ret; + + if (NULL == (ret = valuelquery(p, buf, sz, pos))) + return(NULL); + return(*ret); +} + +/* + * Parse a key from a bracketed string, e.g., @value{foo}, and return + * the pointer to its value. + * If the returned pointer is NULL, either there was no string within + * the brackets (or no brackets), or the value was not found, or the + * value had previously been unset. + */ +const char * +valueblookup(struct texi *p, const char *buf, size_t sz, size_t *pos) +{ + size_t start, end; + char **ret; + + while (*pos < sz && isws(buf[*pos])) + advance(p, buf, pos); + if (*pos == sz || '{' != buf[*pos]) + return(NULL); + advance(p, buf, pos); + for (start = end = *pos; end < sz; end++) + if ('}' == buf[end]) + break; + advanceto(p, buf, pos, end); + if (*pos < sz) { + assert('}' == buf[*pos]); + advance(p, buf, pos); + } + if (NULL == (ret = valuequery(p, buf, start, end))) + return(NULL); + return(*ret); +} + +void +valueadd(struct texi *p, char *key, char *val) +{ + size_t i; + + assert(NULL != key); + assert(NULL != val); + + for (i = 0; i < p->valsz; i++) + if (0 == strcmp(p->vals[i].key, key)) + break; + + if (i < p->valsz) { + free(key); + free(p->vals[i].value); + p->vals[i].value = val; + } else { + p->vals = realloc(p->vals, + (p->valsz + 1) * + sizeof(struct texivalue)); + if (NULL == p->vals) { + perror(NULL); + exit(EXIT_FAILURE); + } + p->vals[p->valsz].key = key; + p->vals[p->valsz].value = val; + p->valsz++; + } +}