aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2015-10-20 02:01:31 +0000
committerIngo Schwarze <schwarze@openbsd.org>2015-10-20 02:01:31 +0000
commit8a6d6ac9ce00755e9537a67b9a9dd8f4c4e76d09 (patch)
treecfc8f856e7b5ebdcad65963f0d3ad74169858e29
parent128ee8c8e1032e5e05f88acbd4000c8166085b25 (diff)
downloadmandoc-8a6d6ac9ce00755e9537a67b9a9dd8f4c4e76d09.tar.gz
mandoc-8a6d6ac9ce00755e9537a67b9a9dd8f4c4e76d09.tar.zst
mandoc-8a6d6ac9ce00755e9537a67b9a9dd8f4c4e76d09.zip
In order to become able to generate syntax tree nodes on the roff(7)
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.
-rw-r--r--Makefile4
-rw-r--r--Makefile.depend3
-rw-r--r--cgi.c8
-rw-r--r--demandoc.c7
-rw-r--r--libmdoc.h8
-rw-r--r--main.c3
-rw-r--r--mandocdb.c3
-rw-r--r--mdoc.c31
-rw-r--r--mdoc.h8
-rw-r--r--mdoc_macro.c20
-rw-r--r--mdoc_state.c269
-rw-r--r--mdoc_validate.c195
-rw-r--r--roff.c13
-rw-r--r--roff_int.h3
14 files changed, 393 insertions, 182 deletions
diff --git a/Makefile b/Makefile
index c6bcefeb..9dd345c4 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.469 2015/10/13 22:59:54 schwarze Exp $
+# $Id: Makefile,v 1.470 2015/10/20 02:01:31 schwarze Exp $
#
# Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
# Copyright (c) 2011, 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -88,6 +88,7 @@ SRCS = att.c \
mdoc_html.c \
mdoc_macro.c \
mdoc_man.c \
+ mdoc_state.c \
mdoc_term.c \
mdoc_validate.c \
msec.c \
@@ -183,6 +184,7 @@ LIBMDOC_OBJS = att.o \
mdoc_argv.o \
mdoc_hash.o \
mdoc_macro.o \
+ mdoc_state.o \
mdoc_validate.o \
st.o
diff --git a/Makefile.depend b/Makefile.depend
index 85d7d673..4cb1df3e 100644
--- a/Makefile.depend
+++ b/Makefile.depend
@@ -1,5 +1,5 @@
att.o: att.c config.h roff.h mdoc.h libmdoc.h
-cgi.o: cgi.c config.h mandoc_aux.h mandoc.h roff.h main.h manconf.h mansearch.h cgi.h
+cgi.o: cgi.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h main.h manconf.h mansearch.h cgi.h
chars.o: chars.c config.h mandoc.h mandoc_aux.h mandoc_ohash.h compat_ohash.h libmandoc.h
compat_err.o: compat_err.c config.h
compat_fgetln.o: compat_fgetln.c config.h
@@ -44,6 +44,7 @@ mdoc_hash.o: mdoc_hash.c config.h roff.h mdoc.h libmdoc.h
mdoc_html.o: mdoc_html.c config.h mandoc_aux.h roff.h mdoc.h out.h html.h main.h
mdoc_macro.o: mdoc_macro.c config.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h
mdoc_man.o: mdoc_man.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h out.h main.h
+mdoc_state.o: mdoc_state.c mandoc.h roff.h mdoc.h libmandoc.h libmdoc.h
mdoc_term.o: mdoc_term.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h out.h term.h tag.h main.h
mdoc_validate.o: mdoc_validate.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h
msec.o: msec.c config.h mandoc.h libmandoc.h msec.in
diff --git a/cgi.c b/cgi.c
index 2148c7cf..7f78aa7b 100644
--- a/cgi.c
+++ b/cgi.c
@@ -1,4 +1,4 @@
-/* $Id: cgi.c,v 1.110 2015/10/13 22:59:54 schwarze Exp $ */
+/* $Id: cgi.c,v 1.111 2015/10/20 02:01:31 schwarze Exp $ */
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@usta.de>
@@ -33,6 +33,7 @@
#include "mandoc_aux.h"
#include "mandoc.h"
#include "roff.h"
+#include "mdoc.h"
#include "main.h"
#include "manconf.h"
#include "mansearch.h"
@@ -856,9 +857,10 @@ format(const struct req *req, const char *file)
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);
diff --git a/demandoc.c b/demandoc.c
index deaa7909..63a4ad7f 100644
--- a/demandoc.c
+++ b/demandoc.c
@@ -1,4 +1,4 @@
-/* $Id: demandoc.c,v 1.22 2015/10/13 22:59:54 schwarze Exp $ */
+/* $Id: demandoc.c,v 1.23 2015/10/20 02:01:31 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -119,9 +119,10 @@ pmandoc(struct mparse *mp, int fd, const char *fn, int list)
if (man == NULL)
return;
- if (man->macroset == MACROSET_MDOC)
+ if (man->macroset == MACROSET_MDOC) {
+ mdoc_validate(man);
pmdoc(man->first->child, &line, &col, list);
- else
+ } else
pman(man->first->child, &line, &col, list);
if ( ! list)
diff --git a/libmdoc.h b/libmdoc.h
index e06ae6e6..5240fd0c 100644
--- a/libmdoc.h
+++ b/libmdoc.h
@@ -1,4 +1,4 @@
-/* $Id: libmdoc.h,v 1.106 2015/10/17 00:21:07 schwarze Exp $ */
+/* $Id: libmdoc.h,v 1.107 2015/10/20 02:01:31 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -73,11 +73,15 @@ void mdoc_tail_alloc(struct roff_man *, int, int, int);
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 *);
const char *mdoc_a2lib(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,
diff --git a/main.c b/main.c
index f21279da..39c8946e 100644
--- a/main.c
+++ b/main.c
@@ -1,4 +1,4 @@
-/* $Id: main.c,v 1.250 2015/10/19 19:51:22 schwarze Exp $ */
+/* $Id: main.c,v 1.251 2015/10/20 02:01:31 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -696,6 +696,7 @@ parse(struct curparse *curp, int fd, const char *file)
if (man == NULL)
return;
if (man->macroset == MACROSET_MDOC) {
+ mdoc_validate(man);
switch (curp->outtype) {
case OUTT_HTML:
html_mdoc(curp->outdata, man);
diff --git a/mandocdb.c b/mandocdb.c
index ff4df09a..cbafc615 100644
--- a/mandocdb.c
+++ b/mandocdb.c
@@ -1,4 +1,4 @@
-/* $Id: mandocdb.c,v 1.203 2015/10/13 22:59:54 schwarze Exp $ */
+/* $Id: mandocdb.c,v 1.204 2015/10/20 02:01:31 schwarze Exp $ */
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011-2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -1166,6 +1166,7 @@ mpages_merge(struct mparse *mp)
}
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(
diff --git a/mdoc.c b/mdoc.c
index a6509722..12f126f5 100644
--- a/mdoc.c
+++ b/mdoc.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc.c,v 1.254 2015/10/12 00:08:15 schwarze Exp $ */
+/* $Id: mdoc.c,v 1.255 2015/10/20 02:01:31 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -121,24 +121,6 @@ mdoc_macro(MACRO_PROT_ARGS)
{
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);
}
@@ -319,8 +301,8 @@ mdoc_ptext(struct roff_man *mdoc, int line, char *buf, int offs)
* 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;
}
@@ -495,3 +477,12 @@ mdoc_isdelim(const char *p)
return DELIM_NONE;
}
+
+void
+mdoc_validate(struct roff_man *mdoc)
+{
+
+ mdoc->last = mdoc->first;
+ mdoc_node_validate(mdoc);
+ mdoc_state_reset(mdoc);
+}
diff --git a/mdoc.h b/mdoc.h
index 30f60fab..f793cc23 100644
--- a/mdoc.h
+++ b/mdoc.h
@@ -1,4 +1,4 @@
-/* $Id: mdoc.h,v 1.142 2015/04/23 16:17:44 schwarze Exp $ */
+/* $Id: mdoc.h,v 1.143 2015/10/20 02:01:31 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -279,3 +279,9 @@ extern const char *const *mdoc_macronames;
/* Names of macro args. Index is enum mdocargt. */
extern const char *const *mdoc_argnames;
+
+__BEGIN_DECLS
+
+void mdoc_validate(struct roff_man *);
+
+__END_DECLS
diff --git a/mdoc_macro.c b/mdoc_macro.c
index 63335cc7..ca959589 100644
--- a/mdoc_macro.c
+++ b/mdoc_macro.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_macro.c,v 1.205 2015/10/17 00:21:07 schwarze Exp $ */
+/* $Id: mdoc_macro.c,v 1.206 2015/10/20 02:01:32 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -228,6 +228,7 @@ mdoc_endparse(struct roff_man *mdoc)
/* Rewind to the first. */
rew_last(mdoc, mdoc->first);
+ mdoc_state_reset(mdoc);
}
/*
@@ -262,25 +263,18 @@ lookup(struct roff_man *mdoc, int from, int line, int ppos, const char *p)
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);
}
/*
diff --git a/mdoc_state.c b/mdoc_state.c
new file mode 100644
index 00000000..061092ce
--- /dev/null
+++ b/mdoc_state.c
@@ -0,0 +1,269 @@
+/* $Id: mdoc_state.c,v 1.1 2015/10/20 02:01:32 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;
+}
diff --git a/mdoc_validate.c b/mdoc_validate.c
index 1b3de60b..384c5345 100644
--- a/mdoc_validate.c
+++ b/mdoc_validate.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_validate.c,v 1.297 2015/10/19 20:04:10 schwarze Exp $ */
+/* $Id: mdoc_validate.c,v 1.298 2015/10/20 02:01:32 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -63,7 +63,6 @@ static void check_argv(struct roff_man *,
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 **);
@@ -111,25 +110,21 @@ static void post_st(POST_ARGS);
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 */
@@ -317,16 +312,23 @@ mdoc_valid_pre(struct roff_man *mdoc, struct roff_node *n)
}
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:
@@ -353,6 +355,8 @@ mdoc_valid_post(struct roff_man *mdoc)
p = mdoc_valids[n->tok].post;
if (*p)
(*p)(mdoc);
+ if (mdoc->last == n)
+ mdoc_state(mdoc, n);
break;
}
}
@@ -594,7 +598,7 @@ pre_bd(PRE_ARGS)
int i;
enum mdoc_disp dt;
- pre_literal(mdoc, n);
+ pre_display(mdoc, n);
if (n->type != ROFFT_BLOCK)
return;
@@ -714,48 +718,6 @@ pre_obsolete(PRE_ARGS)
}
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)
{
struct roff_node *np, *nch;
@@ -986,19 +948,12 @@ post_literal(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
@@ -1016,15 +971,16 @@ post_defaults(POST_ARGS)
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:
@@ -1384,6 +1340,8 @@ post_bl(POST_ARGS)
default:
return;
}
+ if (nbody->end != ENDBODY_NOT)
+ return;
nchild = nbody->child;
if (nchild == NULL) {
@@ -1828,9 +1786,7 @@ post_sh_authors(POST_ARGS)
static void
post_sh_head(POST_ARGS)
{
- struct roff_node *n;
const char *goodsec;
- char *secname;
enum roff_sec sec;
/*
@@ -1840,20 +1796,18 @@ post_sh_head(POST_ARGS)
* 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 {
@@ -1865,26 +1819,10 @@ post_sh_head(POST_ARGS)
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
@@ -1894,12 +1832,12 @@ post_sh_head(POST_ARGS)
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. */
@@ -1907,10 +1845,8 @@ post_sh_head(POST_ARGS)
/* Check particular section/manual conventions. */
- if (mdoc->meta.msec == NULL) {
- free(secname);
+ if (mdoc->meta.msec == NULL)
return;
- }
goodsec = NULL;
switch (sec) {
@@ -1935,12 +1871,11 @@ post_sh_head(POST_ARGS)
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
@@ -2043,44 +1978,26 @@ post_par(POST_ARGS)
}
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);
@@ -2108,6 +2025,18 @@ post_dt(POST_ARGS)
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);
@@ -2210,6 +2139,12 @@ post_os(POST_ARGS)
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.
@@ -2275,8 +2210,8 @@ post_ex(POST_ARGS)
mdoc->last = n;
}
-static enum roff_sec
-a2sec(const char *p)
+enum roff_sec
+mdoc_a2sec(const char *p)
{
int i;
diff --git a/roff.c b/roff.c
index 614758a0..12853cad 100644
--- a/roff.c
+++ b/roff.c
@@ -1,4 +1,4 @@
-/* $Id: roff.c,v 1.280 2015/10/15 23:35:55 schwarze Exp $ */
+/* $Id: roff.c,v 1.281 2015/10/20 02:01:32 schwarze Exp $ */
/*
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -1007,6 +1007,11 @@ roff_node_append(struct roff_man *man, struct roff_node *n)
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;
@@ -1014,12 +1019,12 @@ roff_node_append(struct roff_man *man, struct roff_node *n)
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
@@ -1072,7 +1077,7 @@ roff_word_alloc(struct roff_man *man, int line, int pos, const char *word)
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;
@@ -1160,7 +1165,7 @@ roff_addtbl(struct roff_man *man, const struct tbl_span *tbl)
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;
diff --git a/roff_int.h b/roff_int.h
index 8a9591e4..a0794f1b 100644
--- a/roff_int.h
+++ b/roff_int.h
@@ -1,4 +1,4 @@
-/* $Id: roff_int.h,v 1.3 2015/04/19 14:57:38 schwarze Exp $ */
+/* $Id: roff_int.h,v 1.4 2015/10/20 02:01:32 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -43,7 +43,6 @@ void man_breakscope(struct roff_man *, int);
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