source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* mdocml: In order to become able to generate syntax tree nodes on the
@ 2015-10-20  2:02 schwarze
  0 siblings, 0 replies; only message in thread
From: schwarze @ 2015-10-20  2:02 UTC (permalink / raw)
  To: source

Log Message:
-----------
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.

Modified Files:
--------------
    mdocml:
        Makefile
        Makefile.depend
        cgi.c
        demandoc.c
        libmdoc.h
        main.c
        mandocdb.c
        mdoc.c
        mdoc.h
        mdoc_macro.c
        mdoc_validate.c
        roff.c
        roff_int.h

Added Files:
-----------
    mdocml:
        mdoc_state.c

Revision Data
-------------
Index: roff.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/roff.c,v
retrieving revision 1.280
retrieving revision 1.281
diff -Lroff.c -Lroff.c -u -p -r1.280 -r1.281
--- roff.c
+++ roff.c
@@ -1007,6 +1007,11 @@ roff_node_append(struct roff_man *man, s
 
 	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, s
 	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, in
 	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 
 	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;
Index: cgi.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/cgi.c,v
retrieving revision 1.110
retrieving revision 1.111
diff -Lcgi.c -Lcgi.c -u -p -r1.110 -r1.111
--- cgi.c
+++ cgi.c
@@ -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
 
 	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);
Index: libmdoc.h
===================================================================
RCS file: /home/cvs/mdocml/mdocml/libmdoc.h,v
retrieving revision 1.106
retrieving revision 1.107
diff -Llibmdoc.h -Llibmdoc.h -u -p -r1.106 -r1.107
--- libmdoc.h
+++ libmdoc.h
@@ -73,11 +73,15 @@ void		  mdoc_tail_alloc(struct roff_man 
 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,
Index: mdoc.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc.c,v
retrieving revision 1.254
retrieving revision 1.255
diff -Lmdoc.c -Lmdoc.c -u -p -r1.254 -r1.255
--- mdoc.c
+++ mdoc.c
@@ -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 li
 		 * 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;
 	}
 
@@ -494,4 +476,13 @@ mdoc_isdelim(const char *p)
 		return DELIM_MIDDLE;
 
 	return DELIM_NONE;
+}
+
+void
+mdoc_validate(struct roff_man *mdoc)
+{
+
+	mdoc->last = mdoc->first;
+	mdoc_node_validate(mdoc);
+	mdoc_state_reset(mdoc);
 }
Index: mandocdb.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mandocdb.c,v
retrieving revision 1.203
retrieving revision 1.204
diff -Lmandocdb.c -Lmandocdb.c -u -p -r1.203 -r1.204
--- mandocdb.c
+++ mandocdb.c
@@ -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(
Index: mdoc_macro.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc_macro.c,v
retrieving revision 1.205
retrieving revision 1.206
diff -Lmdoc_macro.c -Lmdoc_macro.c -u -p -r1.205 -r1.206
--- mdoc_macro.c
+++ mdoc_macro.c
@@ -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, 
 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);
 }
 
 /*
Index: main.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/main.c,v
retrieving revision 1.250
retrieving revision 1.251
diff -Lmain.c -Lmain.c -u -p -r1.250 -r1.251
--- main.c
+++ main.c
@@ -696,6 +696,7 @@ parse(struct curparse *curp, int fd, con
 	if (man == NULL)
 		return;
 	if (man->macroset == MACROSET_MDOC) {
+		mdoc_validate(man);
 		switch (curp->outtype) {
 		case OUTT_HTML:
 			html_mdoc(curp->outdata, man);
Index: mdoc.h
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc.h,v
retrieving revision 1.142
retrieving revision 1.143
diff -Lmdoc.h -Lmdoc.h -u -p -r1.142 -r1.143
--- mdoc.h
+++ mdoc.h
@@ -279,3 +279,9 @@ extern	const char *const *mdoc_macroname
 
 /* Names of macro args.  Index is enum mdocargt. */
 extern	const char *const *mdoc_argnames;
+
+__BEGIN_DECLS
+
+void		 mdoc_validate(struct roff_man *);
+
+__END_DECLS
Index: mdoc_validate.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc_validate.c,v
retrieving revision 1.297
retrieving revision 1.298
diff -Lmdoc_validate.c -Lmdoc_validate.c -u -p -r1.297 -r1.298
--- mdoc_validate.c
+++ mdoc_validate.c
@@ -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, st
 }
 
 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;
 
Index: Makefile.depend
===================================================================
RCS file: /home/cvs/mdocml/mdocml/Makefile.depend,v
retrieving revision 1.17
retrieving revision 1.18
diff -LMakefile.depend -LMakefile.depend -u -p -r1.17 -r1.18
--- Makefile.depend
+++ 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_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
--- /dev/null
+++ 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;
+}
Index: demandoc.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/demandoc.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -Ldemandoc.c -Ldemandoc.c -u -p -r1.22 -r1.23
--- demandoc.c
+++ demandoc.c
@@ -119,9 +119,10 @@ pmandoc(struct mparse *mp, int fd, const
 
 	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)
Index: Makefile
===================================================================
RCS file: /home/cvs/mdocml/mdocml/Makefile,v
retrieving revision 1.469
retrieving revision 1.470
diff -LMakefile -LMakefile -u -p -r1.469 -r1.470
--- Makefile
+++ Makefile
@@ -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
 
Index: roff_int.h
===================================================================
RCS file: /home/cvs/mdocml/mdocml/roff_int.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -Lroff_int.h -Lroff_int.h -u -p -r1.3 -r1.4
--- roff_int.h
+++ roff_int.h
@@ -43,7 +43,6 @@ void		  man_breakscope(struct roff_man *
 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
--
 To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2015-10-20  2:02 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-20  2:02 mdocml: In order to become able to generate syntax tree nodes on the schwarze

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).