-/* $Id: mdoc_macro.c,v 1.132 2014/07/02 03:48:07 schwarze Exp $ */
+/* $Id: mdoc_macro.c,v 1.143 2014/09/07 00:05:28 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2012, 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
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#ifdef HAVE_CONFIG_H
#include "config.h"
-#endif
+
+#include <sys/types.h>
#include <assert.h>
#include <ctype.h>
{ in_line_eoln, 0 }, /* sp */
{ in_line_eoln, 0 }, /* %U */
{ phrase_ta, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ta */
- { in_line_eoln, 0 }, /* ll */
+ { in_line_eoln, MDOC_PROLOGUE }, /* ll */
};
const struct mdoc_macro * const mdoc_macros = __mdoc_macros;
for ( ; n; n = n->parent)
if (MDOC_BLOCK == n->type &&
MDOC_EXPLICIT & mdoc_macros[n->tok].flags)
- mdoc_nmsg(mdoc, n, MANDOCERR_SCOPEEXIT);
+ mandoc_msg(MANDOCERR_BLK_NOEND, mdoc->parse,
+ n->line, n->pos, mdoc_macronames[n->tok]);
/* Rewind to the first. */
return(REWIND_NONE);
/* FALLTHROUGH */
case MDOC_Sh:
+ if (MDOC_ROOT == p->parent->type)
+ return(REWIND_THIS);
if (MDOC_Nd == p->tok || MDOC_Ss == p->tok ||
MDOC_Sh == p->tok)
return(REWIND_MORE);
taker->pending = broken->pending;
}
broken->pending = breaker;
- mandoc_vmsg(MANDOCERR_SCOPENEST, mdoc->parse, line, ppos,
+ mandoc_vmsg(MANDOCERR_BLK_NEST, mdoc->parse, line, ppos,
"%s breaks %s", mdoc_macronames[tok],
mdoc_macronames[broken->tok]);
return(1);
! (MDOC_EXPLICIT & mdoc_macros[tok].flags));
break;
case REWIND_FORCE:
- mandoc_vmsg(MANDOCERR_SCOPEBROKEN, mdoc->parse,
+ mandoc_vmsg(MANDOCERR_BLK_BROKEN, mdoc->parse,
line, ppos, "%s breaks %s",
mdoc_macronames[tok],
mdoc_macronames[n->tok]);
return(1);
/* FALLTHROUGH */
case REWIND_ERROR:
- mdoc_pmsg(mdoc, line, ppos, MANDOCERR_NOSCOPE);
+ mandoc_msg(MANDOCERR_BLK_NOTOPEN,
+ mdoc->parse, line, ppos,
+ mdoc_macronames[tok]);
return(1);
}
break;
later = n;
}
- if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
- /* FIXME: do this in validate */
- if (buf[*pos])
- mdoc_pmsg(mdoc, line, ppos, MANDOCERR_ARGSLOST);
-
+ if ( ! (MDOC_PARSED & mdoc_macros[tok].flags)) {
+ if ('\0' != buf[*pos])
+ mandoc_vmsg(MANDOCERR_ARG_SKIP,
+ mdoc->parse, line, ppos,
+ "%s %s", mdoc_macronames[tok],
+ buf + *pos);
if ( ! rew_sub(MDOC_BODY, mdoc, tok, line, ppos))
return(0);
return(rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos));
static int
in_line(MACRO_PROT_ARGS)
{
- int la, scope, cnt, nc, nl;
+ int la, scope, cnt, mayopen, nc, nl;
enum margverr av;
enum mdoct ntok;
enum margserr ac;
return(0);
}
+ mayopen = 1;
for (cnt = scope = 0;; ) {
la = *pos;
ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
return(0);
} else if ( ! nc && 0 == cnt) {
mdoc_argv_free(arg);
- mdoc_pmsg(mdoc, line, ppos,
- MANDOCERR_MACROEMPTY);
+ mandoc_msg(MANDOCERR_MACRO_EMPTY,
+ mdoc->parse, line, ppos,
+ mdoc_macronames[tok]);
}
if ( ! mdoc_macro(mdoc, ntok, line, la, pos, buf))
* If we encounter closing punctuation, no word
* has been omitted, no scope is open, and we're
* allowed to have an empty element, then start
- * a new scope. `Ar', `Fl', and `Li', only do
- * this once per invocation. There may be more
- * of these (all of them?).
+ * a new scope.
*/
- if (0 == cnt && (nc || MDOC_Li == tok) &&
- DELIM_CLOSE == d && ! scope) {
+ if ((d == DELIM_CLOSE ||
+ (d == DELIM_MIDDLE && tok == MDOC_Fl)) &&
+ (nc || tok == MDOC_Li) &&
+ !scope && !cnt && mayopen) {
if ( ! mdoc_elem_alloc(mdoc,
line, ppos, tok, arg))
return(0);
- if (MDOC_Ar == tok || MDOC_Li == tok ||
- MDOC_Fl == tok)
- cnt++;
scope = 1;
+ cnt++;
+ if (MDOC_Li == tok || MDOC_Nm == tok)
+ mayopen = 0;
}
/*
* Close out our scope, if one is open, before
if (scope && ! rew_elem(mdoc, tok))
return(0);
scope = 0;
- } else if ( ! scope) {
+ } else if (mayopen && !scope) {
if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg))
return(0);
scope = 1;
- }
-
- if (DELIM_NONE == d)
cnt++;
+ }
if ( ! dword(mdoc, line, la, p, d,
MDOC_JOIN & mdoc_macros[tok].flags))
return(0);
} else if ( ! nc && 0 == cnt) {
mdoc_argv_free(arg);
- mdoc_pmsg(mdoc, line, ppos, MANDOCERR_MACROEMPTY);
+ mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,
+ line, ppos, mdoc_macronames[tok]);
}
if ( ! nl)
nl = MDOC_NEWLINE & mdoc->flags;
+ /* Skip items outside lists. */
+
+ if (tok == MDOC_It) {
+ for (n = mdoc->last; n; n = n->parent)
+ if (n->tok == MDOC_Bl &&
+ ! (n->flags & MDOC_VALID))
+ break;
+ if (n == NULL) {
+ mandoc_vmsg(MANDOCERR_IT_STRAY, mdoc->parse,
+ line, ppos, "It %s", buf + *pos);
+ if ( ! mdoc_elem_alloc(mdoc, line, ppos,
+ MDOC_br, NULL))
+ return(0);
+ return(rew_elem(mdoc, MDOC_br));
+ }
+ }
+
/* Close out prior implicit scope. */
if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) {
return(1);
}
}
+ assert(n == body);
- /*
- * If we can't rewind to our body, then our scope has already
- * been closed by another macro (like `Oc' closing `Op'). This
- * is ugly behaviour nodding its head to OpenBSD's overwhelming
- * crufty use of `Op' breakage.
- */
- if (n != body)
- mandoc_vmsg(MANDOCERR_SCOPENEST, mdoc->parse, line,
- ppos, "%s broken", mdoc_macronames[tok]);
-
- if (n && ! rew_sub(MDOC_BODY, mdoc, tok, line, ppos))
+ if ( ! rew_sub(MDOC_BODY, mdoc, tok, line, ppos))
return(0);
/* Standard appending of delimiters. */
/* Rewind scope, if applicable. */
- if (n && ! rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos))
+ if ( ! rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos))
return(0);
/* Move trailing .Ns out of scope. */
return(0);
continue;
} else if (0 == j)
- if ( ! mdoc_elem_alloc(mdoc, line, la, tok, arg))
+ if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg))
return(0);
if (j == maxargs && ! flushed) {
j++;
}
- if (0 == j && ! mdoc_elem_alloc(mdoc, line, la, tok, arg))
+ if (0 == j && ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg))
return(0);
/* Close out in a consistent state. */
while (NULL != n && MDOC_Bl != n->tok)
n = n->parent;
if (NULL == n || LIST_column != n->norm->Bl.type) {
- mdoc_pmsg(mdoc, line, ppos, MANDOCERR_STRAYTA);
+ mandoc_msg(MANDOCERR_TA_STRAY, mdoc->parse,
+ line, ppos, "Ta");
return(1);
}