level, validation must be separated from parsing and rewinding.
This first big step moves calling of the mdoc(7) post_*() functions
out of the parser loop into their own mdoc_validate() pass, while
using a new mdoc_state() module to make syntax tree state handling
available to both the parser loop and the validation pass.
-# $OpenBSD: Makefile,v 1.98 2015/10/13 15:50:15 schwarze Exp $
+# $OpenBSD: Makefile,v 1.99 2015/10/20 02:00:49 schwarze Exp $
.include <bsd.own.mk>
SRCS= mandoc.c mandoc_aux.c mandoc_ohash.c preconv.c read.c \
roff.c tbl.c tbl_opts.c tbl_layout.c tbl_data.c eqn.c
SRCS+= mdoc_macro.c mdoc.c mdoc_hash.c \
- mdoc_argv.c mdoc_validate.c att.c msec.c st.c
+ mdoc_argv.c mdoc_state.c mdoc_validate.c att.c msec.c st.c
SRCS+= man_macro.c man.c man_hash.c man_validate.c
SRCS+= main.c mdoc_term.c tag.c chars.c term.c tree.c man_term.c eqn_term.c
SRCS+= mdoc_man.c
# To install, run: sudo make installcgi
# After that, read: man man.cgi.8
-LIBMDOC_OBJS = mdoc_argv.o mdoc_hash.o mdoc_macro.o mdoc_validate.o \
- mdoc.o att.o st.o
+LIBMDOC_OBJS = mdoc_argv.o mdoc_hash.o mdoc_macro.o mdoc_state.o \
+ mdoc_validate.o mdoc.o att.o st.o
LIBMAN_OBJS = man.o man_hash.o man_macro.o man_validate.o
LIBROFF_OBJS = roff.o eqn.o tbl.o tbl_data.o tbl_layout.o tbl_opts.o
LIBMANDOC_OBJS = ${LIBMDOC_OBJS} ${LIBMAN_OBJS} ${LIBROFF_OBJS} \
CGI_OBJS = ${LIBMANDOC_OBJS} ${HTML_OBJS} \
mansearch.o mansearch_const.o cgi.o
-cgi.o: main.h mandoc.h mandoc_aux.h mandoc_ohash.h manconf.h mansearch.h cgi.h
+cgi.o: cgi.h main.h manconf.h mandoc.h mandoc_aux.h mansearch.h \
+ mdoc.h roff.h
man.cgi: ${CGI_OBJS}
${CC} ${LDFLAGS} ${STATIC} -o ${.TARGET} ${CGI_OBJS} ${LDADD}
-/* $OpenBSD: cgi.c,v 1.49 2015/10/13 22:57:49 schwarze Exp $ */
+/* $OpenBSD: cgi.c,v 1.50 2015/10/20 02:00:49 schwarze Exp $ */
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@usta.de>
#include "mandoc_aux.h"
#include "mandoc.h"
#include "roff.h"
+#include "mdoc.h"
#include "main.h"
#include "manconf.h"
#include "mansearch.h"
vp = html_alloc(&conf);
- if (man->macroset == MACROSET_MDOC)
+ if (man->macroset == MACROSET_MDOC) {
+ mdoc_validate(man);
html_mdoc(vp, man);
- else
+ } else
html_man(vp, man);
html_free(vp);
-/* $OpenBSD: libmdoc.h,v 1.77 2015/10/17 00:19:58 schwarze Exp $ */
+/* $OpenBSD: libmdoc.h,v 1.78 2015/10/20 02:00:49 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
struct roff_node *mdoc_endbody_alloc(struct roff_man *, int, int, int,
struct roff_node *, enum mdoc_endbody);
void mdoc_node_relink(struct roff_man *, struct roff_node *);
+void mdoc_node_validate(struct roff_man *);
+void mdoc_state(struct roff_man *, struct roff_node *);
+void mdoc_state_reset(struct roff_man *);
int mdoc_hash_find(const char *);
+const char *mdoc_a2arch(const char *);
const char *mdoc_a2att(const char *);
+enum roff_sec mdoc_a2sec(const char *);
const char *mdoc_a2st(const char *);
-const char *mdoc_a2arch(const char *);
void mdoc_argv(struct roff_man *, int, int,
struct mdoc_arg **, int *, char *);
enum margserr mdoc_args(struct roff_man *, int,
-/* $OpenBSD: main.c,v 1.158 2015/10/19 19:51:06 schwarze Exp $ */
+/* $OpenBSD: main.c,v 1.159 2015/10/20 02:00:49 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
if (man == NULL)
return;
if (man->macroset == MACROSET_MDOC) {
+ mdoc_validate(man);
switch (curp->outtype) {
case OUTT_HTML:
html_mdoc(curp->outdata, man);
-/* $OpenBSD: mandocdb.c,v 1.158 2015/10/16 13:37:44 millert Exp $ */
+/* $OpenBSD: mandocdb.c,v 1.159 2015/10/20 02:00:49 schwarze Exp $ */
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011-2015 Ingo Schwarze <schwarze@openbsd.org>
}
goto nextpage;
} else if (man != NULL && man->macroset == MACROSET_MDOC) {
+ mdoc_validate(man);
mpage->form = FORM_SRC;
mpage->sec = man->meta.msec;
mpage->sec = mandoc_strdup(
-/* $OpenBSD: mdoc.c,v 1.143 2015/10/12 00:07:27 schwarze Exp $ */
+/* $OpenBSD: mdoc.c,v 1.144 2015/10/20 02:00:49 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org>
{
assert(tok > TOKEN_NONE && tok < MDOC_MAX);
- if (mdoc->flags & MDOC_PBODY) {
- if (tok == MDOC_Dt) {
- mandoc_vmsg(MANDOCERR_DT_LATE,
- mdoc->parse, line, ppos,
- "Dt %s", buf + *pos);
- return;
- }
- } else if ( ! (mdoc_macros[tok].flags & MDOC_PROLOGUE)) {
- if (mdoc->meta.title == NULL) {
- mandoc_vmsg(MANDOCERR_DT_NOTITLE,
- mdoc->parse, line, ppos, "%s %s",
- mdoc_macronames[tok], buf + *pos);
- mdoc->meta.title = mandoc_strdup("UNTITLED");
- }
- if (NULL == mdoc->meta.vol)
- mdoc->meta.vol = mandoc_strdup("LOCAL");
- mdoc->flags |= MDOC_PBODY;
- }
(*mdoc_macros[tok].fp)(mdoc, tok, line, ppos, pos, buf);
}
* behaviour that we want to work around it.
*/
roff_elem_alloc(mdoc, line, offs, MDOC_sp);
+ mdoc->last->flags |= MDOC_VALID | MDOC_ENDED;
mdoc->next = ROFF_NEXT_SIBLING;
- mdoc_valid_post(mdoc);
return 1;
}
return DELIM_NONE;
}
+
+void
+mdoc_validate(struct roff_man *mdoc)
+{
+
+ mdoc->last = mdoc->first;
+ mdoc_node_validate(mdoc);
+ mdoc_state_reset(mdoc);
+}
-/* $OpenBSD: mdoc.h,v 1.67 2015/04/23 16:17:04 schwarze Exp $ */
+/* $OpenBSD: mdoc.h,v 1.68 2015/10/20 02:00:49 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
/* Names of macro args. Index is enum mdocargt. */
extern const char *const *mdoc_argnames;
+
+__BEGIN_DECLS
+
+void mdoc_validate(struct roff_man *);
+
+__END_DECLS
-/* $OpenBSD: mdoc_macro.c,v 1.161 2015/10/17 00:19:58 schwarze Exp $ */
+/* $OpenBSD: mdoc_macro.c,v 1.162 2015/10/20 02:00:49 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org>
/* Rewind to the first. */
rew_last(mdoc, mdoc->first);
+ mdoc_state_reset(mdoc);
}
/*
static void
rew_last(struct roff_man *mdoc, const struct roff_node *to)
{
- struct roff_node *np;
if (to->flags & MDOC_VALID)
return;
while (mdoc->last != to) {
- /*
- * Save the parent here, because we may delete the
- * mdoc->last node in the post-validation phase and reset
- * it to mdoc->last->parent, causing a step in the closing
- * out to be lost.
- */
- np = mdoc->last->parent;
- mdoc_valid_post(mdoc);
- mdoc->last = np;
- assert(mdoc->last);
+ mdoc_state(mdoc, mdoc->last);
+ mdoc->last->flags |= MDOC_VALID | MDOC_ENDED;
+ mdoc->last = mdoc->last->parent;
}
+ mdoc_state(mdoc, mdoc->last);
+ mdoc->last->flags |= MDOC_VALID | MDOC_ENDED;
mdoc->next = ROFF_NEXT_SIBLING;
- mdoc_valid_post(mdoc);
}
/*
--- /dev/null
+/* $OpenBSD: mdoc_state.c,v 1.1 2015/10/20 02:00:49 schwarze Exp $ */
+/*
+ * Copyright (c) 2014, 2015 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
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <sys/types.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "mandoc.h"
+#include "roff.h"
+#include "mdoc.h"
+#include "libmandoc.h"
+#include "libmdoc.h"
+
+#define STATE_ARGS struct roff_man *mdoc, struct roff_node *n
+
+typedef void (*state_handler)(STATE_ARGS);
+
+static void state_bd(STATE_ARGS);
+static void state_dl(STATE_ARGS);
+static void state_sh(STATE_ARGS);
+static void state_sm(STATE_ARGS);
+
+static const state_handler state_handlers[MDOC_MAX] = {
+ NULL, /* Ap */
+ NULL, /* Dd */
+ NULL, /* Dt */
+ NULL, /* Os */
+ state_sh, /* Sh */
+ NULL, /* Ss */
+ NULL, /* Pp */
+ NULL, /* D1 */
+ state_dl, /* Dl */
+ state_bd, /* Bd */
+ NULL, /* Ed */
+ NULL, /* Bl */
+ NULL, /* El */
+ NULL, /* It */
+ NULL, /* Ad */
+ NULL, /* An */
+ NULL, /* Ar */
+ NULL, /* Cd */
+ NULL, /* Cm */
+ NULL, /* Dv */
+ NULL, /* Er */
+ NULL, /* Ev */
+ NULL, /* Ex */
+ NULL, /* Fa */
+ NULL, /* Fd */
+ NULL, /* Fl */
+ NULL, /* Fn */
+ NULL, /* Ft */
+ NULL, /* Ic */
+ NULL, /* In */
+ NULL, /* Li */
+ NULL, /* Nd */
+ NULL, /* Nm */
+ NULL, /* Op */
+ NULL, /* Ot */
+ NULL, /* Pa */
+ NULL, /* Rv */
+ NULL, /* St */
+ NULL, /* Va */
+ NULL, /* Vt */
+ NULL, /* Xr */
+ NULL, /* %A */
+ NULL, /* %B */
+ NULL, /* %D */
+ NULL, /* %I */
+ NULL, /* %J */
+ NULL, /* %N */
+ NULL, /* %O */
+ NULL, /* %P */
+ NULL, /* %R */
+ NULL, /* %T */
+ NULL, /* %V */
+ NULL, /* Ac */
+ NULL, /* Ao */
+ NULL, /* Aq */
+ NULL, /* At */
+ NULL, /* Bc */
+ NULL, /* Bf */
+ NULL, /* Bo */
+ NULL, /* Bq */
+ NULL, /* Bsx */
+ NULL, /* Bx */
+ NULL, /* Db */
+ NULL, /* Dc */
+ NULL, /* Do */
+ NULL, /* Dq */
+ NULL, /* Ec */
+ NULL, /* Ef */
+ NULL, /* Em */
+ NULL, /* Eo */
+ NULL, /* Fx */
+ NULL, /* Ms */
+ NULL, /* No */
+ NULL, /* Ns */
+ NULL, /* Nx */
+ NULL, /* Ox */
+ NULL, /* Pc */
+ NULL, /* Pf */
+ NULL, /* Po */
+ NULL, /* Pq */
+ NULL, /* Qc */
+ NULL, /* Ql */
+ NULL, /* Qo */
+ NULL, /* Qq */
+ NULL, /* Re */
+ NULL, /* Rs */
+ NULL, /* Sc */
+ NULL, /* So */
+ NULL, /* Sq */
+ state_sm, /* Sm */
+ NULL, /* Sx */
+ NULL, /* Sy */
+ NULL, /* Tn */
+ NULL, /* Ux */
+ NULL, /* Xc */
+ NULL, /* Xo */
+ NULL, /* Fo */
+ NULL, /* Fc */
+ NULL, /* Oo */
+ NULL, /* Oc */
+ NULL, /* Bk */
+ NULL, /* Ek */
+ NULL, /* Bt */
+ NULL, /* Hf */
+ NULL, /* Fr */
+ NULL, /* Ud */
+ NULL, /* Lb */
+ NULL, /* Lp */
+ NULL, /* Lk */
+ NULL, /* Mt */
+ NULL, /* Brq */
+ NULL, /* Bro */
+ NULL, /* Brc */
+ NULL, /* %C */
+ NULL, /* Es */
+ NULL, /* En */
+ NULL, /* Dx */
+ NULL, /* %Q */
+ NULL, /* br */
+ NULL, /* sp */
+ NULL, /* %U */
+ NULL, /* Ta */
+ NULL, /* ll */
+};
+
+
+void
+mdoc_state(struct roff_man *mdoc, struct roff_node *n)
+{
+ state_handler handler;
+
+ if (n->tok == TOKEN_NONE)
+ return;
+
+ if ( ! (mdoc_macros[n->tok].flags & MDOC_PROLOGUE))
+ mdoc->flags |= MDOC_PBODY;
+
+ handler = state_handlers[n->tok];
+ if (*handler)
+ (*handler)(mdoc, n);
+}
+
+void
+mdoc_state_reset(struct roff_man *mdoc)
+{
+
+ roff_setreg(mdoc->roff, "nS", 0, '=');
+ mdoc->flags = 0;
+}
+
+static void
+state_bd(STATE_ARGS)
+{
+ enum mdocargt arg;
+
+ if (n->type != ROFFT_HEAD &&
+ (n->type != ROFFT_BODY || n->end != ENDBODY_NOT))
+ return;
+
+ arg = n->parent->args->argv[0].arg;
+ if (arg != MDOC_Literal && arg != MDOC_Unfilled)
+ return;
+
+ state_dl(mdoc, n);
+}
+
+static void
+state_dl(STATE_ARGS)
+{
+
+ switch (n->type) {
+ case ROFFT_HEAD:
+ mdoc->flags |= MDOC_LITERAL;
+ break;
+ case ROFFT_BODY:
+ mdoc->flags &= ~MDOC_LITERAL;
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+state_sh(STATE_ARGS)
+{
+ struct roff_node *nch;
+ char *secname;
+
+ if (n->type != ROFFT_HEAD)
+ return;
+
+ if ( ! (n->flags & MDOC_VALID)) {
+ secname = NULL;
+ deroff(&secname, n);
+
+ /*
+ * Set the section attribute for the BLOCK, HEAD,
+ * and HEAD children; the latter can only be TEXT
+ * nodes, so no recursion is needed. For other
+ * nodes, including the .Sh BODY, this is done
+ * when allocating the node data structures, but
+ * for .Sh BLOCK and HEAD, the section is still
+ * unknown at that time.
+ */
+
+ n->sec = n->parent->sec = secname == NULL ?
+ SEC_CUSTOM : mdoc_a2sec(secname);
+ for (nch = n->child; nch != NULL; nch = nch->next)
+ nch->sec = n->sec;
+ free(secname);
+ }
+
+ if ((mdoc->lastsec = n->sec) == SEC_SYNOPSIS) {
+ roff_setreg(mdoc->roff, "nS", 1, '=');
+ mdoc->flags |= MDOC_SYNOPSIS;
+ } else {
+ roff_setreg(mdoc->roff, "nS", 0, '=');
+ mdoc->flags &= ~MDOC_SYNOPSIS;
+ }
+}
+
+static void
+state_sm(STATE_ARGS)
+{
+
+ if (n->child == NULL)
+ mdoc->flags ^= MDOC_SMOFF;
+ else if ( ! strcmp(n->child->string, "on"))
+ mdoc->flags &= ~MDOC_SMOFF;
+ else if ( ! strcmp(n->child->string, "off"))
+ mdoc->flags |= MDOC_SMOFF;
+}
-/* $OpenBSD: mdoc_validate.c,v 1.213 2015/10/19 20:03:57 schwarze Exp $ */
+/* $OpenBSD: mdoc_validate.c,v 1.214 2015/10/20 02:00:49 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
struct roff_node *, struct mdoc_argv *);
static void check_args(struct roff_man *, struct roff_node *);
static int child_an(const struct roff_node *);
-static enum roff_sec a2sec(const char *);
static size_t macro2len(int);
static void rewrite_macro2len(char **);
static void pre_an(PRE_ARGS);
static void pre_bd(PRE_ARGS);
static void pre_bl(PRE_ARGS);
-static void pre_dd(PRE_ARGS);
static void pre_display(PRE_ARGS);
-static void pre_dt(PRE_ARGS);
-static void pre_literal(PRE_ARGS);
static void pre_obsolete(PRE_ARGS);
-static void pre_os(PRE_ARGS);
static void pre_par(PRE_ARGS);
static void pre_std(PRE_ARGS);
static const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, NULL }, /* Ap */
- { pre_dd, post_dd }, /* Dd */
- { pre_dt, post_dt }, /* Dt */
- { pre_os, post_os }, /* Os */
+ { NULL, post_dd }, /* Dd */
+ { NULL, post_dt }, /* Dt */
+ { NULL, post_os }, /* Os */
{ NULL, post_sh }, /* Sh */
{ NULL, post_ignpar }, /* Ss */
{ pre_par, post_par }, /* Pp */
{ pre_display, post_d1 }, /* D1 */
- { pre_literal, post_literal }, /* Dl */
+ { pre_display, post_literal }, /* Dl */
{ pre_bd, post_literal }, /* Bd */
{ NULL, NULL }, /* Ed */
{ pre_bl, post_bl }, /* Bl */
}
void
-mdoc_valid_post(struct roff_man *mdoc)
+mdoc_node_validate(struct roff_man *mdoc)
{
struct roff_node *n;
v_post p;
n = mdoc->last;
- if (n->flags & MDOC_VALID)
- return;
- n->flags |= MDOC_VALID | MDOC_ENDED;
+ mdoc->last = mdoc->last->child;
+ while (mdoc->last != NULL) {
+ mdoc_node_validate(mdoc);
+ if (mdoc->last == n)
+ mdoc->last = mdoc->last->child;
+ else
+ mdoc->last = mdoc->last->next;
+ }
+ mdoc->last = n;
+ mdoc->next = ROFF_NEXT_SIBLING;
switch (n->type) {
case ROFFT_TEXT:
case ROFFT_EQN:
p = mdoc_valids[n->tok].post;
if (*p)
(*p)(mdoc);
+ if (mdoc->last == n)
+ mdoc_state(mdoc, n);
break;
}
}
int i;
enum mdoc_disp dt;
- pre_literal(mdoc, n);
+ pre_display(mdoc, n);
if (n->type != ROFFT_BLOCK)
return;
n->line, n->pos, mdoc_macronames[n->tok]);
}
-static void
-pre_dt(PRE_ARGS)
-{
-
- if (mdoc->meta.title != NULL)
- mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse,
- n->line, n->pos, "Dt");
- else if (mdoc->meta.os != NULL)
- mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse,
- n->line, n->pos, "Dt after Os");
-}
-
-static void
-pre_os(PRE_ARGS)
-{
-
- if (mdoc->meta.os != NULL)
- mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse,
- n->line, n->pos, "Os");
- else if (mdoc->flags & MDOC_PBODY)
- mandoc_msg(MANDOCERR_PROLOG_LATE, mdoc->parse,
- n->line, n->pos, "Os");
-}
-
-static void
-pre_dd(PRE_ARGS)
-{
-
- if (mdoc->meta.date != NULL)
- mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse,
- n->line, n->pos, "Dd");
- else if (mdoc->flags & MDOC_PBODY)
- mandoc_msg(MANDOCERR_PROLOG_LATE, mdoc->parse,
- n->line, n->pos, "Dd");
- else if (mdoc->meta.title != NULL)
- mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse,
- n->line, n->pos, "Dd after Dt");
- else if (mdoc->meta.os != NULL)
- mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse,
- n->line, n->pos, "Dd after Os");
-}
-
static void
post_bf(POST_ARGS)
{
n = mdoc->last;
- if (n->type != ROFFT_BODY)
+ if (n->type != ROFFT_BODY || n->end != ENDBODY_NOT)
return;
if (n->child == NULL)
mandoc_msg(MANDOCERR_BLK_EMPTY, mdoc->parse,
n->line, n->pos, mdoc_macronames[n->tok]);
-
- if (n->tok == MDOC_Bd &&
- n->norm->Bd.type != DISP_literal &&
- n->norm->Bd.type != DISP_unfilled)
- return;
-
- mdoc->flags &= ~MDOC_LITERAL;
}
static void
return;
nn = mdoc->last;
- mdoc->next = ROFF_NEXT_CHILD;
switch (nn->tok) {
case MDOC_Ar:
+ mdoc->next = ROFF_NEXT_CHILD;
roff_word_alloc(mdoc, nn->line, nn->pos, "file");
roff_word_alloc(mdoc, nn->line, nn->pos, "...");
break;
case MDOC_Pa:
case MDOC_Mt:
+ mdoc->next = ROFF_NEXT_CHILD;
roff_word_alloc(mdoc, nn->line, nn->pos, "~");
break;
default:
default:
return;
}
+ if (nbody->end != ENDBODY_NOT)
+ return;
nchild = nbody->child;
if (nchild == NULL) {
static void
post_sh_head(POST_ARGS)
{
- struct roff_node *n;
const char *goodsec;
- char *secname;
enum roff_sec sec;
/*
* manual sections.
*/
- secname = NULL;
- deroff(&secname, mdoc->last);
- sec = NULL == secname ? SEC_CUSTOM : a2sec(secname);
+ sec = mdoc->last->sec;
/* The NAME should be first. */
if (SEC_NAME != sec && SEC_NONE == mdoc->lastnamed)
mandoc_vmsg(MANDOCERR_NAMESEC_FIRST, mdoc->parse,
mdoc->last->line, mdoc->last->pos,
- "Sh %s", secname);
+ "Sh %s", secnames[sec]);
/* The SYNOPSIS gets special attention in other areas. */
- if (SEC_SYNOPSIS == sec) {
+ if (sec == SEC_SYNOPSIS) {
roff_setreg(mdoc->roff, "nS", 1, '=');
mdoc->flags |= MDOC_SYNOPSIS;
} else {
mdoc->lastsec = sec;
- /*
- * Set the section attribute for the current HEAD, for its
- * parent BLOCK, and for the HEAD children; the latter can
- * only be TEXT nodes, so no recursion is needed.
- * For other blocks and elements, including .Sh BODY, this is
- * done when allocating the node data structures, but for .Sh
- * BLOCK and HEAD, the section is still unknown at that time.
- */
-
- mdoc->last->parent->sec = sec;
- mdoc->last->sec = sec;
- for (n = mdoc->last->child; n != NULL; n = n->next)
- n->sec = sec;
-
/* We don't care about custom sections after this. */
- if (SEC_CUSTOM == sec) {
- free(secname);
+ if (sec == SEC_CUSTOM)
return;
- }
/*
* Check whether our non-custom section is being repeated or is
if (sec == mdoc->lastnamed)
mandoc_vmsg(MANDOCERR_SEC_REP, mdoc->parse,
mdoc->last->line, mdoc->last->pos,
- "Sh %s", secname);
+ "Sh %s", secnames[sec]);
if (sec < mdoc->lastnamed)
mandoc_vmsg(MANDOCERR_SEC_ORDER, mdoc->parse,
mdoc->last->line, mdoc->last->pos,
- "Sh %s", secname);
+ "Sh %s", secnames[sec]);
/* Mark the last named section. */
/* Check particular section/manual conventions. */
- if (mdoc->meta.msec == NULL) {
- free(secname);
+ if (mdoc->meta.msec == NULL)
return;
- }
goodsec = NULL;
switch (sec) {
goodsec = "9";
mandoc_vmsg(MANDOCERR_SEC_MSEC, mdoc->parse,
mdoc->last->line, mdoc->last->pos,
- "Sh %s for %s only", secname, goodsec);
+ "Sh %s for %s only", secnames[sec], goodsec);
break;
default:
break;
}
- free(secname);
}
static void
roff_node_delete(mdoc, mdoc->last);
}
-static void
-pre_literal(PRE_ARGS)
-{
-
- pre_display(mdoc, n);
-
- if (n->type != ROFFT_BODY)
- return;
-
- /*
- * The `Dl' (note "el" not "one") and `Bd -literal' and `Bd
- * -unfilled' macros set MDOC_LITERAL on entrance to the body.
- */
-
- switch (n->tok) {
- case MDOC_Dl:
- mdoc->flags |= MDOC_LITERAL;
- break;
- case MDOC_Bd:
- if (DISP_literal == n->norm->Bd.type)
- mdoc->flags |= MDOC_LITERAL;
- if (DISP_unfilled == n->norm->Bd.type)
- mdoc->flags |= MDOC_LITERAL;
- break;
- default:
- abort();
- }
-}
-
static void
post_dd(POST_ARGS)
{
struct roff_node *n;
char *datestr;
- if (mdoc->meta.date)
+ n = mdoc->last;
+ if (mdoc->meta.date != NULL) {
+ mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse,
+ n->line, n->pos, "Dd");
free(mdoc->meta.date);
+ } else if (mdoc->flags & MDOC_PBODY)
+ mandoc_msg(MANDOCERR_PROLOG_LATE, mdoc->parse,
+ n->line, n->pos, "Dd");
+ else if (mdoc->meta.title != NULL)
+ mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse,
+ n->line, n->pos, "Dd after Dt");
+ else if (mdoc->meta.os != NULL)
+ mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse,
+ n->line, n->pos, "Dd after Os");
- n = mdoc->last;
if (n->child == NULL || n->child->string[0] == '\0') {
mdoc->meta.date = mdoc->quick ? mandoc_strdup("") :
mandoc_normdate(mdoc->parse, NULL, n->line, n->pos);
char *p;
n = mdoc->last;
+ if (mdoc->flags & MDOC_PBODY) {
+ mandoc_msg(MANDOCERR_DT_LATE, mdoc->parse,
+ n->line, n->pos, "Dt");
+ goto out;
+ }
+
+ if (mdoc->meta.title != NULL)
+ mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse,
+ n->line, n->pos, "Dt");
+ else if (mdoc->meta.os != NULL)
+ mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse,
+ n->line, n->pos, "Dt after Os");
free(mdoc->meta.title);
free(mdoc->meta.msec);
struct roff_node *n;
n = mdoc->last;
+ if (mdoc->meta.os != NULL)
+ mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse,
+ n->line, n->pos, "Os");
+ else if (mdoc->flags & MDOC_PBODY)
+ mandoc_msg(MANDOCERR_PROLOG_LATE, mdoc->parse,
+ n->line, n->pos, "Os");
/*
* Set the operating system by way of the `Os' macro.
mdoc->last = n;
}
-static enum roff_sec
-a2sec(const char *p)
+enum roff_sec
+mdoc_a2sec(const char *p)
{
int i;
-/* $OpenBSD: roff.c,v 1.152 2015/10/15 23:35:38 schwarze Exp $ */
+/* $OpenBSD: roff.c,v 1.153 2015/10/20 02:00:50 schwarze Exp $ */
/*
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
switch (man->next) {
case ROFF_NEXT_SIBLING:
+ if (man->last->next != NULL) {
+ n->next = man->last->next;
+ man->last->next->prev = n;
+ } else
+ man->last->parent->last = n;
man->last->next = n;
n->prev = man->last;
n->parent = man->last->parent;
case ROFF_NEXT_CHILD:
man->last->child = n;
n->parent = man->last;
+ n->parent->last = n;
break;
default:
abort();
}
n->parent->nchild++;
- n->parent->last = n;
/*
* Copy over the normalised-data pointer of our parent. Not
n->string = roff_strdup(man->roff, word);
roff_node_append(man, n);
if (man->macroset == MACROSET_MDOC)
- mdoc_valid_post(man);
+ n->flags |= MDOC_VALID | MDOC_ENDED;
else
man_valid_post(man);
man->next = ROFF_NEXT_SIBLING;
n->span = tbl;
roff_node_append(man, n);
if (man->macroset == MACROSET_MDOC)
- mdoc_valid_post(man);
+ n->flags |= MDOC_VALID | MDOC_ENDED;
else
man_valid_post(man);
man->next = ROFF_NEXT_SIBLING;
-/* $OpenBSD: roff_int.h,v 1.3 2015/04/19 14:57:16 schwarze Exp $ */
+/* $OpenBSD: roff_int.h,v 1.4 2015/10/20 02:00:50 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
void man_valid_post(struct roff_man *);
void mdoc_valid_pre(struct roff_man *, struct roff_node *);
-void mdoc_valid_post(struct roff_man *);
void mdoc_argv_free(struct mdoc_arg *);
__END_DECLS