summaryrefslogtreecommitdiffstats
path: root/roff.c
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2017-06-06 15:01:04 +0000
committerIngo Schwarze <schwarze@openbsd.org>2017-06-06 15:01:04 +0000
commit3a094373dfa33d1e287d59127a8629dde3205dd8 (patch)
tree25ebac57ab1aa54735b559fef4ca6a55dc4494e2 /roff.c
parent57a85465cebb415008468ba9f16a7668e9119051 (diff)
downloadmandoc-3a094373dfa33d1e287d59127a8629dde3205dd8.tar.gz
Minimal implementation of the roff(7) .ce request (center a number
of input lines without filling). Contrary to groff, high-level macros abort .ce mode for now.
Diffstat (limited to 'roff.c')
-rw-r--r--roff.c69
1 files changed, 60 insertions, 9 deletions
diff --git a/roff.c b/roff.c
index de3e204c..b56e028b 100644
--- a/roff.c
+++ b/roff.c
@@ -189,7 +189,8 @@ static enum rofferr roff_nr(ROFF_ARGS);
static enum rofferr roff_onearg(ROFF_ARGS);
static enum roff_tok roff_parse(struct roff *, char *, int *,
int, int);
-static enum rofferr roff_parsetext(struct buf *, int, int *);
+static enum rofferr roff_parsetext(struct roff *, struct buf *,
+ int, int *);
static enum rofferr roff_res(struct roff *, struct buf *, int, int);
static enum rofferr roff_rm(ROFF_ARGS);
static enum rofferr roff_rr(ROFF_ARGS);
@@ -215,15 +216,16 @@ static enum rofferr roff_userdef(ROFF_ARGS);
#define ROFFNUM_WHITE (1 << 1) /* Skip whitespace in roff_evalnum(). */
const char *__roff_name[MAN_MAX + 1] = {
- "br", "ft", "ll", "mc",
- "sp", "ta", "ti", NULL,
+ "br", "ce", "ft", "ll",
+ "mc", "sp", "ta", "ti",
+ NULL,
"ab", "ad", "af", "aln",
"als", "am", "am1", "ami",
"ami1", "as", "as1", "asciify",
"backtrace", "bd", "bleedat", "blm",
"box", "boxa", "bp", "BP",
"break", "breakchar", "brnl", "brp",
- "brpnl", "c2", "cc", "ce",
+ "brpnl", "c2", "cc",
"cf", "cflags", "ch", "char",
"chop", "class", "close", "CL",
"color", "composite", "continue", "cp",
@@ -323,6 +325,7 @@ const char *const *roff_name = __roff_name;
static struct roffmac roffs[TOKEN_NONE] = {
{ roff_br, NULL, NULL, 0 }, /* br */
+ { roff_onearg, NULL, NULL, 0 }, /* ce */
{ roff_onearg, NULL, NULL, 0 }, /* ft */
{ roff_onearg, NULL, NULL, 0 }, /* ll */
{ roff_onearg, NULL, NULL, 0 }, /* mc */
@@ -357,7 +360,6 @@ static struct roffmac roffs[TOKEN_NONE] = {
{ roff_line_ignore, NULL, NULL, 0 }, /* brpnl */
{ roff_unsupp, NULL, NULL, 0 }, /* c2 */
{ roff_cc, NULL, NULL, 0 }, /* cc */
- { roff_line_ignore, NULL, NULL, 0 }, /* ce */
{ roff_insec, NULL, NULL, 0 }, /* cf */
{ roff_line_ignore, NULL, NULL, 0 }, /* cflags */
{ roff_line_ignore, NULL, NULL, 0 }, /* ch */
@@ -604,6 +606,8 @@ static const struct predef predefs[PREDEFS_MAX] = {
#include "predefs.in"
};
+static int roffce_lines; /* number of input lines to center */
+static struct roff_node *roffce_node; /* active request */
static int roffit_lines; /* number of lines to delay */
static char *roffit_macro; /* nil-terminated macro line */
@@ -1387,7 +1391,7 @@ roff_res(struct roff *r, struct buf *buf, int ln, int pos)
* Process text streams.
*/
static enum rofferr
-roff_parsetext(struct buf *buf, int pos, int *offs)
+roff_parsetext(struct roff *r, struct buf *buf, int pos, int *offs)
{
size_t sz;
const char *start;
@@ -1409,6 +1413,16 @@ roff_parsetext(struct buf *buf, int pos, int *offs)
} else if (roffit_lines > 1)
--roffit_lines;
+ if (roffce_node != NULL && buf->buf[pos] != '\0') {
+ if (roffce_lines < 1) {
+ r->man->last = roffce_node;
+ r->man->next = ROFF_NEXT_SIBLING;
+ roffce_lines = 0;
+ roffce_node = NULL;
+ } else
+ roffce_lines--;
+ }
+
/* Convert all breakable hyphens into ASCII_HYPH. */
start = p = buf->buf + pos;
@@ -1494,7 +1508,7 @@ roff_parseln(struct roff *r, int ln, struct buf *buf, int *offs)
if (r->tbl != NULL && ( ! ctl || buf->buf[pos] == '\0'))
return tbl_read(r->tbl, ln, buf->buf, ppos);
if ( ! ctl)
- return roff_parsetext(buf, pos, offs);
+ return roff_parsetext(r, buf, pos, offs);
/* Skip empty request lines. */
@@ -1535,6 +1549,16 @@ roff_parseln(struct roff *r, int ln, struct buf *buf, int *offs)
return tbl_read(r->tbl, ln, buf->buf, pos);
}
+ /* For now, let high level macros abort .ce mode. */
+
+ if (ctl && roffce_node != NULL &&
+ (t == TOKEN_NONE || t == ROFF_EQ || t == ROFF_TS)) {
+ r->man->last = roffce_node;
+ r->man->next = ROFF_NEXT_SIBLING;
+ roffce_lines = 0;
+ roffce_node = NULL;
+ }
+
/*
* This is neither a roff request nor a user-defined macro.
* Let the standard macro set parsers handle it.
@@ -2836,11 +2860,17 @@ roff_onearg(ROFF_ARGS)
{
struct roff_node *n;
char *cp;
+ int npos;
if (r->man->flags & (MAN_BLINE | MAN_ELINE) &&
(tok == ROFF_sp || tok == ROFF_ti))
man_breakscope(r->man, tok);
+ if (tok == ROFF_ce && roffce_node != NULL) {
+ r->man->last = roffce_node;
+ r->man->next = ROFF_NEXT_SIBLING;
+ }
+
roff_elem_alloc(r->man, ln, ppos, tok);
n = r->man->last;
@@ -2857,8 +2887,29 @@ roff_onearg(ROFF_ARGS)
roff_word_alloc(r->man, ln, pos, buf->buf + pos);
}
- n->flags |= NODE_LINE | NODE_VALID | NODE_ENDED;
- r->man->last = n;
+ if (tok == ROFF_ce) {
+ if (r->man->last->tok == ROFF_ce) {
+ roff_word_alloc(r->man, ln, pos, "1");
+ r->man->last->flags |= NODE_NOSRC;
+ }
+ npos = 0;
+ if (roff_evalnum(r, ln, r->man->last->string, &npos,
+ &roffce_lines, 0) == 0) {
+ mandoc_vmsg(MANDOCERR_CE_NONUM,
+ r->parse, ln, pos, "ce %s", buf->buf + pos);
+ roffce_lines = 1;
+ }
+ if (roffce_lines < 1) {
+ r->man->last = r->man->last->parent;
+ roffce_node = NULL;
+ roffce_lines = 0;
+ } else
+ roffce_node = r->man->last->parent;
+ } else {
+ n->flags |= NODE_VALID | NODE_ENDED;
+ r->man->last = n;
+ }
+ n->flags |= NODE_LINE;
r->man->next = ROFF_NEXT_SIBLING;
return ROFF_IGN;
}