summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2014-11-17 06:44:58 +0000
committerIngo Schwarze <schwarze@openbsd.org>2014-11-17 06:44:58 +0000
commita6c982532bfd28e9dee86e99b8f6c5102300c294 (patch)
tree703a57e3dc6da961266a29fd02e142916fb8b756
parent4fab3c6e074ed129fedec660b155817a528496d3 (diff)
downloadmandoc-a6c982532bfd28e9dee86e99b8f6c5102300c294.tar.gz
Multiple fixes with respect to in-line macros:
* .No selects the default font; relevant e.g. in .Bf blocks * no need to force empty .Li elements * closing delimiters as leading macro arguments do not suppress space * opening delimiters at the end of a macro line do not suppress space * correctly handle delimiter spacing in -Tman As a side effect, these fixes let mandoc warn about empty .No macros as requested by bentley@.
-rw-r--r--libmdoc.h3
-rw-r--r--mdoc_html.c13
-rw-r--r--mdoc_macro.c74
-rw-r--r--mdoc_man.c4
-rw-r--r--mdoc_term.c2
-rw-r--r--mdoc_validate.c20
6 files changed, 84 insertions, 32 deletions
diff --git a/libmdoc.h b/libmdoc.h
index f0e5b961..c7a67705 100644
--- a/libmdoc.h
+++ b/libmdoc.h
@@ -1,7 +1,7 @@
/* $Id$ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2013 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -37,6 +37,7 @@ struct mdoc {
#define MDOC_SYNOPSIS (1 << 7) /* SYNOPSIS-style formatting */
#define MDOC_KEEP (1 << 8) /* in a word keep */
#define MDOC_SMOFF (1 << 9) /* spacing is off */
+#define MDOC_NODELIMC (1 << 10) /* disable closing delimiter handling */
enum mdoc_next next; /* where to put the next node */
struct mdoc_node *last; /* the last node parsed */
struct mdoc_node *first; /* the first node parsed */
diff --git a/mdoc_html.c b/mdoc_html.c
index 04d3883e..c64d38c4 100644
--- a/mdoc_html.c
+++ b/mdoc_html.c
@@ -98,6 +98,7 @@ static int mdoc_mt_pre(MDOC_ARGS);
static int mdoc_ms_pre(MDOC_ARGS);
static int mdoc_nd_pre(MDOC_ARGS);
static int mdoc_nm_pre(MDOC_ARGS);
+static int mdoc_no_pre(MDOC_ARGS);
static int mdoc_ns_pre(MDOC_ARGS);
static int mdoc_pa_pre(MDOC_ARGS);
static void mdoc_pf_post(MDOC_ARGS);
@@ -192,7 +193,7 @@ static const struct htmlmdoc mdocs[MDOC_MAX] = {
{mdoc_quote_pre, mdoc_quote_post}, /* Eo */
{mdoc_xx_pre, NULL}, /* Fx */
{mdoc_ms_pre, NULL}, /* Ms */
- {mdoc_igndelim_pre, NULL}, /* No */
+ {mdoc_no_pre, NULL}, /* No */
{mdoc_ns_pre, NULL}, /* Ns */
{mdoc_xx_pre, NULL}, /* Nx */
{mdoc_xx_pre, NULL}, /* Ox */
@@ -1884,6 +1885,16 @@ mdoc_rs_pre(MDOC_ARGS)
}
static int
+mdoc_no_pre(MDOC_ARGS)
+{
+ struct htmlpair tag;
+
+ PAIR_CLASS_INIT(&tag, "none");
+ print_otag(h, TAG_CODE, 1, &tag);
+ return(1);
+}
+
+static int
mdoc_li_pre(MDOC_ARGS)
{
struct htmlpair tag;
diff --git a/mdoc_macro.c b/mdoc_macro.c
index 183d0c73..16c99abb 100644
--- a/mdoc_macro.c
+++ b/mdoc_macro.c
@@ -147,8 +147,7 @@ const struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */
{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */
{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ms */
- { in_line_argn, MDOC_CALLABLE | MDOC_PARSED |
- MDOC_IGNDELIM | MDOC_JOIN }, /* No */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* No */
{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED |
MDOC_IGNDELIM | MDOC_JOIN }, /* Ns */
{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */
@@ -627,24 +626,22 @@ dword(struct mdoc *mdoc, int line, int col, const char *p,
if ( ! mdoc_word_alloc(mdoc, line, col, p))
return(0);
- if (DELIM_OPEN == d)
- mdoc->last->flags |= MDOC_DELIMO;
-
/*
- * Closing delimiters only suppress the preceding space
- * when they follow something, not when they start a new
- * block or element, and not when they follow `No'.
- *
- * XXX Explicitly special-casing MDOC_No here feels
- * like a layering violation. Find a better way
- * and solve this in the code related to `No'!
+ * If the word consists of a bare delimiter,
+ * flag the new node accordingly,
+ * unless doing so was vetoed by the invoking macro.
+ * Always clear the veto, it is only valid for one word.
*/
- else if (DELIM_CLOSE == d && mdoc->last->prev &&
- mdoc->last->prev->tok != MDOC_No &&
+ if (d == DELIM_OPEN)
+ mdoc->last->flags |= MDOC_DELIMO;
+ else if (d == DELIM_CLOSE &&
+ ! (mdoc->flags & MDOC_NODELIMC) &&
mdoc->last->parent->tok != MDOC_Fd)
mdoc->last->flags |= MDOC_DELIMC;
+ mdoc->flags &= ~MDOC_NODELIMC;
+
return(1);
}
@@ -843,7 +840,7 @@ blk_exp_close(MACRO_PROT_ARGS)
static int
in_line(MACRO_PROT_ARGS)
{
- int la, scope, cnt, mayopen, nc, nl;
+ int la, scope, cnt, firstarg, mayopen, nc, nl;
enum margverr av;
enum mdoct ntok;
enum margserr ac;
@@ -894,17 +891,40 @@ in_line(MACRO_PROT_ARGS)
return(0);
}
+ d = DELIM_NONE;
+ firstarg = 1;
mayopen = 1;
for (cnt = scope = 0;; ) {
la = *pos;
ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
- if (ARGS_ERROR == ac)
+ if (ac == ARGS_ERROR)
return(0);
- if (ARGS_EOLN == ac)
+
+ /*
+ * At the end of a macro line,
+ * opening delimiters do not suppress spacing.
+ */
+
+ if (ac == ARGS_EOLN) {
+ if (d == DELIM_OPEN)
+ mdoc->last->flags &= ~MDOC_DELIMO;
break;
- if (ARGS_PUNCT == ac)
+ }
+
+ /*
+ * The rest of the macro line is only punctuation,
+ * to be handled by append_delims().
+ * If there were no other arguments,
+ * do not allow the first one to suppress spacing,
+ * even if it turns out to be a closing one.
+ */
+
+ if (ac == ARGS_PUNCT) {
+ if (cnt == 0 && nc == 0)
+ mdoc->flags |= MDOC_NODELIMC;
break;
+ }
ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
@@ -949,20 +969,19 @@ in_line(MACRO_PROT_ARGS)
if (DELIM_NONE != d) {
/*
* If we encounter closing punctuation, no word
- * has been omitted, no scope is open, and we're
+ * has been emitted, no scope is open, and we're
* allowed to have an empty element, then start
* a new scope.
*/
if ((d == DELIM_CLOSE ||
(d == DELIM_MIDDLE && tok == MDOC_Fl)) &&
- (nc || tok == MDOC_Li) &&
- !scope && !cnt && mayopen) {
+ !cnt && !scope && nc && mayopen) {
if ( ! mdoc_elem_alloc(mdoc,
line, ppos, tok, arg))
return(0);
scope = 1;
cnt++;
- if (MDOC_Li == tok || MDOC_Nm == tok)
+ if (MDOC_Nm == tok)
mayopen = 0;
}
/*
@@ -984,6 +1003,15 @@ in_line(MACRO_PROT_ARGS)
return(0);
/*
+ * If the first argument is a closing delimiter,
+ * do not suppress spacing before it.
+ */
+
+ if (firstarg && d == DELIM_CLOSE && !nc)
+ mdoc->last->flags &= ~MDOC_DELIMC;
+ firstarg = 0;
+
+ /*
* `Fl' macros have their scope re-opened with each new
* word so that the `-' can be added to each one without
* having to parse out spaces.
@@ -1533,8 +1561,6 @@ in_line_argn(MACRO_PROT_ARGS)
switch (tok) {
case MDOC_Ap:
/* FALLTHROUGH */
- case MDOC_No:
- /* FALLTHROUGH */
case MDOC_Ns:
/* FALLTHROUGH */
case MDOC_Ux:
diff --git a/mdoc_man.c b/mdoc_man.c
index 234b9929..e5d062c9 100644
--- a/mdoc_man.c
+++ b/mdoc_man.c
@@ -594,7 +594,11 @@ print_node(DECL_ARGS)
printf("\\&");
outflags &= ~MMAN_spc;
}
+ if (outflags & MMAN_Sm && ! (n->flags & MDOC_DELIMC))
+ outflags |= MMAN_spc_force;
print_word(n->string);
+ if (outflags & MMAN_Sm && ! (n->flags & MDOC_DELIMO))
+ outflags |= MMAN_spc;
} else {
/*
* Conditionally run the pre-node action handler for a
diff --git a/mdoc_term.c b/mdoc_term.c
index c115e0eb..e513ad19 100644
--- a/mdoc_term.c
+++ b/mdoc_term.c
@@ -193,7 +193,7 @@ static const struct termact termacts[MDOC_MAX] = {
{ termp_quote_pre, termp_quote_post }, /* Eo */
{ termp_xx_pre, NULL }, /* Fx */
{ termp_bold_pre, NULL }, /* Ms */
- { NULL, NULL }, /* No */
+ { termp_li_pre, NULL }, /* No */
{ termp_ns_pre, NULL }, /* Ns */
{ termp_xx_pre, NULL }, /* Nx */
{ termp_xx_pre, NULL }, /* Ox */
diff --git a/mdoc_validate.c b/mdoc_validate.c
index 977bf073..b891af6e 100644
--- a/mdoc_validate.c
+++ b/mdoc_validate.c
@@ -209,7 +209,7 @@ static const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, NULL }, /* Eo */
{ NULL, NULL }, /* Fx */
{ NULL, NULL }, /* Ms */
- { NULL, ewarn_eq0 }, /* No */
+ { NULL, NULL }, /* No */
{ NULL, post_ns }, /* Ns */
{ NULL, NULL }, /* Nx */
{ NULL, NULL }, /* Ox */
@@ -353,6 +353,20 @@ mdoc_valid_post(struct mdoc *mdoc)
case MDOC_ROOT:
return(post_root(mdoc));
default:
+
+ /*
+ * Closing delimiters are not special at the
+ * beginning of a block, opening delimiters
+ * are not special at the end.
+ */
+
+ if (n->child != NULL)
+ n->child->flags &= ~MDOC_DELIMC;
+ if (n->last != NULL)
+ n->last->flags &= ~MDOC_DELIMO;
+
+ /* Call the macro's postprocessor. */
+
p = mdoc_valids[n->tok].post;
return(*p ? (*p)(mdoc) : 1);
}
@@ -1162,10 +1176,6 @@ post_defaults(POST_ARGS)
if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "..."))
return(0);
break;
- case MDOC_Li:
- if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, ""))
- return(0);
- break;
case MDOC_Pa:
/* FALLTHROUGH */
case MDOC_Mt: