diff options
-rw-r--r-- | eqn.c | 119 | ||||
-rw-r--r-- | libroff.h | 16 | ||||
-rw-r--r-- | roff.c | 8 |
3 files changed, 129 insertions, 14 deletions
@@ -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 <kristaps@bsd.lv> * @@ -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); +} @@ -1,4 +1,4 @@ -/* $Id: libroff.h,v 1.21 2011/07/12 21:32:43 kristaps Exp $ */ +/* $Id: libroff.h,v 1.22 2011/07/17 12:13:37 kristaps Exp $ */ /* * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -42,10 +42,19 @@ struct tbl_node { struct tbl_node *next; }; +struct eqn_def { + char *key; + size_t keysz; + char *val; + size_t valsz; +}; + struct eqn_node { + struct eqn_def *defs; + size_t defsz; struct eqn eqn; - struct eqn_node *next; struct mparse *parse; + struct eqn_node *next; }; struct tbl_node *tbl_alloc(int, int, struct mparse *); @@ -62,7 +71,8 @@ void tbl_end(struct tbl_node *); struct eqn_node *eqn_alloc(int, int, struct mparse *); void eqn_end(struct eqn_node *); void eqn_free(struct eqn_node *); -enum rofferr eqn_read(struct eqn_node **, int, const char *, int); +enum rofferr eqn_read(struct eqn_node **, int, + const char *, int, int *); __END_DECLS @@ -1,4 +1,4 @@ -/* $Id: roff.c,v 1.145 2011/07/12 21:32:43 kristaps Exp $ */ +/* $Id: roff.c,v 1.146 2011/07/17 12:13:37 kristaps Exp $ */ /* * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org> @@ -519,18 +519,18 @@ roff_parseln(struct roff *r, int ln, char **bufp, if (ROFF_CONT != e) return(e); if (r->eqn) - return(eqn_read(&r->eqn, ln, *bufp, pos)); + return(eqn_read(&r->eqn, ln, *bufp, pos, offs)); if (r->tbl) return(tbl_read(r->tbl, ln, *bufp, pos)); return(ROFF_CONT); } else if ( ! ctl) { if (r->eqn) - return(eqn_read(&r->eqn, ln, *bufp, pos)); + return(eqn_read(&r->eqn, ln, *bufp, pos, offs)); if (r->tbl) return(tbl_read(r->tbl, ln, *bufp, pos)); return(ROFF_CONT); } else if (r->eqn) - return(eqn_read(&r->eqn, ln, *bufp, ppos)); + return(eqn_read(&r->eqn, ln, *bufp, ppos, offs)); /* * If a scope is open, go to the child handler for that macro, |