diff options
author | Ingo Schwarze <schwarze@openbsd.org> | 2018-08-23 14:29:38 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@openbsd.org> | 2018-08-23 14:29:38 +0000 |
commit | a99c9a30e9f41eb3ce553ac0b2ac6ff963ebe49d (patch) | |
tree | 9de2c70188a81c04c2b08671dcf1d3eb421403da /read.c | |
parent | 50f5bf83cff66e2f7baa88e327d78c37143bed97 (diff) | |
download | mandoc-a99c9a30e9f41eb3ce553ac0b2ac6ff963ebe49d.tar.gz |
Implement the roff(7) .shift and .return requests,
for example used by groff_hdtbl(7) and groff_mom(7).
Also correctly interpolate arguments during nested macro execution
even after .shift and .return, implemented using a stack of argument
arrays.
Note that only read.c, but not roff.c can detect the end of a macro
execution, and the existence of .shift implies that arguments cannot
be interpolated up front, so unfortunately, this includes a partial
revert of roff.c rev. 1.337, moving argument interpolation back into
the function roff_res().
Diffstat (limited to 'read.c')
-rw-r--r-- | read.c | 42 |
1 files changed, 31 insertions, 11 deletions
@@ -62,7 +62,7 @@ struct mparse { static void choose_parser(struct mparse *); static void resize_buf(struct buf *, size_t); -static int mparse_buf_r(struct mparse *, struct buf, size_t, int); +static enum rofferr mparse_buf_r(struct mparse *, struct buf, size_t, int); static int read_whole_file(struct mparse *, const char *, int, struct buf *, int *); static void mparse_end(struct mparse *); @@ -233,6 +233,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = { "input stack limit exceeded, infinite loop?", "skipping bad character", "skipping unknown macro", + "ignoring request outside macro", "skipping insecure request", "skipping item outside list", "skipping column outside column list", @@ -243,6 +244,8 @@ static const char * const mandocerrs[MANDOCERR_MAX] = { /* related to request and macro arguments */ "escaped character not allowed in a name", + "using macro argument outside macro", + "argument number is not numeric", "NOT IMPLEMENTED: Bd -file", "skipping display without arguments", "missing list type, using -item", @@ -251,6 +254,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = { "uname(3) system call failed, using UNKNOWN", "unknown standard specifier", "skipping request without numeric argument", + "excessive shift", "NOT IMPLEMENTED: .so with absolute path or \"..\"", ".so request failed", "skipping all arguments", @@ -338,14 +342,14 @@ choose_parser(struct mparse *curp) * macros, inline equations, and input line traps) * and indirectly (for .so file inclusion). */ -static int +static enum rofferr mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start) { struct buf ln; const char *save_file; char *cp; size_t pos; /* byte number in the ln buffer */ - enum rofferr rr; + enum rofferr line_result, sub_result; int of; int lnn; /* line number in the real file */ int fd; @@ -468,20 +472,36 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start) [curp->secondary->sz] = '\0'; } rerun: - rr = roff_parseln(curp->roff, curp->line, &ln, &of); + line_result = roff_parseln(curp->roff, curp->line, &ln, &of); - switch (rr) { + switch (line_result) { case ROFF_REPARSE: - if (++curp->reparse_count > REPARSE_LIMIT) + case ROFF_USERCALL: + if (++curp->reparse_count > REPARSE_LIMIT) { + sub_result = ROFF_IGN; mandoc_msg(MANDOCERR_ROFFLOOP, curp, curp->line, pos, NULL); - else if (mparse_buf_r(curp, ln, of, 0) == 1 || - start == 1) { + } else { + sub_result = mparse_buf_r(curp, ln, of, 0); + if (line_result == ROFF_USERCALL) { + if (sub_result == ROFF_USERRET) + sub_result = ROFF_CONT; + roff_userret(curp->roff); + } + if (start || sub_result == ROFF_CONT) { + pos = 0; + continue; + } + } + free(ln.buf); + return sub_result; + case ROFF_USERRET: + if (start) { pos = 0; continue; } free(ln.buf); - return 0; + return ROFF_USERRET; case ROFF_APPEND: pos = strlen(ln.buf); continue; @@ -495,7 +515,7 @@ rerun: (i >= blk.sz || blk.buf[i] == '\0')) { curp->sodest = mandoc_strdup(ln.buf + of); free(ln.buf); - return 1; + return ROFF_CONT; } /* * We remove `so' clauses from our lookaside @@ -547,7 +567,7 @@ rerun: } free(ln.buf); - return 1; + return ROFF_CONT; } static int |