=================================================================== RCS file: /cvs/mandoc/roff.c,v retrieving revision 1.227 retrieving revision 1.233 diff -u -p -r1.227 -r1.233 --- mandoc/roff.c 2014/09/06 22:39:36 1.227 +++ mandoc/roff.c 2014/10/20 15:04:56 1.233 @@ -1,4 +1,4 @@ -/* $Id: roff.c,v 1.227 2014/09/06 22:39:36 schwarze Exp $ */ +/* $Id: roff.c,v 1.233 2014/10/20 15:04:56 schwarze Exp $ */ /* * Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons * Copyright (c) 2010-2014 Ingo Schwarze @@ -60,6 +60,7 @@ enum rofft { ROFF_nh, ROFF_nr, ROFF_ns, + ROFF_pl, ROFF_ps, ROFF_rm, ROFF_rr, @@ -119,6 +120,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 */ @@ -182,6 +184,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 *); @@ -256,6 +260,7 @@ static struct roffmac roffs[ROFF_MAX] = { { "nh", roff_line_ignore, NULL, NULL, 0, NULL }, { "nr", roff_nr, NULL, NULL, 0, NULL }, { "ns", roff_line_ignore, NULL, NULL, 0, NULL }, + { "pl", roff_line_ignore, NULL, NULL, 0, NULL }, { "ps", roff_line_ignore, NULL, NULL, 0, NULL }, { "rm", roff_rm, NULL, NULL, 0, NULL }, { "rr", roff_rr, NULL, NULL, 0, NULL }, @@ -722,11 +727,18 @@ 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) return(e); @@ -759,6 +771,15 @@ roff_parseln(struct roff *r, int ln, char **bufp, return(roff_parsetext(bufp, szp, pos, offs)); } + /* Skip empty request lines. */ + + if ((*bufp)[pos] == '"') { + mandoc_msg(MANDOCERR_COMMENT_BAD, r->parse, + ln, pos, NULL); + return(ROFF_IGN); + } else if ((*bufp)[pos] == '\0') + return(ROFF_IGN); + /* * If a scope is open, go to the child handler for that macro, * as it may want to preprocess before doing anything with it. @@ -1830,14 +1851,71 @@ 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; + const char *bef_pr, *bef_nl, *mac, *aft_nl, *aft_pr; - 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); + + *cp2++ = '\0'; + bef_pr = bef_nl = aft_nl = aft_pr = ""; + + /* Handle preceding text, protecting whitespace. */ + + if (**bufp != '\0') { + if (r->eqn == NULL) + bef_pr = "\\&"; + bef_nl = "\n"; + } + + /* + * Prepare replacing the delimiter with an equation macro + * and drop leading white space from the equation. + */ + + if (r->eqn == NULL) { + while (*cp2 == ' ') + cp2++; + mac = ".EQ"; + } else + mac = ".EN"; + + /* Handle following text, protecting whitespace. */ + + if (*cp2 != '\0') { + aft_nl = "\n"; + if (r->eqn != NULL) + aft_pr = "\\&"; + } + + /* Do the actual replacement. */ + + *szp = mandoc_asprintf(&cp1, "%s%s%s%s%s%s%s", *bufp, + bef_pr, bef_nl, mac, aft_nl, aft_pr, 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, @@ -1849,9 +1927,12 @@ roff_openeqn(struct roff *r, const char *name, int lin 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;