-/* $Id: mdoc_term.c,v 1.28 2009/07/12 17:25:07 kristaps Exp $ */
+/* $Id: mdoc_term.c,v 1.59 2009/07/23 09:40:25 kristaps Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
*
#include "mdoc.h"
/* FIXME: macro arguments can be escaped. */
-/* FIXME: support more offset/width tokens. */
#define TTYPE_PROG 0
#define TTYPE_CMD_FLAG 1
#define TTYPE_LINK_ANCHOR 19
#define TTYPE_LINK_TEXT 20
#define TTYPE_REF_JOURNAL 21
-#define TTYPE_LIST 22
-#define TTYPE_NMAX 23
+#define TTYPE_REF_TITLE 22
+#define TTYPE_LIST 23
+#define TTYPE_NMAX 24
const int ttypes[TTYPE_NMAX] = {
TERMP_BOLD, /* TTYPE_PROG */
TERMP_UNDER, /* TTYPE_FUNC_ARG */
TERMP_UNDER, /* TTYPE_LINK */
TERMP_BOLD, /* TTYPE_SSECTION */
- TERMP_UNDER, /* TTYPE_FILE */
+ TERMP_UNDER, /* TTYPE_FILE */
TERMP_UNDER, /* TTYPE_EMPH */
TERMP_BOLD, /* TTYPE_CONFIG */
TERMP_BOLD, /* TTYPE_CMD */
TERMP_UNDER, /* TTYPE_LINK_ANCHOR */
TERMP_BOLD, /* TTYPE_LINK_TEXT */
TERMP_UNDER, /* TTYPE_REF_JOURNAL */
+ TERMP_UNDER, /* TTYPE_REF_TITLE */
TERMP_BOLD /* TTYPE_LIST */
};
-/*
- * This is used to preserve a style of value across a macro, instead of
- * losing it while the body is processed.
- */
struct termpair {
struct termpair *ppair;
- int flag; /* Whether being used. */
- size_t offset; /* Left margin. */
- size_t rmargin; /* Right margin. */
- int count; /* Enum count. */
+ int flag;
+ int count;
};
-#define DECL_ARGS \
- struct termp *p, struct termpair *pair, \
- const struct mdoc_meta *meta, \
- const struct mdoc_node *node
-
-#define DECL_PRE(name) \
-static int name##_pre(DECL_ARGS)
-#define DECL_POST(name) \
-static void name##_post(DECL_ARGS)
-#define DECL_PREPOST(name) \
-DECL_PRE(name); \
-DECL_POST(name);
-
-DECL_PREPOST(termp__t);
-DECL_PREPOST(termp_aq);
-DECL_PREPOST(termp_bd);
-DECL_PREPOST(termp_bq);
-DECL_PREPOST(termp_brq);
-DECL_PREPOST(termp_d1);
-DECL_PREPOST(termp_dq);
-DECL_PREPOST(termp_fd);
-DECL_PREPOST(termp_fn);
-DECL_PREPOST(termp_fo);
-DECL_PREPOST(termp_ft);
-DECL_PREPOST(termp_in);
-DECL_PREPOST(termp_it);
-DECL_PREPOST(termp_lb);
-DECL_PREPOST(termp_op);
-DECL_PREPOST(termp_pf);
-DECL_PREPOST(termp_pq);
-DECL_PREPOST(termp_qq);
-DECL_PREPOST(termp_sh);
-DECL_PREPOST(termp_ss);
-DECL_PREPOST(termp_sq);
-DECL_PREPOST(termp_vt);
-
-DECL_PRE(termp__j);
-DECL_PRE(termp_ap);
-DECL_PRE(termp_ar);
-DECL_PRE(termp_at);
-DECL_PRE(termp_bf);
-DECL_PRE(termp_bt);
-DECL_PRE(termp_cd);
-DECL_PRE(termp_cm);
-DECL_PRE(termp_em);
-DECL_PRE(termp_ex);
-DECL_PRE(termp_fa);
-DECL_PRE(termp_fl);
-DECL_PRE(termp_ic);
-DECL_PRE(termp_lk);
-DECL_PRE(termp_ms);
-DECL_PRE(termp_mt);
-DECL_PRE(termp_nd);
-DECL_PRE(termp_nm);
-DECL_PRE(termp_ns);
-DECL_PRE(termp_xx);
-DECL_PRE(termp_pa);
-DECL_PRE(termp_pp);
-DECL_PRE(termp_rs);
-DECL_PRE(termp_rv);
-DECL_PRE(termp_sm);
-DECL_PRE(termp_st);
-DECL_PRE(termp_sx);
-DECL_PRE(termp_sy);
-DECL_PRE(termp_ud);
-DECL_PRE(termp_va);
-DECL_PRE(termp_xr);
-
-DECL_POST(termp___);
-DECL_POST(termp_bl);
-DECL_POST(termp_bx);
+#define DECL_ARGS struct termp *p, \
+ struct termpair *pair, \
+ const struct mdoc_meta *meta, \
+ const struct mdoc_node *node
struct termact {
int (*pre)(DECL_ARGS);
void (*post)(DECL_ARGS);
};
+static void termp____post(DECL_ARGS);
+static void termp_aq_post(DECL_ARGS);
+static void termp_bd_post(DECL_ARGS);
+static void termp_bl_post(DECL_ARGS);
+static void termp_bq_post(DECL_ARGS);
+static void termp_brq_post(DECL_ARGS);
+static void termp_bx_post(DECL_ARGS);
+static void termp_d1_post(DECL_ARGS);
+static void termp_dq_post(DECL_ARGS);
+static void termp_fd_post(DECL_ARGS);
+static void termp_fn_post(DECL_ARGS);
+static void termp_fo_post(DECL_ARGS);
+static void termp_ft_post(DECL_ARGS);
+static void termp_in_post(DECL_ARGS);
+static void termp_it_post(DECL_ARGS);
+static void termp_lb_post(DECL_ARGS);
+static void termp_op_post(DECL_ARGS);
+static void termp_pf_post(DECL_ARGS);
+static void termp_pq_post(DECL_ARGS);
+static void termp_qq_post(DECL_ARGS);
+static void termp_sh_post(DECL_ARGS);
+static void termp_sq_post(DECL_ARGS);
+static void termp_ss_post(DECL_ARGS);
+static void termp_vt_post(DECL_ARGS);
+
+static int termp__j_pre(DECL_ARGS);
+static int termp__t_pre(DECL_ARGS);
+static int termp_ap_pre(DECL_ARGS);
+static int termp_aq_pre(DECL_ARGS);
+static int termp_ar_pre(DECL_ARGS);
+static int termp_bd_pre(DECL_ARGS);
+static int termp_bf_pre(DECL_ARGS);
+static int termp_bq_pre(DECL_ARGS);
+static int termp_br_pre(DECL_ARGS);
+static int termp_brq_pre(DECL_ARGS);
+static int termp_bt_pre(DECL_ARGS);
+static int termp_cd_pre(DECL_ARGS);
+static int termp_cm_pre(DECL_ARGS);
+static int termp_d1_pre(DECL_ARGS);
+static int termp_dq_pre(DECL_ARGS);
+static int termp_em_pre(DECL_ARGS);
+static int termp_ex_pre(DECL_ARGS);
+static int termp_fa_pre(DECL_ARGS);
+static int termp_fd_pre(DECL_ARGS);
+static int termp_fl_pre(DECL_ARGS);
+static int termp_fn_pre(DECL_ARGS);
+static int termp_fo_pre(DECL_ARGS);
+static int termp_ft_pre(DECL_ARGS);
+static int termp_ic_pre(DECL_ARGS);
+static int termp_in_pre(DECL_ARGS);
+static int termp_it_pre(DECL_ARGS);
+static int termp_lk_pre(DECL_ARGS);
+static int termp_ms_pre(DECL_ARGS);
+static int termp_mt_pre(DECL_ARGS);
+static int termp_nd_pre(DECL_ARGS);
+static int termp_nm_pre(DECL_ARGS);
+static int termp_ns_pre(DECL_ARGS);
+static int termp_op_pre(DECL_ARGS);
+static int termp_pa_pre(DECL_ARGS);
+static int termp_pf_pre(DECL_ARGS);
+static int termp_pp_pre(DECL_ARGS);
+static int termp_pq_pre(DECL_ARGS);
+static int termp_qq_pre(DECL_ARGS);
+static int termp_rs_pre(DECL_ARGS);
+static int termp_rv_pre(DECL_ARGS);
+static int termp_sh_pre(DECL_ARGS);
+static int termp_sm_pre(DECL_ARGS);
+static int termp_sp_pre(DECL_ARGS);
+static int termp_sq_pre(DECL_ARGS);
+static int termp_ss_pre(DECL_ARGS);
+static int termp_sx_pre(DECL_ARGS);
+static int termp_sy_pre(DECL_ARGS);
+static int termp_ud_pre(DECL_ARGS);
+static int termp_va_pre(DECL_ARGS);
+static int termp_vt_pre(DECL_ARGS);
+static int termp_xr_pre(DECL_ARGS);
+static int termp_xx_pre(DECL_ARGS);
+
static const struct termact termacts[MDOC_MAX] = {
{ termp_ap_pre, NULL }, /* Ap */
{ NULL, NULL }, /* Dd */
{ NULL, NULL }, /* Ot */
{ termp_pa_pre, NULL }, /* Pa */
{ termp_rv_pre, NULL }, /* Rv */
- { termp_st_pre, NULL }, /* St */
+ { NULL, NULL }, /* St */
{ termp_va_pre, NULL }, /* Va */
{ termp_vt_pre, termp_vt_post }, /* Vt */
{ termp_xr_pre, NULL }, /* Xr */
{ NULL, termp____post }, /* %O */
{ NULL, termp____post }, /* %P */
{ NULL, termp____post }, /* %R */
- { termp__t_pre, termp__t_post }, /* %T */
+ { termp__t_pre, termp____post }, /* %T */
{ NULL, termp____post }, /* %V */
{ NULL, NULL }, /* Ac */
{ termp_aq_pre, termp_aq_post }, /* Ao */
{ termp_aq_pre, termp_aq_post }, /* Aq */
- { termp_at_pre, NULL }, /* At */
+ { NULL, NULL }, /* At */
{ NULL, NULL }, /* Bc */
{ termp_bf_pre, NULL }, /* Bf */
{ termp_bq_pre, termp_bq_post }, /* Bo */
{ NULL, NULL }, /* Hf */
{ NULL, NULL }, /* Fr */
{ termp_ud_pre, NULL }, /* Ud */
- { termp_lb_pre, termp_lb_post }, /* Lb */
+ { NULL, termp_lb_post }, /* Lb */
{ termp_pp_pre, NULL }, /* Lp */
{ termp_lk_pre, NULL }, /* Lk */
{ termp_mt_pre, NULL }, /* Mt */
{ NULL, NULL }, /* En */
{ termp_xx_pre, NULL }, /* Dx */
{ NULL, NULL }, /* %Q */
+ { termp_br_pre, NULL }, /* br */
+ { termp_sp_pre, NULL }, /* sp */
};
#ifdef __linux__
static size_t arg_offset(const struct mdoc_argv *);
static size_t arg_width(const struct mdoc_argv *, int);
static int arg_listtype(const struct mdoc_node *);
-static int fmt_block_vspace(struct termp *,
+static void fmt_block_vspace(struct termp *,
const struct mdoc_node *,
const struct mdoc_node *);
static void print_node(DECL_ARGS);
* Main output function. When this is called, assume that the
* tree is properly formed.
*/
-
print_head(p, mdoc_meta(m));
assert(mdoc_node(m));
assert(MDOC_ROOT == mdoc_node(m)->type);
{
int dochild;
struct termpair npair;
-
- /* Pre-processing. */
+ size_t offset, rmargin;
dochild = 1;
+ offset = p->offset;
+ rmargin = p->rmargin;
+
npair.ppair = pair;
- npair.offset = npair.rmargin = 0;
npair.flag = 0;
npair.count = 0;
+ /*
+ * Note on termpair. This allows a pre function to set a termp
+ * flag that is automatically unset after the body, but before
+ * the post function. Thus, if a pre uses a termpair flag, it
+ * must be reapplied in the post for use.
+ */
+
if (MDOC_TEXT != node->type) {
if (termacts[node->tok].pre)
if ( ! (*termacts[node->tok].pre)(p, &npair, meta, node))
if (MDOC_TEXT != node->type)
if (termacts[node->tok].post)
(*termacts[node->tok].post)(p, &npair, meta, node);
+
+ p->offset = offset;
+ p->rmargin = rmargin;
}
tm = localtime(&meta->date);
- if (0 == strftime(buf, p->rmargin, "%B %d, %Y", tm))
+ if (0 == strftime(buf, p->rmargin, "%B %e, %Y", tm))
err(1, "strftime");
(void)strlcpy(os, meta->os, p->rmargin);
static size_t
arg_width(const struct mdoc_argv *arg, int pos)
{
- size_t v;
int i, len;
+ const char *p;
assert(pos < (int)arg->sz && pos >= 0);
assert(arg->value[pos]);
- if (0 == (len = (int)strlen(arg->value[pos])))
+ p = arg->value[pos];
+
+ if (0 == (len = (int)strlen(p)))
return(0);
for (i = 0; i < len - 1; i++)
- if ( ! isdigit((u_char)arg->value[pos][i]))
+ if ( ! isdigit((u_char)p[i]))
break;
- if (i == len - 1) {
- if ('n' == arg->value[pos][len - 1] ||
- 'm' == arg->value[pos][len - 1]) {
- v = (size_t)atoi(arg->value[pos]);
- return(v + 2);
- }
+ if (i == len - 1)
+ if ('n' == p[len - 1] || 'm' == p[len - 1])
+ return((size_t)atoi(p) + 2);
- }
- return(strlen(arg->value[pos]) + 2);
+ return((size_t)len + 2);
}
/* FALLTHROUGH */
case (MDOC_Column):
/* FALLTHROUGH */
+ case (MDOC_Hang):
+ /* FALLTHROUGH */
case (MDOC_Ohang):
return(n->args->argv[i].arg);
default:
break;
}
- /* FIXME: mandated by parser. */
-
- errx(1, "list type not supported");
- /* NOTREACHED */
+ return(-1);
}
static size_t
arg_offset(const struct mdoc_argv *arg)
{
+ int len, i;
+ const char *p;
assert(*arg->value);
- if (0 == strcmp(*arg->value, "left"))
+ p = *arg->value;
+
+ if (0 == strcmp(p, "left"))
return(0);
- if (0 == strcmp(*arg->value, "indent"))
+ if (0 == strcmp(p, "indent"))
return(INDENT + 1);
- if (0 == strcmp(*arg->value, "indent-two"))
+ if (0 == strcmp(p, "indent-two"))
return((INDENT + 1) * 2);
- /* FIXME: needs to support field-widths (10n, etc.). */
+ if (0 == (len = (int)strlen(p)))
+ return(0);
- return(strlen(*arg->value));
+ for (i = 0; i < len - 1; i++)
+ if ( ! isdigit((u_char)p[i]))
+ break;
+
+ if (i == len - 1)
+ if ('n' == p[len - 1] || 'm' == p[len - 1])
+ return((size_t)atoi(p));
+
+ return((size_t)len);
}
/* ARGSUSED */
-static int
+static void
fmt_block_vspace(struct termp *p,
const struct mdoc_node *bl,
const struct mdoc_node *node)
term_newln(p);
- if (arg_hasattr(MDOC_Compact, bl))
- return(1);
+ if (MDOC_Bl == bl->tok && arg_hasattr(MDOC_Compact, bl))
+ return;
+
+ /*
+ * Search through our prior nodes. If we follow a `Ss' or `Sh',
+ * then don't vspace.
+ */
for (n = node; n; n = n->parent) {
if (MDOC_BLOCK != n->type)
continue;
if (MDOC_Ss == n->tok)
- break;
+ return;
if (MDOC_Sh == n->tok)
- break;
+ return;
if (NULL == n->prev)
continue;
- term_vspace(p);
break;
}
- return(1);
+ /*
+ * XXX - not documented: a `-column' does not ever assert vspace
+ * within the list.
+ */
+
+ if (MDOC_Bl == bl->tok && arg_hasattr(MDOC_Column, bl))
+ if (node->prev && MDOC_It == node->prev->tok)
+ return;
+
+ /*
+ * XXX - not documented: a `-diag' without a body does not
+ * assert a vspace prior to the next element.
+ */
+ if (MDOC_Bl == bl->tok && arg_hasattr(MDOC_Diag, bl))
+ if (node->prev && MDOC_It == node->prev->tok) {
+ assert(node->prev->body);
+ if (NULL == node->prev->body->child)
+ return;
+ }
+
+ term_vspace(p);
}
{
const struct mdoc_node *bl, *n;
char buf[7];
- int i, type, keys[3], vals[3], sv;
+ int i, type, keys[3], vals[3];
size_t width, offset;
- if (MDOC_BLOCK == node->type)
- return(fmt_block_vspace(p, node->parent->parent, node));
+ if (MDOC_BLOCK == node->type) {
+ fmt_block_vspace(p, node->parent->parent, node);
+ return(1);
+ }
bl = node->parent->parent->parent;
/* Save parent attributes. */
- pair->offset = p->offset;
- pair->rmargin = p->rmargin;
pair->flag = p->flags;
/* Get list width and offset. */
(void)arg_getattrs(keys, vals, 3, bl);
type = arg_listtype(bl);
+ assert(-1 != type);
/* Calculate real width and offset. */
case (MDOC_Column):
if (MDOC_BODY == node->type)
break;
- for (i = 0, n = node->prev; n; n = n->prev, i++)
+ /*
+ * Work around groff's column handling. The offset is
+ * equal to the sum of all widths leading to the current
+ * column (plus the -offset value). If this column
+ * exceeds the stated number of columns, the width is
+ * set as 0, else it's the stated column width (later
+ * the 0 will be adjusted to default 10 or, if in the
+ * last column case, set to stretch to the margin).
+ */
+ for (i = 0, n = node->prev; n && n &&
+ i < (int)bl->args[vals[2]].argv->sz;
+ n = n->prev, i++)
offset += arg_width
(&bl->args->argv[vals[2]], i);
- assert(i < (int)bl->args->argv[vals[2]].sz);
- width = arg_width(&bl->args->argv[vals[2]], i);
+
+ /* Whether exceeds maximum column. */
+ if (i < (int)bl->args[vals[2]].argv->sz)
+ width = arg_width(&bl->args->argv[vals[2]], i);
+ else
+ width = 0;
+
if (vals[1] >= 0)
offset += arg_offset(&bl->args->argv[vals[1]]);
break;
/*
* List-type can override the width in the case of fixed-head
* values (bullet, dash/hyphen, enum). Tags need a non-zero
- * offset.
+ * offset. FIXME: double-check that correct.
*/
switch (type) {
if (width < 5)
width = 5;
break;
+ case (MDOC_Hang):
+ if (0 == width)
+ width = 8;
+ break;
+ case (MDOC_Column):
+ /* FALLTHROUGH */
case (MDOC_Tag):
if (0 == width)
width = 10;
* while diagonal bodies need two.
*/
+ p->flags |= TERMP_NOSPACE;
+
switch (type) {
case (MDOC_Diag):
- term_word(p, "\\ ");
- /* FALLTHROUGH */
+ term_word(p, "\\ \\ ");
+ break;
case (MDOC_Inset):
if (MDOC_BODY == node->type)
- p->flags &= ~TERMP_NOSPACE;
- else
- p->flags |= TERMP_NOSPACE;
+ term_word(p, "\\ ");
break;
default:
- p->flags |= TERMP_NOSPACE;
break;
}
+ p->flags |= TERMP_NOSPACE;
+
/*
* Style flags. Diagnostic heads need TTYPE_DIAG.
*/
case (MDOC_Enum):
/* FALLTHROUGH */
case (MDOC_Hyphen):
- /* FALLTHROUGH */
- case (MDOC_Tag):
if (MDOC_HEAD == node->type)
p->flags |= TERMP_NOBREAK;
else
p->flags |= TERMP_NOLPAD;
- if (MDOC_HEAD == node->type && MDOC_Tag == type)
- if (NULL == node->next ||
- NULL == node->next->child)
- p->flags |= TERMP_NONOBREAK;
+ break;
+ case (MDOC_Hang):
+ if (MDOC_HEAD == node->type)
+ p->flags |= TERMP_NOBREAK;
+ else
+ p->flags |= TERMP_NOLPAD;
+
+ if (MDOC_HEAD != node->type)
+ break;
+
+ /*
+ * This is ugly. If `-hang' is specified and the body
+ * is a `Bl' or `Bd', then we want basically to nullify
+ * the "overstep" effect in term_flushln() and treat
+ * this as a `-ohang' list instead.
+ */
+ if (node->next->child &&
+ (MDOC_Bl == node->next->child->tok ||
+ MDOC_Bd == node->next->child->tok)) {
+ p->flags &= ~TERMP_NOBREAK;
+ p->flags &= ~TERMP_NOLPAD;
+ } else
+ p->flags |= TERMP_HANG;
+ break;
+ case (MDOC_Tag):
+ if (MDOC_HEAD == node->type)
+ p->flags |= TERMP_NOBREAK | TERMP_TWOSPACE;
+ else
+ p->flags |= TERMP_NOLPAD;
+
+ if (MDOC_HEAD != node->type)
+ break;
+ if (NULL == node->next || NULL == node->next->child)
+ p->flags |= TERMP_DANGLE;
break;
case (MDOC_Column):
if (MDOC_HEAD == node->type) {
p->offset += offset;
switch (type) {
+ case (MDOC_Hang):
+ /*
+ * Same stipulation as above, regarding `-hang'. We
+ * don't want to recalculate rmargin and offsets when
+ * using `Bd' or `Bl' within `-hang' overstep lists.
+ */
+ if (MDOC_HEAD == node->type && node->next->child &&
+ (MDOC_Bl == node->next->child->tok ||
+ MDOC_Bd == node->next->child->tok))
+ break;
+ /* FALLTHROUGH */
case (MDOC_Bullet):
/* FALLTHROUGH */
case (MDOC_Dash):
case (MDOC_Hyphen):
/* FALLTHROUGH */
case (MDOC_Tag):
+ assert(width);
if (MDOC_HEAD == node->type)
p->rmargin = p->offset + width;
else
p->offset += width;
break;
case (MDOC_Column):
+ assert(width);
p->rmargin = p->offset + width;
+ /*
+ * XXX - this behaviour is not documented: the
+ * right-most column is filled to the right margin.
+ */
+ if (MDOC_HEAD == node->type &&
+ MDOC_BODY == node->next->type)
+ p->rmargin = p->maxrmargin;
break;
default:
break;
* HEAD character (temporarily bold, in some cases).
*/
- sv = p->flags;
if (MDOC_HEAD == node->type)
switch (type) {
case (MDOC_Bullet):
p->flags |= TERMP_BOLD;
term_word(p, "\\[bu]");
+ p->flags &= ~TERMP_BOLD;
break;
case (MDOC_Dash):
/* FALLTHROUGH */
case (MDOC_Hyphen):
p->flags |= TERMP_BOLD;
term_word(p, "\\(hy");
+ p->flags &= ~TERMP_BOLD;
break;
case (MDOC_Enum):
(pair->ppair->ppair->count)++;
break;
}
- p->flags = sv; /* Restore saved flags. */
-
/*
* If we're not going to process our children, indicate so here.
*/
return;
type = arg_listtype(node->parent->parent->parent);
+ assert(-1 != type);
switch (type) {
- case (MDOC_Diag):
- /* FALLTHROUGH */
case (MDOC_Item):
/* FALLTHROUGH */
+ case (MDOC_Diag):
+ /* FALLTHROUGH */
case (MDOC_Inset):
if (MDOC_BODY == node->type)
term_flushln(p);
break;
}
- p->offset = pair->offset;
- p->rmargin = pair->rmargin;
p->flags = pair->flag;
}
}
-/* ARGSUSED */
-static int
-termp_st_pre(DECL_ARGS)
-{
- const char *cp;
-
- if (node->child && (cp = mdoc_a2st(node->child->string)))
- term_word(p, cp);
- return(0);
-}
-
-
/* ARGSUSED */
static int
termp_rs_pre(DECL_ARGS)
{
int i;
- /* FIXME: mandated by parser. */
-
- if (-1 == (i = arg_getattr(MDOC_Std, node)))
- errx(1, "expected -std argument");
- if (1 != node->args->argv[i].sz)
- errx(1, "expected -std argument");
+ i = arg_getattr(MDOC_Std, node);
+ assert(-1 != i);
+ assert(node->args->argv[i].sz);
term_newln(p);
term_word(p, "The");
{
int i;
- /* FIXME: mandated by parser? */
-
- if (-1 == (i = arg_getattr(MDOC_Std, node)))
- errx(1, "expected -std argument");
- if (1 != node->args->argv[i].sz)
- errx(1, "expected -std argument");
+ i = arg_getattr(MDOC_Std, node);
+ assert(-1 != i);
+ assert(node->args->argv[i].sz);
term_word(p, "The");
p->flags |= ttypes[TTYPE_PROG];
if (MDOC_BODY != node->type)
return(1);
- /*
- * XXX: signed off by jmc@openbsd.org. This technically
- * produces a minus sign after the Nd, which is wrong, but is
- * consistent with the historic OpenBSD tmac file.
- */
+
#if defined(__OpenBSD__) || defined(__linux__)
- term_word(p, "\\-");
+ term_word(p, "\\(en");
#else
term_word(p, "\\(em");
#endif
{
/* FIXME: this can be "type name". */
- pair->flag |= TTYPE_VAR_DECL;
+ pair->flag |= ttypes[TTYPE_VAR_DECL];
return(1);
}
termp_vt_post(DECL_ARGS)
{
- if (node->sec == SEC_SYNOPSIS)
+ if (node->sec != SEC_SYNOPSIS)
+ return;
+ if (node->next && MDOC_Vt == node->next->tok)
+ term_newln(p);
+ else if (node->next)
term_vspace(p);
}
termp_fd_pre(DECL_ARGS)
{
- pair->flag |= TTYPE_FUNC_DECL;
+ pair->flag |= ttypes[TTYPE_FUNC_DECL];
return(1);
}
if (node->sec != SEC_SYNOPSIS)
return;
+
term_newln(p);
if (node->next && MDOC_Fd != node->next->tok)
term_vspace(p);
}
-/* ARGSUSED */
-static int
-termp_lb_pre(DECL_ARGS)
-{
- const char *lb;
-
- assert(node->child && MDOC_TEXT == node->child->type);
- lb = mdoc_a2lib(node->child->string);
- if (lb) {
- term_word(p, lb);
- return(0);
- }
- term_word(p, "library");
- return(1);
-}
-
-
/* ARGSUSED */
static void
termp_lb_post(DECL_ARGS)
if (MDOC_BLOCK != node->type)
return(1);
term_newln(p);
- pair->offset = INDENT + 1;
- p->offset += pair->offset;
+ p->offset += (INDENT + 1);
return(1);
}
if (MDOC_BLOCK != node->type)
return;
term_newln(p);
- p->offset -= pair->offset;
}
* line. Blank lines are allowed.
*/
- if (MDOC_BLOCK == node->type)
- return(fmt_block_vspace(p, node, node));
- else if (MDOC_BODY != node->type)
+ if (MDOC_BLOCK == node->type) {
+ fmt_block_vspace(p, node, node);
+ return(1);
+ } else if (MDOC_BODY != node->type)
return(1);
/* FIXME: display type should be mandated by parser. */
if (NULL == node->parent->args)
errx(1, "missing display type");
- pair->offset = p->offset;
-
for (type = -1, i = 0;
i < (int)node->parent->args->argc; i++) {
switch (node->parent->args->argv[i].arg) {
* Ew.
*/
- p->flags |= TERMP_LITERAL;
ln = node->child ? node->child->line : 0;
for (node = node->child; node; node = node->next) {
if (MDOC_BODY != node->type)
return;
-
term_flushln(p);
- p->flags &= ~TERMP_LITERAL;
- p->offset = pair->offset;
- p->flags |= TERMP_NOSPACE;
}
}
+/* ARGSUSED */
+static int
+termp_pa_pre(DECL_ARGS)
+{
+
+ pair->flag |= ttypes[TTYPE_FILE];
+ return(1);
+}
+
+
/* ARGSUSED */
static int
termp_pf_pre(DECL_ARGS)
termp_ss_post(DECL_ARGS)
{
- switch (node->type) {
- case (MDOC_HEAD):
+ if (MDOC_HEAD == node->type)
term_newln(p);
- p->offset = INDENT;
- break;
- default:
- break;
- }
-}
-
-
-/* ARGSUSED */
-static int
-termp_pa_pre(DECL_ARGS)
-{
-
- pair->flag |= ttypes[TTYPE_FILE];
- return(1);
}
termp_in_post(DECL_ARGS)
{
- p->flags |= TERMP_NOSPACE;
+ p->flags |= TERMP_NOSPACE | ttypes[TTYPE_INCLUDE];
term_word(p, ">");
+ p->flags &= ~ttypes[TTYPE_INCLUDE];
if (SEC_SYNOPSIS != node->sec)
return;
/* ARGSUSED */
static int
-termp_at_pre(DECL_ARGS)
+termp_sp_pre(DECL_ARGS)
{
- const char *att;
+ int i, len;
- att = NULL;
+ if (NULL == node->child) {
+ term_vspace(p);
+ return(0);
+ }
- if (node->child)
- att = mdoc_a2att(node->child->string);
- if (NULL == att)
- att = "AT&T UNIX";
+ len = atoi(node->child->string);
+ if (0 == len)
+ term_newln(p);
+ for (i = 0; i < len; i++)
+ term_vspace(p);
- term_word(p, att);
return(0);
}
+/* ARGSUSED */
+static int
+termp_br_pre(DECL_ARGS)
+{
+
+ term_newln(p);
+ return(1);
+}
+
+
/* ARGSUSED */
static int
termp_brq_pre(DECL_ARGS)
const struct mdoc_node *n;
if (MDOC_BODY == node->type) {
+ p->flags |= TERMP_NOSPACE;
term_word(p, "(");
p->flags |= TERMP_NOSPACE;
return(1);
} else if (MDOC_HEAD != node->type)
return(1);
- /* XXX - groff shows only first parameter */
-
p->flags |= ttypes[TTYPE_FUNC_NAME];
for (n = node->child; n; n = n->next) {
assert(MDOC_TEXT == n->type);
termp__t_pre(DECL_ARGS)
{
- term_word(p, "\"");
- p->flags |= TERMP_NOSPACE;
+ pair->flag |= ttypes[TTYPE_REF_TITLE];
return(1);
}
-/* ARGSUSED */
-static void
-termp__t_post(DECL_ARGS)
-{
-
- p->flags |= TERMP_NOSPACE;
- term_word(p, "\"");
- termp____post(p, pair, meta, node);
-}
-
-
/* ARGSUSED */
static void
termp____post(DECL_ARGS)