=================================================================== RCS file: /cvs/mandoc/roff.c,v retrieving revision 1.231 retrieving revision 1.237 diff -u -p -r1.231 -r1.237 --- mandoc/roff.c 2014/10/16 01:28:38 1.231 +++ mandoc/roff.c 2014/10/28 17:36:19 1.237 @@ -1,4 +1,4 @@ -/* $Id: roff.c,v 1.231 2014/10/16 01:28:38 schwarze Exp $ */ +/* $Id: roff.c,v 1.237 2014/10/28 17:36:19 schwarze Exp $ */ /* * Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons * Copyright (c) 2010-2014 Ingo Schwarze @@ -107,6 +107,7 @@ struct roffreg { struct roff { struct mparse *parse; /* parse point */ + const struct mchars *mchars; /* character table */ struct roffnode *last; /* leaf of stack */ int *rstack; /* stack of inverted `ie' values */ struct roffreg *regtab; /* number registers */ @@ -186,9 +187,12 @@ 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 *); +static int roff_evalcond(struct roff *r, int, + const char *, int *); +static int roff_evalnum(struct roff *, int, + const char *, int *, int *, int); +static int roff_evalpar(struct roff *, int, + const char *, int *, int *); static int roff_evalstrcond(const char *, int *); static void roff_free1(struct roff *); static void roff_freereg(struct roffreg *); @@ -204,8 +208,6 @@ static const char *roff_getstrn(const struct roff *, static enum rofferr roff_it(ROFF_ARGS); static enum rofferr roff_line_ignore(ROFF_ARGS); static enum rofferr roff_nr(ROFF_ARGS); -static void roff_openeqn(struct roff *, const char *, - int, int, const char *); static enum rofft roff_parse(struct roff *, char *, int *, int, int); static enum rofferr roff_parsetext(char **, size_t *, int, int *); @@ -475,12 +477,13 @@ roff_free(struct roff *r) } struct roff * -roff_alloc(struct mparse *parse, int options) +roff_alloc(struct mparse *parse, const struct mchars *mchars, int options) { struct roff *r; r = mandoc_calloc(1, sizeof(struct roff)); r->parse = parse; + r->mchars = mchars; r->options = options; r->format = options & (MPARSE_MDOC | MPARSE_MAN); r->rstackpos = -1; @@ -507,6 +510,8 @@ roff_res(struct roff *r, char **bufp, size_t *szp, int char *nbuf; /* new buffer to copy bufp to */ size_t maxl; /* expected length of the escape name */ size_t naml; /* actual length of the escape name */ + enum mandoc_esc esc; /* type of the escape sequence */ + int inaml; /* length returned from mandoc_escape() */ int expand_count; /* to avoid infinite loops */ int npos; /* position in numeric expression */ int arg_complete; /* argument not interrupted by eol */ @@ -550,7 +555,10 @@ roff_res(struct roff *r, char **bufp, size_t *szp, int res = ubuf; break; default: - if (ESCAPE_ERROR == mandoc_escape(&cp, NULL, NULL)) + esc = mandoc_escape(&cp, &stnam, &inaml); + if (esc == ESCAPE_ERROR || + (esc == ESCAPE_SPECIAL && + mchars_spec2cp(r->mchars, stnam, inaml) < 0)) mandoc_vmsg(MANDOCERR_ESC_BAD, r->parse, ln, (int)(stesc - *bufp), "%.*s", (int)(cp - stesc), stesc); @@ -622,7 +630,7 @@ roff_res(struct roff *r, char **bufp, size_t *szp, int case 'B': npos = 0; ubuf[0] = arg_complete && - roff_evalnum(stnam, &npos, NULL, 0) && + roff_evalnum(r, ln, stnam, &npos, NULL, 0) && stnam + npos + 1 == cp ? '1' : '0'; ubuf[1] = '\0'; break; @@ -729,7 +737,8 @@ roff_parseln(struct roff *r, int ln, char **bufp, /* Handle in-line equation delimiters. */ - if (r->last_eqn != NULL && r->last_eqn->delim && + if (r->tbl == NULL && + 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) @@ -1240,7 +1249,7 @@ out: * or string condition. */ static int -roff_evalcond(const char *v, int *pos) +roff_evalcond(struct roff *r, int ln, const char *v, int *pos) { int wanttrue, number; @@ -1271,7 +1280,7 @@ roff_evalcond(const char *v, int *pos) break; } - if (roff_evalnum(v, pos, &number, 0)) + if (roff_evalnum(r, ln, v, pos, &number, 0)) return((number > 0) == wanttrue); else return(roff_evalstrcond(v, pos) == wanttrue); @@ -1300,7 +1309,7 @@ roff_cond(ROFF_ARGS) r->last->rule = ROFF_el == tok ? (r->rstackpos < 0 ? 0 : r->rstack[r->rstackpos--]) : - roff_evalcond(*bufp, &pos); + roff_evalcond(r, ln, *bufp, &pos); /* * An if-else will put the NEGATION of the current evaluated @@ -1466,14 +1475,15 @@ roff_getop(const char *v, int *pos, char *res) * or a single signed integer number. */ static int -roff_evalpar(const char *v, int *pos, int *res) +roff_evalpar(struct roff *r, int ln, + const char *v, int *pos, int *res) { if ('(' != v[*pos]) return(roff_getnum(v, pos, res)); (*pos)++; - if ( ! roff_evalnum(v, pos, res, 1)) + if ( ! roff_evalnum(r, ln, v, pos, res, 1)) return(0); /* @@ -1495,7 +1505,8 @@ roff_evalpar(const char *v, int *pos, int *res) * Proceed left to right, there is no concept of precedence. */ static int -roff_evalnum(const char *v, int *pos, int *res, int skipwhite) +roff_evalnum(struct roff *r, int ln, const char *v, + int *pos, int *res, int skipwhite) { int mypos, operand2; char operator; @@ -1509,7 +1520,7 @@ roff_evalnum(const char *v, int *pos, int *res, int sk while (isspace((unsigned char)v[*pos])) (*pos)++; - if ( ! roff_evalpar(v, pos, res)) + if ( ! roff_evalpar(r, ln, v, pos, res)) return(0); while (1) { @@ -1524,7 +1535,7 @@ roff_evalnum(const char *v, int *pos, int *res, int sk while (isspace((unsigned char)v[*pos])) (*pos)++; - if ( ! roff_evalpar(v, pos, &operand2)) + if ( ! roff_evalpar(r, ln, v, pos, &operand2)) return(0); if (skipwhite) @@ -1545,6 +1556,12 @@ roff_evalnum(const char *v, int *pos, int *res, int sk *res *= operand2; break; case '/': + if (0 == operand2) { + mandoc_msg(MANDOCERR_DIVZERO, + r->parse, ln, *pos, v); + *res = 0; + break; + } *res /= operand2; break; case '%': @@ -1719,7 +1736,7 @@ roff_nr(ROFF_ARGS) if ('+' == sign || '-' == sign) val++; - if (roff_evalnum(val, NULL, &iv, 0)) + if (roff_evalnum(r, ln, val, NULL, &iv, 0)) roff_setreg(r, key, iv, sign); return(ROFF_IGN); @@ -1857,7 +1874,8 @@ roff_T_(ROFF_ARGS) static enum rofferr roff_eqndelim(struct roff *r, char **bufp, size_t *szp, int pos) { - char *cp1, *cp2; + char *cp1, *cp2; + const char *bef_pr, *bef_nl, *mac, *aft_nl, *aft_pr; /* * Outside equations, look for an opening delimiter. @@ -1872,19 +1890,41 @@ roff_eqndelim(struct roff *r, char **bufp, size_t *szp if (cp2 == NULL) return(ROFF_CONT); - /* Found a delimiter; get rid of surrounding blanks. */ + *cp2++ = '\0'; + bef_pr = bef_nl = aft_nl = aft_pr = ""; - cp1 = cp2++; - while (cp2[0] == ' ') - cp2++; - while (cp1[-1] == ' ') - cp1--; - *cp1 = '\0'; + /* Handle preceding text, protecting whitespace. */ - /* Replace the delimiter with an equation macro. */ + if (**bufp != '\0') { + if (r->eqn == NULL) + bef_pr = "\\&"; + bef_nl = "\n"; + } - *szp = mandoc_asprintf(&cp1, "%s\n.E%s%s", *bufp, - r->eqn == NULL ? "Q\n" : "N\n\\&", cp2) + 1; + /* + * 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; @@ -1894,15 +1934,13 @@ roff_eqndelim(struct roff *r, char **bufp, size_t *szp return(ROFF_REPARSE); } -static void -roff_openeqn(struct roff *r, const char *name, int line, - int offs, const char *buf) +static enum rofferr +roff_EQ(ROFF_ARGS) { struct eqn_node *e; - int poff; assert(NULL == r->eqn); - e = eqn_alloc(name, offs, line, r->parse); + e = eqn_alloc(ppos, ln, r->parse); if (r->last_eqn) { r->last_eqn->next = e; @@ -1914,17 +1952,10 @@ roff_openeqn(struct roff *r, const char *name, int lin r->eqn = r->last_eqn = e; - if (buf) { - poff = 0; - eqn_read(&r->eqn, line, buf, offs, &poff); - } -} + if ((*bufp)[pos]) + mandoc_vmsg(MANDOCERR_ARG_SKIP, r->parse, ln, pos, + ".EQ %s", *bufp + pos); -static enum rofferr -roff_EQ(ROFF_ARGS) -{ - - roff_openeqn(r, *bufp + pos, ln, ppos, NULL); return(ROFF_IGN); }