diff options
author | Kristaps Dzonsons <kristaps@bsd.lv> | 2011-07-17 12:13:37 +0000 |
---|---|---|
committer | Kristaps Dzonsons <kristaps@bsd.lv> | 2011-07-17 12:13:37 +0000 |
commit | c65bd324370683e30cc03e16fa78b9ee7059a19e (patch) | |
tree | c34b88eba1bd0d2dcc069e123f0195ac92ddbac0 /eqn.c | |
parent | e1668c2d072b1ff1b0f569174c78d672523280a2 (diff) | |
download | mandoc-c65bd324370683e30cc03e16fa78b9ee7059a19e.tar.gz |
Add initial `define' support for eqn(7).
This works by iterating over a simple list. It's a slow, auditable
early implementation. Data is read (the reading function will be
reused) then parsed, then the line re-run if remaining stuff exists.
Note this function isn't the same as mandoc_getarg(), as eqn(7) uses a
different system for reading quoted strings.
This doesn't actually use the defines.
Diffstat (limited to 'eqn.c')
-rw-r--r-- | eqn.c | 117 |
1 files changed, 111 insertions, 6 deletions
@@ -28,12 +28,18 @@ #include "libmandoc.h" #include "libroff.h" +static const char *eqn_nexttok(struct mparse *, int, int, + const char **, size_t *); + /* ARGSUSED */ enum rofferr -eqn_read(struct eqn_node **epp, int ln, const char *p, int offs) +eqn_read(struct eqn_node **epp, int ln, + const char *p, int pos, int *offs) { - size_t sz; - struct eqn_node *ep; + size_t sz; + struct eqn_node *ep; + const char *start, *end; + int i; if (0 == strcmp(p, ".EN")) { *epp = NULL; @@ -41,14 +47,69 @@ eqn_read(struct eqn_node **epp, int ln, const char *p, int offs) } ep = *epp; + end = p + pos; + start = eqn_nexttok(ep->parse, ln, pos, &end, &sz); + + if (NULL == start) + return(ROFF_IGN); + + if (6 == sz && 0 == strncmp("define", start, 6)) { + /* + * TODO: warn if key is quoted: groff doesn't seem to + * like this (I don't know why). + */ + start = eqn_nexttok(ep->parse, ln, pos, &end, &sz); + for (i = 0; i < (int)ep->defsz; i++) { + if (ep->defs[i].keysz != sz) + continue; + if (0 == strncmp(ep->defs[i].key, start, sz)) + break; + } + + /* + * TODO: merge this code with roff_getstr(). + */ + + if (i == (int)ep->defsz) { + ep->defsz++; + ep->defs = mandoc_realloc + (ep->defs, ep->defsz * + sizeof(struct eqn_def)); + ep->defs[i].keysz = sz; + ep->defs[i].key = mandoc_malloc(sz + 1); + memcpy(ep->defs[i].key, start, sz); + ep->defs[i].key[(int)sz] = '\0'; + ep->defs[i].val = NULL; + ep->defs[i].valsz = 0; + } + + start = eqn_nexttok(ep->parse, ln, pos, &end, &sz); + + ep->defs[i].valsz = sz; + ep->defs[i].val = mandoc_realloc + (ep->defs[i].val, sz + 1); + memcpy(ep->defs[i].val, start, sz); + ep->defs[i].val[(int)sz] = '\0'; + + if ('\0' == *end) + return(ROFF_IGN); + + *offs = end - (p + pos); + assert(*offs > 0); + + return(ROFF_RERUN); + } else + end = p + pos; + + if (0 == (sz = strlen(end))) + return(ROFF_IGN); - sz = strlen(&p[offs]); ep->eqn.data = mandoc_realloc(ep->eqn.data, ep->eqn.sz + sz + 1); if (0 == ep->eqn.sz) *ep->eqn.data = '\0'; ep->eqn.sz += sz; - strlcat(ep->eqn.data, &p[offs], ep->eqn.sz + 1); + strlcat(ep->eqn.data, end, ep->eqn.sz + 1); return(ROFF_IGN); } @@ -59,7 +120,6 @@ eqn_alloc(int pos, int line, struct mparse *parse) p = mandoc_calloc(1, sizeof(struct eqn_node)); p->parse = parse; - p->eqn.line = line; p->eqn.pos = pos; @@ -77,7 +137,52 @@ eqn_end(struct eqn_node *e) void eqn_free(struct eqn_node *p) { + int i; free(p->eqn.data); + + for (i = 0; i < (int)p->defsz; i++) { + free(p->defs[i].key); + free(p->defs[i].val); + } + + free(p->defs); free(p); } + +static const char * +eqn_nexttok(struct mparse *mp, int ln, int pos, + const char **next, size_t *sz) +{ + const char *start; + int q; + + start = *next; + q = 0; + + if ('\0' == *start) + return(NULL); + + if ('"' == *start) { + start++; + q = 1; + } + + *next = q ? strchr(start, '"') : strchr(start, ' '); + + if (NULL != *next) { + *sz = (size_t)(*next - start); + if (q) + (*next)++; + while (' ' == **next) + (*next)++; + } else { + if (q) + mandoc_msg(MANDOCERR_BADQUOTE, + mp, ln, pos, NULL); + *next = strchr(start, '\0'); + *sz = (size_t)(*next - start); + } + + return(start); +} |