=================================================================== RCS file: /cvs/mandoc/roff.c,v retrieving revision 1.147 retrieving revision 1.154 diff -u -p -r1.147 -r1.154 --- mandoc/roff.c 2011/07/18 07:46:41 1.147 +++ mandoc/roff.c 2011/07/27 07:09:41 1.154 @@ -1,4 +1,4 @@ -/* $Id: roff.c,v 1.147 2011/07/18 07:46:41 kristaps Exp $ */ +/* $Id: roff.c,v 1.154 2011/07/27 07:09:41 kristaps Exp $ */ /* * Copyright (c) 2010, 2011 Kristaps Dzonsons * Copyright (c) 2010, 2011 Ingo Schwarze @@ -159,7 +159,7 @@ static const char *roff_getstrn(const struct roff *, const char *, size_t); static enum rofferr roff_line_ignore(ROFF_ARGS); static enum rofferr roff_nr(ROFF_ARGS); -static int roff_res(struct roff *, +static void roff_res(struct roff *, char **, size_t *, int, int); static enum rofferr roff_rm(ROFF_ARGS); static void roff_setstr(struct roff *, @@ -395,15 +395,16 @@ roff_alloc(struct mparse *parse) return(r); } - /* * Pre-filter each and every line for reserved words (one beginning with * `\*', e.g., `\*(ab'). These must be handled before the actual line * is processed. + * This also checks the syntax of regular escapes. */ -static int +static void roff_res(struct roff *r, char **bufp, size_t *szp, int ln, int pos) { + enum mandoc_esc esc; const char *stesc; /* start of an escape sequence ('\\') */ const char *stnam; /* start of the name, after "[(*" */ const char *cp; /* end of the name, e.g. before ']' */ @@ -412,8 +413,7 @@ roff_res(struct roff *r, char **bufp, size_t *szp, int size_t nsz; char *n; - /* Search for a leading backslash and save a pointer to it. */ - +again: cp = *bufp + pos; while (NULL != (cp = strchr(cp, '\\'))) { stesc = cp++; @@ -425,10 +425,22 @@ roff_res(struct roff *r, char **bufp, size_t *szp, int */ if ('\0' == *cp) - return(1); - if ('*' != *cp++) - continue; + return; + if ('*' != *cp) { + res = cp; + esc = mandoc_escape(&cp, NULL, NULL); + if (ESCAPE_ERROR != esc) + continue; + cp = res; + mandoc_msg + (MANDOCERR_BADESCAPE, r->parse, + ln, (int)(stesc - *bufp), NULL); + return; + } + + cp++; + /* * The third character decides the length * of the name of the string. @@ -437,7 +449,7 @@ roff_res(struct roff *r, char **bufp, size_t *szp, int switch (*cp) { case ('\0'): - return(1); + return; case ('('): cp++; maxl = 2; @@ -455,8 +467,13 @@ roff_res(struct roff *r, char **bufp, size_t *szp, int /* Advance to the end of the name. */ for (i = 0; 0 == maxl || i < maxl; i++, cp++) { - if ('\0' == *cp) - return(1); /* Error. */ + if ('\0' == *cp) { + mandoc_msg + (MANDOCERR_BADESCAPE, + r->parse, ln, + (int)(stesc - *bufp), NULL); + return; + } if (0 == maxl && ']' == *cp) break; } @@ -469,13 +486,16 @@ roff_res(struct roff *r, char **bufp, size_t *szp, int res = roff_getstrn(r, stnam, (size_t)i); if (NULL == res) { - /* TODO: keep track of the correct position. */ - mandoc_msg(MANDOCERR_BADESCAPE, r->parse, ln, pos, NULL); + mandoc_msg + (MANDOCERR_BADESCAPE, r->parse, + ln, (int)(stesc - *bufp), NULL); res = ""; } /* Replace the escape sequence by the string. */ + pos += (stesc - *bufp); + nsz = *szp + strlen(res) + 1; n = mandoc_malloc(nsz); @@ -487,13 +507,43 @@ roff_res(struct roff *r, char **bufp, size_t *szp, int *bufp = n; *szp = nsz; - return(0); + goto again; } - - return(1); } +/* + * Process text streams: convert all breakable hyphens into ASCII_HYPH. + */ +static enum rofferr +roff_parsetext(char *p) +{ + size_t sz; + const char *start; + enum mandoc_esc esc; + start = p; + + while ('\0' != *p) { + sz = strcspn(p, "-\\"); + p += sz; + + if ('\\' == *p) { + /* Skip over escapes. */ + p++; + esc = mandoc_escape + ((const char **)&p, NULL, NULL); + if (ESCAPE_ERROR == esc) + break; + } else if ('-' == *p) { + if (mandoc_hyph(start, p)) + *p = ASCII_HYPH; + p++; + } + } + + return(ROFF_CONT); +} + enum rofferr roff_parseln(struct roff *r, int ln, char **bufp, size_t *szp, int pos, int *offs) @@ -507,8 +557,7 @@ roff_parseln(struct roff *r, int ln, char **bufp, * words to fill in. */ - if (r->first_string && ! roff_res(r, bufp, szp, ln, pos)) - return(ROFF_REPARSE); + roff_res(r, bufp, szp, ln, pos); ppos = pos; ctl = mandoc_getcontrol(*bufp, &pos); @@ -533,13 +582,13 @@ roff_parseln(struct roff *r, int ln, char **bufp, return(eqn_read(&r->eqn, ln, *bufp, pos, offs)); if (r->tbl) return(tbl_read(r->tbl, ln, *bufp, pos)); - return(ROFF_CONT); + return(roff_parsetext(*bufp + pos)); } else if ( ! ctl) { if (r->eqn) return(eqn_read(&r->eqn, ln, *bufp, pos, offs)); if (r->tbl) return(tbl_read(r->tbl, ln, *bufp, pos)); - return(ROFF_CONT); + return(roff_parsetext(*bufp + pos)); } else if (r->eqn) return(eqn_read(&r->eqn, ln, *bufp, ppos, offs)); @@ -583,16 +632,14 @@ roff_endparse(struct roff *r) if (r->eqn) { mandoc_msg(MANDOCERR_SCOPEEXIT, r->parse, - r->eqn->eqn.line, r->eqn->eqn.pos, NULL); - eqn_end(r->eqn); - r->eqn = NULL; + r->eqn->eqn.ln, r->eqn->eqn.pos, NULL); + eqn_end(&r->eqn); } if (r->tbl) { mandoc_msg(MANDOCERR_SCOPEEXIT, r->parse, r->tbl->line, r->tbl->pos, NULL); - tbl_end(r->tbl); - r->tbl = NULL; + tbl_end(&r->tbl); } } @@ -1149,7 +1196,7 @@ roff_nr(ROFF_ARGS) if (0 == strcmp(key, "nS")) { r->regs[(int)REG_nS].set = 1; - if ((iv = mandoc_strntou(val, strlen(val), 10)) >= 0) + if ((iv = mandoc_strntoi(val, strlen(val), 10)) >= 0) r->regs[(int)REG_nS].u = (unsigned)iv; else r->regs[(int)REG_nS].u = 0u; @@ -1182,9 +1229,8 @@ roff_TE(ROFF_ARGS) if (NULL == r->tbl) mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL); else - tbl_end(r->tbl); + tbl_end(&r->tbl); - r->tbl = NULL; return(ROFF_IGN); } @@ -1201,14 +1247,22 @@ roff_T_(ROFF_ARGS) return(ROFF_IGN); } -/* ARGSUSED */ -static enum rofferr -roff_EQ(ROFF_ARGS) +int +roff_closeeqn(struct roff *r) { - struct eqn_node *e; + return(r->eqn && ROFF_EQN == eqn_end(&r->eqn) ? 1 : 0); +} + +void +roff_openeqn(struct roff *r, const char *name, int line, + int offs, const char *buf) +{ + struct eqn_node *e; + int poff; + assert(NULL == r->eqn); - e = eqn_alloc(ppos, ln, r->parse); + e = eqn_alloc(name, offs, line, r->parse); if (r->last_eqn) r->last_eqn->next = e; @@ -1216,6 +1270,19 @@ roff_EQ(ROFF_ARGS) r->first_eqn = r->last_eqn = e; r->eqn = r->last_eqn = e; + + if (buf) { + poff = 0; + eqn_read(&r->eqn, line, buf, offs, &poff); + } +} + +/* ARGSUSED */ +static enum rofferr +roff_EQ(ROFF_ARGS) +{ + + roff_openeqn(r, *bufp + pos, ln, ppos, NULL); return(ROFF_IGN); } @@ -1236,7 +1303,7 @@ roff_TS(ROFF_ARGS) if (r->tbl) { mandoc_msg(MANDOCERR_SCOPEBROKEN, r->parse, ln, ppos, NULL); - tbl_end(r->tbl); + tbl_end(&r->tbl); } t = tbl_alloc(ppos, ln, r->parse); @@ -1471,4 +1538,11 @@ roff_eqn(const struct roff *r) { return(r->last_eqn ? &r->last_eqn->eqn : NULL); +} + +char +roff_eqndelim(const struct roff *r) +{ + + return('\0'); }