diff options
author | Ingo Schwarze <schwarze@openbsd.org> | 2017-06-06 15:01:04 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@openbsd.org> | 2017-06-06 15:01:04 +0000 |
commit | 3a094373dfa33d1e287d59127a8629dde3205dd8 (patch) | |
tree | 25ebac57ab1aa54735b559fef4ca6a55dc4494e2 /roff.c | |
parent | 57a85465cebb415008468ba9f16a7668e9119051 (diff) | |
download | mandoc-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.c | 69 |
1 files changed, 60 insertions, 9 deletions
@@ -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; } |