aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/read.c
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2018-08-23 14:29:38 +0000
committerIngo Schwarze <schwarze@openbsd.org>2018-08-23 14:29:38 +0000
commitc56c17992552256b55134ead16c3e16164fd2e67 (patch)
treecfe287e6cfd33a9dcb04a6a781b093af17e5b556 /read.c
parent1483cf671448b44a8bf37ea7129c88e24f588abd (diff)
downloadmandoc-c56c17992552256b55134ead16c3e16164fd2e67.tar.gz
mandoc-c56c17992552256b55134ead16c3e16164fd2e67.tar.zst
mandoc-c56c17992552256b55134ead16c3e16164fd2e67.zip
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.c44
1 files changed, 32 insertions, 12 deletions
diff --git a/read.c b/read.c
index 0a583445..12901bd3 100644
--- a/read.c
+++ b/read.c
@@ -1,4 +1,4 @@
-/* $Id: read.c,v 1.196 2018/07/28 18:34:15 schwarze Exp $ */
+/* $Id: read.c,v 1.197 2018/08/23 14:29:38 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2018 Ingo Schwarze <schwarze@openbsd.org>
@@ -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