=================================================================== RCS file: /cvs/mandoc/eqn.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -p -r1.5 -r1.6 --- mandoc/eqn.c 2011/07/12 21:32:43 1.5 +++ mandoc/eqn.c 2011/07/17 12:13:37 1.6 @@ -1,4 +1,4 @@ -/* $Id: eqn.c,v 1.5 2011/07/12 21:32:43 kristaps Exp $ */ +/* $Id: eqn.c,v 1.6 2011/07/17 12:13:37 kristaps Exp $ */ /* * Copyright (c) 2011 Kristaps Dzonsons * @@ -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, } ep = *epp; + end = p + pos; + start = eqn_nexttok(ep->parse, ln, pos, &end, &sz); - sz = strlen(&p[offs]); + 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); + 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); }