-/* $Id: man_macro.c,v 1.117 2017/05/04 17:48:28 schwarze Exp $ */
+/* $Id: man_macro.c,v 1.128 2018/08/18 02:08:27 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2012-2015, 2017 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
int *, char *, char **);
static void rew_scope(struct roff_man *, enum roff_tok);
-const struct man_macro __man_macros[MAN_MAX - MAN_TH] = {
+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_exp, 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 - MAN_TH;
+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", roff_name[n->tok]);
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,
roff_name[n->tok]);
}
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)
{
- enum roff_tok 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();
}
mandoc_msg(MANDOCERR_BLK_NOTOPEN, man->parse,
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);
+ 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;
+ }
+
+ /* 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);
}
}
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,
* 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;
}
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",
roff_name[tok], buf + *pos);
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;
}