diff options
author | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2014-10-16 01:10:07 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2014-10-16 01:10:07 +0000 |
commit | b4b76d0cb9986efb0f45a5739ff2967b6e56710f (patch) | |
tree | d18ceeb417cbcf0a5edffb9430df4429ea3c9078 | |
parent | a39c64b683f22e56215d0c9ee0d901a70d81b0a1 (diff) |
Implement in-line equations, much needed by Xenocara manuals.
Put the steering into the roff parser rather than into the mdoc
parser such that it works for all macro languages and on both text
and macro lines.
Line breaks and blank characters generated before and after in-line
equations are not perfect yet, but let's do one thing at a time.
-rw-r--r-- | usr.bin/mandoc/eqn.c | 28 | ||||
-rw-r--r-- | usr.bin/mandoc/libmandoc.h | 8 | ||||
-rw-r--r-- | usr.bin/mandoc/libroff.h | 26 | ||||
-rw-r--r-- | usr.bin/mandoc/mdoc.c | 59 | ||||
-rw-r--r-- | usr.bin/mandoc/roff.c | 71 |
5 files changed, 103 insertions, 89 deletions
diff --git a/usr.bin/mandoc/eqn.c b/usr.bin/mandoc/eqn.c index c6a779646c6..d7bcb9ff2e3 100644 --- a/usr.bin/mandoc/eqn.c +++ b/usr.bin/mandoc/eqn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: eqn.c,v 1.16 2014/10/12 20:08:43 schwarze Exp $ */ +/* $OpenBSD: eqn.c,v 1.17 2014/10/16 01:10:06 schwarze Exp $ */ /* * Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> @@ -586,6 +586,30 @@ eqn_box_makebinary(struct eqn_node *ep, } /* + * Parse the "delim" control statement. + */ +static void +eqn_delim(struct eqn_node *ep) +{ + const char *start; + size_t sz; + + if ((start = eqn_nextrawtok(ep, &sz)) == NULL) + mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse, + ep->eqn.ln, ep->eqn.pos, "delim"); + else if (strncmp(start, "off", 3) == 0) + ep->delim = 0; + else if (strncmp(start, "on", 2) == 0) { + if (ep->odelim && ep->cdelim) + ep->delim = 1; + } else if (start[1] != '\0') { + ep->odelim = start[0]; + ep->cdelim = start[1]; + ep->delim = 1; + } +} + +/* * Undefine a previously-defined string. */ static int @@ -696,6 +720,8 @@ this_tok: EQN_MSG(MANDOCERR_EQNEOF, ep); break; case (EQN_TOK_DELIM): + eqn_delim(ep); + break; case (EQN_TOK_GFONT): if (eqn_nextrawtok(ep, NULL) == NULL) mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse, diff --git a/usr.bin/mandoc/libmandoc.h b/usr.bin/mandoc/libmandoc.h index ddc661a620a..45a83edf08a 100644 --- a/usr.bin/mandoc/libmandoc.h +++ b/usr.bin/mandoc/libmandoc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: libmandoc.h,v 1.29 2014/09/06 22:38:35 schwarze Exp $ */ +/* $OpenBSD: libmandoc.h,v 1.30 2014/10/16 01:10:06 schwarze Exp $ */ /* * Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org> @@ -75,12 +75,6 @@ char *roff_strdup(const struct roff *, const char *); int roff_getcontrol(const struct roff *, const char *, int *); int roff_getformat(const struct roff *); -#if 0 -char roff_eqndelim(const struct roff *); -void roff_openeqn(struct roff *, const char *, - int, int, const char *); -int roff_closeeqn(struct roff *); -#endif const struct tbl_span *roff_span(const struct roff *); const struct eqn *roff_eqn(const struct roff *); diff --git a/usr.bin/mandoc/libroff.h b/usr.bin/mandoc/libroff.h index 17c5f01ff90..3f555a1a8f9 100644 --- a/usr.bin/mandoc/libroff.h +++ b/usr.bin/mandoc/libroff.h @@ -1,6 +1,7 @@ -/* $Id: libroff.h,v 1.7 2014/04/20 16:44:44 schwarze Exp $ */ +/* $OpenBSD: libroff.h,v 1.8 2014/10/16 01:10:06 schwarze Exp $ */ /* * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> + * Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -43,16 +44,19 @@ struct tbl_node { }; struct eqn_node { - struct eqn_def *defs; - size_t defsz; - char *data; - size_t rew; - size_t cur; - size_t sz; - int gsize; - struct eqn eqn; - struct mparse *parse; - struct eqn_node *next; + struct eqn eqn; /* syntax tree of this equation */ + struct mparse *parse; /* main parser, for error reporting */ + struct eqn_node *next; /* singly linked list of equations */ + struct eqn_def *defs; /* array of definitions */ + char *data; /* source code of this equation */ + size_t defsz; /* number of definitions */ + size_t sz; /* length of the source code */ + size_t cur; /* parse point in the source code */ + size_t rew; /* beginning of the current token */ + int gsize; /* default point size */ + int delim; /* in-line delimiters enabled */ + char odelim; /* in-line opening delimiter */ + char cdelim; /* in-line closing delimiter */ }; struct eqn_def { diff --git a/usr.bin/mandoc/mdoc.c b/usr.bin/mandoc/mdoc.c index 00066b18345..ee6b8d90326 100644 --- a/usr.bin/mandoc/mdoc.c +++ b/usr.bin/mandoc/mdoc.c @@ -1,4 +1,4 @@ -/* $Id: mdoc.c,v 1.114 2014/09/06 23:24:27 schwarze Exp $ */ +/* $OpenBSD: mdoc.c,v 1.115 2014/10/16 01:10:06 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org> @@ -89,9 +89,6 @@ static struct mdoc_node *node_alloc(struct mdoc *, int, int, enum mdoct, enum mdoc_type); static int node_append(struct mdoc *, struct mdoc_node *); -#if 0 -static int mdoc_preptext(struct mdoc *, int, char *, int); -#endif static int mdoc_ptext(struct mdoc *, int, char *, int); static int mdoc_pmacro(struct mdoc *, int, char *, int); @@ -607,60 +604,6 @@ mdoc_node_relink(struct mdoc *mdoc, struct mdoc_node *p) return(node_append(mdoc, p)); } -#if 0 -/* - * Pre-treat a text line. - * Text lines can consist of equations, which must be handled apart from - * the regular text. - * Thus, use this function to step through a line checking if it has any - * equations embedded in it. - * This must handle multiple equations AND equations that do not end at - * the end-of-line, i.e., will re-enter in the next roff parse. - */ -static int -mdoc_preptext(struct mdoc *mdoc, int line, char *buf, int offs) -{ - char *start, *end; - char delim; - - while ('\0' != buf[offs]) { - /* Mark starting position if eqn is set. */ - start = NULL; - if ('\0' != (delim = roff_eqndelim(mdoc->roff))) - if (NULL != (start = strchr(buf + offs, delim))) - *start++ = '\0'; - - /* Parse text as normal. */ - if ( ! mdoc_ptext(mdoc, line, buf, offs)) - return(0); - - /* Continue only if an equation exists. */ - if (NULL == start) - break; - - /* Read past the end of the equation. */ - offs += start - (buf + offs); - assert(start == &buf[offs]); - if (NULL != (end = strchr(buf + offs, delim))) { - *end++ = '\0'; - while (' ' == *end) - end++; - } - - /* Parse the equation itself. */ - roff_openeqn(mdoc->roff, NULL, line, offs, buf); - - /* Process a finished equation? */ - if (roff_closeeqn(mdoc->roff)) - if ( ! mdoc_addeqn(mdoc, roff_eqn(mdoc->roff))) - return(0); - offs += (end - (buf + offs)); - } - - return(1); -} -#endif - /* * Parse free-form text, that is, a line that does not begin with the * control character. diff --git a/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c index 72da009aafd..469ad2535f9 100644 --- a/usr.bin/mandoc/roff.c +++ b/usr.bin/mandoc/roff.c @@ -1,4 +1,4 @@ -/* $OpenBSD: roff.c,v 1.101 2014/09/07 00:21:23 schwarze Exp $ */ +/* $OpenBSD: roff.c,v 1.102 2014/10/16 01:10:06 schwarze Exp $ */ /* * Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org> @@ -118,6 +118,7 @@ struct roff { struct eqn_node *last_eqn; /* last equation parsed */ struct eqn_node *first_eqn; /* first equation parsed */ struct eqn_node *eqn; /* current equation being parsed */ + int eqn_inline; /* current equation is inline */ int options; /* parse options */ int rstacksz; /* current size limit of rstack */ int rstackpos; /* position in rstack */ @@ -181,6 +182,8 @@ static enum rofferr roff_cond(ROFF_ARGS); static enum rofferr roff_cond_text(ROFF_ARGS); static enum rofferr roff_cond_sub(ROFF_ARGS); static enum rofferr roff_ds(ROFF_ARGS); +static enum rofferr roff_eqndelim(struct roff *, + char **, size_t *, int); static int roff_evalcond(const char *, int *); static int roff_evalnum(const char *, int *, int *, int); static int roff_evalpar(const char *, int *, int *); @@ -722,10 +725,17 @@ roff_parseln(struct roff *r, int ln, char **bufp, enum rofferr e; int ppos, ctl; - /* - * Run the reserved-word filter only if we have some reserved - * words to fill in. - */ + /* Handle in-line equation delimiters. */ + + if (r->last_eqn != NULL && r->last_eqn->delim && + (r->eqn == NULL || r->eqn_inline)) { + e = roff_eqndelim(r, bufp, szp, pos); + if (e == ROFF_REPARSE) + return(e); + assert(e == ROFF_CONT); + } + + /* Expand some escape sequences. */ e = roff_res(r, bufp, szp, ln, pos); if (ROFF_IGN == e) @@ -1839,14 +1849,48 @@ roff_T_(ROFF_ARGS) return(ROFF_IGN); } -#if 0 -static int -roff_closeeqn(struct roff *r) +/* + * Handle in-line equation delimiters. + */ +static enum rofferr +roff_eqndelim(struct roff *r, char **bufp, size_t *szp, int pos) { + char *cp1, *cp2; - return(r->eqn && ROFF_EQN == eqn_end(&r->eqn) ? 1 : 0); + /* + * Outside equations, look for an opening delimiter. + * If we are inside an equation, we already know it is + * in-line, or this function wouldn't have been called; + * so look for a closing delimiter. + */ + + cp1 = *bufp + pos; + cp2 = strchr(cp1, r->eqn == NULL ? + r->last_eqn->odelim : r->last_eqn->cdelim); + if (cp2 == NULL) + return(ROFF_CONT); + + /* Found a delimiter; get rid of surrounding blanks. */ + + cp1 = cp2++; + while (cp2[0] == ' ') + cp2++; + while (cp1[-1] == ' ') + cp1--; + *cp1 = '\0'; + + /* Replace the delimiter with an equation macro. */ + + *szp = mandoc_asprintf(&cp1, "%s\n.E%c\n\\&%s", *bufp, + r->eqn == NULL ? 'Q' : 'N', cp2) + 1; + free(*bufp); + *bufp = cp1; + + /* Toggle the in-line state of the eqn subsystem. */ + + r->eqn_inline = r->eqn == NULL; + return(ROFF_REPARSE); } -#endif static void roff_openeqn(struct roff *r, const char *name, int line, @@ -1858,9 +1902,12 @@ roff_openeqn(struct roff *r, const char *name, int line, assert(NULL == r->eqn); e = eqn_alloc(name, offs, line, r->parse); - if (r->last_eqn) + if (r->last_eqn) { r->last_eqn->next = e; - else + e->delim = r->last_eqn->delim; + e->odelim = r->last_eqn->odelim; + e->cdelim = r->last_eqn->cdelim; + } else r->first_eqn = r->last_eqn = e; r->eqn = r->last_eqn = e; |