version 1.198, 2018/08/23 19:33:27 |
version 1.199, 2018/08/24 23:12:33 |
|
|
const char *file; /* filename of current input file */ |
const char *file; /* filename of current input file */ |
struct buf *primary; /* buffer currently being parsed */ |
struct buf *primary; /* buffer currently being parsed */ |
struct buf *secondary; /* copy of top level input */ |
struct buf *secondary; /* copy of top level input */ |
|
struct buf *loop; /* open .while request line */ |
const char *os_s; /* default operating system */ |
const char *os_s; /* default operating system */ |
mandocmsg mmsg; /* warning/error message handler */ |
mandocmsg mmsg; /* warning/error message handler */ |
enum mandoclevel file_status; /* status of current parse */ |
enum mandoclevel file_status; /* status of current parse */ |
|
|
static void choose_parser(struct mparse *); |
static void choose_parser(struct mparse *); |
static void free_buf_list(struct buf *); |
static void free_buf_list(struct buf *); |
static void resize_buf(struct buf *, size_t); |
static void resize_buf(struct buf *, size_t); |
static enum rofferr mparse_buf_r(struct mparse *, struct buf, size_t, int); |
static int mparse_buf_r(struct mparse *, struct buf, size_t, int); |
static int read_whole_file(struct mparse *, const char *, int, |
static int read_whole_file(struct mparse *, const char *, int, |
struct buf *, int *); |
struct buf *, int *); |
static void mparse_end(struct mparse *); |
static void mparse_end(struct mparse *); |
Line 266 static const char * const mandocerrs[MANDOCERR_MAX] = |
|
Line 267 static const char * const mandocerrs[MANDOCERR_MAX] = |
|
"input too large", |
"input too large", |
"unsupported control character", |
"unsupported control character", |
"unsupported roff request", |
"unsupported roff request", |
|
"nested .while loops", |
|
"end of scope with open .while loop", |
|
"end of .while loop in inner scope", |
|
"cannot continue this .while loop", |
"eqn delim option in tbl", |
"eqn delim option in tbl", |
"unsupported tbl layout modifier", |
"unsupported tbl layout modifier", |
"ignoring macro in table", |
"ignoring macro in table", |
Line 356 choose_parser(struct mparse *curp) |
|
Line 361 choose_parser(struct mparse *curp) |
|
* macros, inline equations, and input line traps) |
* macros, inline equations, and input line traps) |
* and indirectly (for .so file inclusion). |
* and indirectly (for .so file inclusion). |
*/ |
*/ |
static enum rofferr |
static int |
mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start) |
mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start) |
{ |
{ |
struct buf ln; |
struct buf ln; |
struct buf *firstln, *lastln, *thisln; |
struct buf *firstln, *lastln, *thisln, *loop; |
const char *save_file; |
const char *save_file; |
char *cp; |
char *cp; |
size_t pos; /* byte number in the ln buffer */ |
size_t pos; /* byte number in the ln buffer */ |
enum rofferr line_result, result; |
int line_result, result; |
int of; |
int of; |
int lnn; /* line number in the real file */ |
int lnn; /* line number in the real file */ |
int fd; |
int fd; |
|
int inloop; /* Saw .while on this level. */ |
unsigned char c; |
unsigned char c; |
|
|
ln.sz = 256; |
ln.sz = 256; |
ln.buf = mandoc_malloc(ln.sz); |
ln.buf = mandoc_malloc(ln.sz); |
ln.next = NULL; |
ln.next = NULL; |
firstln = NULL; |
firstln = loop = NULL; |
lnn = curp->line; |
lnn = curp->line; |
pos = 0; |
pos = 0; |
|
inloop = 0; |
result = ROFF_CONT; |
result = ROFF_CONT; |
|
|
while (i < blk.sz) { |
while (i < blk.sz && (blk.buf[i] != '\0' || pos != 0)) { |
if (0 == pos && '\0' == blk.buf[i]) |
|
break; |
|
|
|
if (start) { |
if (start) { |
curp->line = lnn; |
curp->line = lnn; |
curp->reparse_count = 0; |
curp->reparse_count = 0; |
Line 490 mparse_buf_r(struct mparse *curp, struct buf blk, size |
|
Line 494 mparse_buf_r(struct mparse *curp, struct buf blk, size |
|
rerun: |
rerun: |
line_result = roff_parseln(curp->roff, curp->line, &ln, &of); |
line_result = roff_parseln(curp->roff, curp->line, &ln, &of); |
|
|
switch (line_result) { |
/* Process options. */ |
|
|
|
if (line_result & ROFF_APPEND) |
|
assert(line_result == (ROFF_IGN | ROFF_APPEND)); |
|
|
|
if (line_result & ROFF_USERCALL) |
|
assert((line_result & ROFF_MASK) == ROFF_REPARSE); |
|
|
|
if (line_result & ROFF_USERRET) { |
|
assert(line_result == (ROFF_IGN | ROFF_USERRET)); |
|
if (start == 0) { |
|
/* Return from the current macro. */ |
|
result = ROFF_USERRET; |
|
goto out; |
|
} |
|
} |
|
|
|
switch (line_result & ROFF_LOOPMASK) { |
|
case ROFF_IGN: |
|
break; |
|
case ROFF_WHILE: |
|
if (curp->loop != NULL) { |
|
if (loop == curp->loop) |
|
break; |
|
mandoc_msg(MANDOCERR_WHILE_NEST, |
|
curp, curp->line, pos, NULL); |
|
} |
|
curp->loop = thisln; |
|
loop = NULL; |
|
inloop = 1; |
|
break; |
|
case ROFF_LOOPCONT: |
|
case ROFF_LOOPEXIT: |
|
if (curp->loop == NULL) { |
|
mandoc_msg(MANDOCERR_WHILE_FAIL, |
|
curp, curp->line, pos, NULL); |
|
break; |
|
} |
|
if (inloop == 0) { |
|
mandoc_msg(MANDOCERR_WHILE_INTO, |
|
curp, curp->line, pos, NULL); |
|
curp->loop = loop = NULL; |
|
break; |
|
} |
|
if (line_result & ROFF_LOOPCONT) |
|
loop = curp->loop; |
|
else { |
|
curp->loop = loop = NULL; |
|
inloop = 0; |
|
} |
|
break; |
|
default: |
|
abort(); |
|
} |
|
|
|
/* Process the main instruction from the roff parser. */ |
|
|
|
switch (line_result & ROFF_MASK) { |
|
case ROFF_IGN: |
|
break; |
|
case ROFF_CONT: |
|
if (curp->man->macroset == MACROSET_NONE) |
|
choose_parser(curp); |
|
if ((curp->man->macroset == MACROSET_MDOC ? |
|
mdoc_parseln(curp->man, curp->line, ln.buf, of) : |
|
man_parseln(curp->man, curp->line, ln.buf, of) |
|
) == 2) |
|
goto out; |
|
break; |
|
case ROFF_RERUN: |
|
goto rerun; |
case ROFF_REPARSE: |
case ROFF_REPARSE: |
case ROFF_USERCALL: |
|
if (++curp->reparse_count > REPARSE_LIMIT) { |
if (++curp->reparse_count > REPARSE_LIMIT) { |
|
/* Abort and return to the top level. */ |
result = ROFF_IGN; |
result = ROFF_IGN; |
mandoc_msg(MANDOCERR_ROFFLOOP, curp, |
mandoc_msg(MANDOCERR_ROFFLOOP, curp, |
curp->line, pos, NULL); |
curp->line, pos, NULL); |
} else { |
goto out; |
result = mparse_buf_r(curp, ln, of, 0); |
|
if (line_result == ROFF_USERCALL) { |
|
if (result == ROFF_USERRET) |
|
result = ROFF_CONT; |
|
roff_userret(curp->roff); |
|
} |
|
if (start || result == ROFF_CONT) { |
|
pos = 0; |
|
continue; |
|
} |
|
} |
} |
goto out; |
result = mparse_buf_r(curp, ln, of, 0); |
case ROFF_USERRET: |
if (line_result & ROFF_USERCALL) { |
if (start) { |
roff_userret(curp->roff); |
pos = 0; |
/* Continue normally. */ |
continue; |
if (result & ROFF_USERRET) |
|
result = ROFF_CONT; |
} |
} |
result = ROFF_USERRET; |
if (start == 0 && result != ROFF_CONT) |
goto out; |
goto out; |
case ROFF_APPEND: |
break; |
pos = strlen(ln.buf); |
|
continue; |
|
case ROFF_RERUN: |
|
goto rerun; |
|
case ROFF_IGN: |
|
pos = 0; |
|
continue; |
|
case ROFF_SO: |
case ROFF_SO: |
if ( ! (curp->options & MPARSE_SO) && |
if ( ! (curp->options & MPARSE_SO) && |
(i >= blk.sz || blk.buf[i] == '\0')) { |
(i >= blk.sz || blk.buf[i] == '\0')) { |
|
|
of = 0; |
of = 0; |
mparse_buf_r(curp, ln, of, 0); |
mparse_buf_r(curp, ln, of, 0); |
} |
} |
pos = 0; |
|
continue; |
|
default: |
|
break; |
break; |
|
default: |
|
abort(); |
} |
} |
|
|
if (curp->man->macroset == MACROSET_NONE) |
/* Start the next input line. */ |
choose_parser(curp); |
|
|
|
if ((curp->man->macroset == MACROSET_MDOC ? |
if (loop != NULL && |
mdoc_parseln(curp->man, curp->line, ln.buf, of) : |
(line_result & ROFF_LOOPMASK) == ROFF_IGN) |
man_parseln(curp->man, curp->line, ln.buf, of)) == 2) |
loop = loop->next; |
break; |
|
|
|
/* Temporary buffers typically are not full. */ |
if (loop != NULL) { |
|
if ((line_result & ROFF_APPEND) == 0) |
|
*ln.buf = '\0'; |
|
if (ln.sz < loop->sz) |
|
resize_buf(&ln, loop->sz); |
|
(void)strlcat(ln.buf, loop->buf, ln.sz); |
|
of = 0; |
|
goto rerun; |
|
} |
|
|
if (0 == start && '\0' == blk.buf[i]) |
pos = (line_result & ROFF_APPEND) ? strlen(ln.buf) : 0; |
break; |
|
|
|
/* Start the next input line. */ |
|
|
|
pos = 0; |
|
} |
} |
out: |
out: |
|
if (inloop) { |
|
if (result != ROFF_USERRET) |
|
mandoc_msg(MANDOCERR_WHILE_OUTOF, curp, |
|
curp->line, pos, NULL); |
|
curp->loop = NULL; |
|
} |
free(ln.buf); |
free(ln.buf); |
if (firstln != curp->secondary) |
if (firstln != curp->secondary) |
free_buf_list(firstln); |
free_buf_list(firstln); |