version 1.1, 2015/02/20 09:58:50 |
version 1.2, 2015/02/20 12:25:25 |
Line 801 parsefile(struct texi *p, const char *fname, int parse |
|
Line 801 parsefile(struct texi *p, const char *fname, int parse |
|
texifilepop(p); |
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++; |
|
} |
|
} |