-/* $Id: man_macro.c,v 1.115 2017/01/10 13:47:00 schwarze Exp $ */
+/* $Id: man_macro.c,v 1.132 2018/08/18 20:41:54 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2012, 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2012-2015, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
*
* Permission to use, copy, modify, and distribute this software for any
static void in_line_eoln(MACRO_PROT_ARGS);
static int man_args(struct roff_man *, int,
int *, char *, char **);
-static void rew_scope(struct roff_man *, int);
+static void rew_scope(struct roff_man *, enum roff_tok);
-const struct man_macro __man_macros[MAN_MAX] = {
- { in_line_eoln, MAN_NSCOPED }, /* br */
+static const struct man_macro man_macros[MAN_MAX - MAN_TH] = {
{ in_line_eoln, MAN_BSCOPE }, /* TH */
{ blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* SH */
{ blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* SS */
{ blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* TP */
+ { blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* TQ */
{ blk_imp, MAN_BSCOPE }, /* LP */
{ blk_imp, MAN_BSCOPE }, /* PP */
{ blk_imp, MAN_BSCOPE }, /* P */
{ in_line_eoln, MAN_SCOPED | MAN_JOIN }, /* I */
{ in_line_eoln, 0 }, /* IR */
{ in_line_eoln, 0 }, /* RI */
- { in_line_eoln, MAN_NSCOPED }, /* sp */
{ in_line_eoln, MAN_NSCOPED }, /* nf */
{ in_line_eoln, MAN_NSCOPED }, /* fi */
{ blk_close, MAN_BSCOPE }, /* RE */
{ in_line_eoln, 0 }, /* UC */
{ in_line_eoln, MAN_NSCOPED }, /* PD */
{ in_line_eoln, 0 }, /* AT */
- { in_line_eoln, 0 }, /* in */
- { in_line_eoln, 0 }, /* ft */
+ { in_line_eoln, MAN_NSCOPED }, /* in */
+ { blk_imp, MAN_BSCOPE }, /* SY */
+ { blk_close, MAN_BSCOPE }, /* YS */
{ in_line_eoln, 0 }, /* OP */
{ in_line_eoln, MAN_BSCOPE }, /* EX */
{ in_line_eoln, MAN_BSCOPE }, /* EE */
{ blk_exp, MAN_BSCOPE }, /* UR */
{ blk_close, MAN_BSCOPE }, /* UE */
- { in_line_eoln, 0 }, /* ll */
+ { blk_exp, MAN_BSCOPE }, /* MT */
+ { blk_close, MAN_BSCOPE }, /* ME */
};
-const struct man_macro * const man_macros = __man_macros;
+const struct man_macro *
+man_macro(enum roff_tok tok)
+{
+ assert(tok >= MAN_TH && tok <= MAN_MAX);
+ return man_macros + (tok - MAN_TH);
+}
void
man_unscope(struct roff_man *man, const struct roff_node *to)
if (to == NULL && ! (n->flags & NODE_VALID)) {
if (man->flags & (MAN_BLINE | MAN_ELINE) &&
- man_macros[n->tok].flags & MAN_SCOPED) {
+ man_macro(n->tok)->flags & MAN_SCOPED) {
mandoc_vmsg(MANDOCERR_BLK_LINE,
man->parse, n->line, n->pos,
- "EOF breaks %s",
- man_macronames[n->tok]);
+ "EOF breaks %s", roff_name[n->tok]);
if (man->flags & MAN_ELINE)
man->flags &= ~MAN_ELINE;
else {
continue;
}
if (n->type == ROFFT_BLOCK &&
- man_macros[n->tok].fp == blk_exp)
+ man_macro(n->tok)->fp == blk_exp)
mandoc_msg(MANDOCERR_BLK_NOEND,
man->parse, n->line, n->pos,
- man_macronames[n->tok]);
+ roff_name[n->tok]);
}
/*
* scopes. When a scope is closed, it must be validated and actioned.
*/
static void
-rew_scope(struct roff_man *man, int tok)
+rew_scope(struct roff_man *man, enum roff_tok tok)
{
struct roff_node *n;
}
if (tok != MAN_SH && (n->tok == MAN_SH ||
(tok != MAN_SS && (n->tok == MAN_SS ||
- man_macros[n->tok].fp == blk_exp))))
+ man_macro(n->tok)->fp == blk_exp))))
return;
man_unscope(man, n);
n = man->last;
void
blk_close(MACRO_PROT_ARGS)
{
- int ntok;
+ enum roff_tok ctok, ntok;
const struct roff_node *nn;
char *p;
- int nrew, target;
+ int cline, cpos, nrew, target;
nrew = 1;
switch (tok) {
return;
}
break;
+ case MAN_YS:
+ ntok = MAN_SY;
+ break;
case MAN_UE:
ntok = MAN_UR;
break;
+ case MAN_ME:
+ ntok = MAN_MT;
+ break;
default:
abort();
}
if (nn == NULL) {
mandoc_msg(MANDOCERR_BLK_NOTOPEN, man->parse,
- line, ppos, man_macronames[tok]);
+ line, ppos, roff_name[tok]);
rew_scope(man, MAN_PP);
- } else {
- line = man->last->line;
- ppos = man->last->pos;
- ntok = man->last->tok;
- man_unscope(man, nn);
+ if (tok == MAN_RE) {
+ roff_elem_alloc(man, line, ppos, ROFF_br);
+ man->last->flags |= NODE_LINE |
+ NODE_VALID | NODE_ENDED;
+ man->next = ROFF_NEXT_SIBLING;
+ }
+ return;
+ }
- /* Move a trailing paragraph behind the block. */
+ cline = man->last->line;
+ cpos = man->last->pos;
+ ctok = man->last->tok;
+ man_unscope(man, nn);
- if (ntok == MAN_LP || ntok == MAN_PP || ntok == MAN_P) {
- *pos = strlen(buf);
- blk_imp(man, ntok, line, ppos, pos, buf);
- }
+ if (tok == MAN_RE && nn->head->aux > 0)
+ roff_setreg(man->roff, "an-margin", nn->head->aux, '-');
+
+ /* Trailing text. */
+
+ if (buf[*pos] != '\0') {
+ roff_word_alloc(man, line, ppos, buf + *pos);
+ man->last->flags |= NODE_DELIMC;
+ if (mandoc_eos(man->last->string, strlen(man->last->string)))
+ man->last->flags |= NODE_EOS;
+ }
+
+ /* Move a trailing paragraph behind the block. */
+
+ if (ctok == MAN_LP || ctok == MAN_PP || ctok == MAN_P) {
+ *pos = strlen(buf);
+ blk_imp(man, ctok, cline, cpos, pos, buf);
+ }
+
+ /* Synopsis blocks need an explicit end marker for spacing. */
+
+ if (tok == MAN_YS && man->last == nn) {
+ roff_elem_alloc(man, line, ppos, tok);
+ man_unscope(man, man->last);
}
}
char *p;
int la;
- rew_scope(man, tok);
+ if (tok == MAN_RS)
+ rew_scope(man, tok);
roff_block_alloc(man, line, ppos, tok);
head = roff_head_alloc(man, line, ppos, tok);
la = *pos;
- if (man_args(man, line, pos, buf, &p))
+ if (man_args(man, line, pos, buf, &p)) {
roff_word_alloc(man, line, la, p);
+ if (tok == MAN_RS) {
+ if (roff_getreg(man->roff, "an-margin") == 0)
+ roff_setreg(man->roff, "an-margin",
+ 7 * 24, '=');
+ if ((head->aux = strtod(p, NULL) * 24.0) > 0)
+ roff_setreg(man->roff, "an-margin",
+ head->aux, '+');
+ }
+ }
if (buf[*pos] != '\0')
- mandoc_vmsg(MANDOCERR_ARG_EXCESS,
- man->parse, line, *pos, "%s ... %s",
- man_macronames[tok], buf + *pos);
+ mandoc_vmsg(MANDOCERR_ARG_EXCESS, man->parse, line,
+ *pos, "%s ... %s", roff_name[tok], buf + *pos);
man_unscope(man, head);
roff_body_alloc(man, line, ppos, tok);
* For `TP', always keep the head open.
*/
- if (man_macros[tok].flags & MAN_SCOPED &&
- (tok == MAN_TP || n == man->last)) {
+ if (man_macro(tok)->flags & MAN_SCOPED &&
+ (tok == MAN_TP || tok == MAN_TQ || n == man->last)) {
man->flags |= MAN_BLINE;
return;
}
n = man->last;
for (;;) {
- if (buf[*pos] != '\0' && (tok == MAN_br ||
- tok == MAN_fi || tok == MAN_nf)) {
+ if (buf[*pos] != '\0' && (tok == MAN_fi || tok == MAN_nf)) {
mandoc_vmsg(MANDOCERR_ARG_SKIP,
man->parse, line, *pos, "%s %s",
- man_macronames[tok], buf + *pos);
+ roff_name[tok], buf + *pos);
break;
}
- if (buf[*pos] != '\0' && man->last != n &&
- (tok == MAN_PD || tok == MAN_ft || tok == MAN_sp)) {
+ if (buf[*pos] != '\0' && man->last != n && tok == MAN_PD) {
mandoc_vmsg(MANDOCERR_ARG_EXCESS,
man->parse, line, *pos, "%s ... %s",
- man_macronames[tok], buf + *pos);
+ roff_name[tok], buf + *pos);
break;
}
la = *pos;
if ( ! man_args(man, line, pos, buf, &p))
break;
- if (man_macros[tok].flags & MAN_JOIN &&
+ if (man_macro(tok)->flags & MAN_JOIN &&
man->last->type == ROFFT_TEXT)
roff_word_append(man, p);
else
* waiting for terms to load into our context.
*/
- if (n == man->last && man_macros[tok].flags & MAN_SCOPED) {
- assert( ! (man_macros[tok].flags & MAN_NSCOPED));
+ if (n == man->last && man_macro(tok)->flags & MAN_SCOPED) {
+ assert((man_macro(tok)->flags & MAN_NSCOPED) == 0);
man->flags |= MAN_ELINE;
return;
}