summaryrefslogtreecommitdiffstats
path: root/mdoc_validate.c
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2017-01-11 17:39:53 +0000
committerIngo Schwarze <schwarze@openbsd.org>2017-01-11 17:39:53 +0000
commitb319284232133fdd31db9dc5894da706c99eda06 (patch)
tree83ab8d1f6f6dd343a1fc796d73b9551f8fafeb2c /mdoc_validate.c
parentf1073511b0d42c759d7f3aac33e0f567c69e7dfe (diff)
downloadmandoc-b319284232133fdd31db9dc5894da706c99eda06.tar.gz
Do text production for .Bt, .Ex, .Rv, .Ud at the validation stage
rather than in the formatters. Use NODE_NOSRC flag for .Lb and NODE_NOSRC and NODE_NOPRT for .St. Results in a more rigorous syntax tree and in 135 lines less code. This work was triggered by a question from Abhinav Upadhyay <er dot abhinav dot upadhyay at gmail dot com> (NetBSD) on discuss@.
Diffstat (limited to 'mdoc_validate.c')
-rw-r--r--mdoc_validate.c268
1 files changed, 187 insertions, 81 deletions
diff --git a/mdoc_validate.c b/mdoc_validate.c
index ed717511..885d6281 100644
--- a/mdoc_validate.c
+++ b/mdoc_validate.c
@@ -51,6 +51,7 @@ enum check_ineq {
typedef void (*v_post)(POST_ARGS);
+static int build_list(struct roff_man *, int);
static void check_text(struct roff_man *, int, int, char *);
static void check_argv(struct roff_man *,
struct roff_node *, struct mdoc_argv *);
@@ -95,6 +96,7 @@ static void post_par(POST_ARGS);
static void post_prevpar(POST_ARGS);
static void post_root(POST_ARGS);
static void post_rs(POST_ARGS);
+static void post_rv(POST_ARGS);
static void post_sh(POST_ARGS);
static void post_sh_head(POST_ARGS);
static void post_sh_name(POST_ARGS);
@@ -143,7 +145,7 @@ static v_post mdoc_valids[MDOC_MAX] = {
NULL, /* Op */
post_obsolete, /* Ot */
post_defaults, /* Pa */
- post_std, /* Rv */
+ post_rv, /* Rv */
post_st, /* St */
NULL, /* Va */
NULL, /* Vt */
@@ -621,6 +623,10 @@ post_bd(POST_ARGS)
}
}
+/*
+ * Stand-alone line macros.
+ */
+
static void
post_an_norm(POST_ARGS)
{
@@ -649,6 +655,158 @@ post_an_norm(POST_ARGS)
}
static void
+post_eoln(POST_ARGS)
+{
+ struct roff_node *n;
+
+ n = mdoc->last;
+ if (n->child != NULL)
+ mandoc_vmsg(MANDOCERR_ARG_SKIP, mdoc->parse,
+ n->line, n->pos, "%s %s",
+ mdoc_macronames[n->tok], n->child->string);
+
+ while (n->child != NULL)
+ roff_node_delete(mdoc, n->child);
+
+ roff_word_alloc(mdoc, n->line, n->pos, n->tok == MDOC_Bt ?
+ "is currently in beta test." : "currently under development.");
+ mdoc->last->flags |= NODE_EOS | NODE_NOSRC;
+ mdoc->last = n;
+}
+
+static int
+build_list(struct roff_man *mdoc, int tok)
+{
+ struct roff_node *n;
+ int ic;
+
+ n = mdoc->last->next;
+ for (ic = 1;; ic++) {
+ roff_elem_alloc(mdoc, n->line, n->pos, tok);
+ mdoc->last->flags |= NODE_NOSRC;
+ mdoc_node_relink(mdoc, n);
+ n = mdoc->last = mdoc->last->parent;
+ mdoc->next = ROFF_NEXT_SIBLING;
+ if (n->next == NULL)
+ return ic;
+ if (ic > 1 || n->next->next != NULL) {
+ roff_word_alloc(mdoc, n->line, n->pos, ",");
+ mdoc->last->flags |= NODE_DELIMC | NODE_NOSRC;
+ }
+ n = mdoc->last->next;
+ if (n->next == NULL) {
+ roff_word_alloc(mdoc, n->line, n->pos, "and");
+ mdoc->last->flags |= NODE_NOSRC;
+ }
+ }
+}
+
+static void
+post_ex(POST_ARGS)
+{
+ struct roff_node *n;
+ int ic;
+
+ post_std(mdoc);
+
+ n = mdoc->last;
+ mdoc->next = ROFF_NEXT_CHILD;
+ roff_word_alloc(mdoc, n->line, n->pos, "The");
+ mdoc->last->flags |= NODE_NOSRC;
+
+ if (mdoc->last->next != NULL)
+ ic = build_list(mdoc, MDOC_Nm);
+ else if (mdoc->meta.name != NULL) {
+ roff_elem_alloc(mdoc, n->line, n->pos, MDOC_Nm);
+ mdoc->last->flags |= NODE_NOSRC;
+ roff_word_alloc(mdoc, n->line, n->pos, mdoc->meta.name);
+ mdoc->last->flags |= NODE_NOSRC;
+ mdoc->last = mdoc->last->parent;
+ mdoc->next = ROFF_NEXT_SIBLING;
+ ic = 1;
+ } else {
+ mandoc_msg(MANDOCERR_EX_NONAME, mdoc->parse,
+ n->line, n->pos, "Ex");
+ ic = 0;
+ }
+
+ roff_word_alloc(mdoc, n->line, n->pos,
+ ic > 1 ? "utilities exit\\~0" : "utility exits\\~0");
+ mdoc->last->flags |= NODE_NOSRC;
+ roff_word_alloc(mdoc, n->line, n->pos,
+ "on success, and\\~>0 if an error occurs.");
+ mdoc->last->flags |= NODE_EOS | NODE_NOSRC;
+ mdoc->last = n;
+}
+
+static void
+post_lb(POST_ARGS)
+{
+ struct roff_node *n;
+ const char *p;
+
+ n = mdoc->last;
+ assert(n->child->type == ROFFT_TEXT);
+ mdoc->next = ROFF_NEXT_CHILD;
+
+ if ((p = mdoc_a2lib(n->child->string)) != NULL) {
+ n->child->flags |= NODE_NOPRT;
+ roff_word_alloc(mdoc, n->line, n->pos, p);
+ mdoc->last->flags = NODE_NOSRC;
+ mdoc->last = n;
+ return;
+ }
+
+ roff_word_alloc(mdoc, n->line, n->pos, "library");
+ mdoc->last->flags = NODE_NOSRC;
+ roff_word_alloc(mdoc, n->line, n->pos, "\\(Lq");
+ mdoc->last->flags = NODE_DELIMO | NODE_NOSRC;
+ mdoc->last = mdoc->last->next;
+ roff_word_alloc(mdoc, n->line, n->pos, "\\(Rq");
+ mdoc->last->flags = NODE_DELIMC | NODE_NOSRC;
+ mdoc->last = n;
+}
+
+static void
+post_rv(POST_ARGS)
+{
+ struct roff_node *n;
+ int ic;
+
+ post_std(mdoc);
+
+ n = mdoc->last;
+ mdoc->next = ROFF_NEXT_CHILD;
+ if (n->child != NULL) {
+ roff_word_alloc(mdoc, n->line, n->pos, "The");
+ mdoc->last->flags |= NODE_NOSRC;
+ ic = build_list(mdoc, MDOC_Fn);
+ roff_word_alloc(mdoc, n->line, n->pos,
+ ic > 1 ? "functions return" : "function returns");
+ mdoc->last->flags |= NODE_NOSRC;
+ roff_word_alloc(mdoc, n->line, n->pos,
+ "the value\\~0 if successful;");
+ } else
+ roff_word_alloc(mdoc, n->line, n->pos, "Upon successful "
+ "completion, the value\\~0 is returned;");
+ mdoc->last->flags |= NODE_NOSRC;
+
+ roff_word_alloc(mdoc, n->line, n->pos, "otherwise "
+ "the value\\~\\-1 is returned and the global variable");
+ mdoc->last->flags |= NODE_NOSRC;
+ roff_elem_alloc(mdoc, n->line, n->pos, MDOC_Va);
+ mdoc->last->flags |= NODE_NOSRC;
+ roff_word_alloc(mdoc, n->line, n->pos, "errno");
+ mdoc->last->flags |= NODE_NOSRC;
+ mdoc->last = mdoc->last->parent;
+ mdoc->next = ROFF_NEXT_SIBLING;
+ roff_word_alloc(mdoc, n->line, n->pos,
+ "is set to indicate the error.");
+ mdoc->last->flags |= NODE_EOS | NODE_NOSRC;
+ mdoc->last = n;
+}
+
+static void
post_std(POST_ARGS)
{
struct roff_node *n;
@@ -663,6 +821,30 @@ post_std(POST_ARGS)
}
static void
+post_st(POST_ARGS)
+{
+ struct roff_node *n, *nch;
+ const char *p;
+
+ n = mdoc->last;
+ nch = n->child;
+ assert(nch->type == ROFFT_TEXT);
+
+ if ((p = mdoc_a2st(nch->string)) == NULL) {
+ mandoc_vmsg(MANDOCERR_ST_BAD, mdoc->parse,
+ nch->line, nch->pos, "St %s", nch->string);
+ roff_node_delete(mdoc, n);
+ return;
+ }
+
+ nch->flags |= NODE_NOPRT;
+ mdoc->next = ROFF_NEXT_CHILD;
+ roff_word_alloc(mdoc, nch->line, nch->pos, p);
+ mdoc->last->flags |= NODE_NOSRC;
+ mdoc->last= n;
+}
+
+static void
post_obsolete(POST_ARGS)
{
struct roff_node *n;
@@ -673,6 +855,10 @@ post_obsolete(POST_ARGS)
n->line, n->pos, mdoc_macronames[n->tok]);
}
+/*
+ * Block macros.
+ */
+
static void
post_bf(POST_ARGS)
{
@@ -739,39 +925,6 @@ post_bf(POST_ARGS)
}
static void
-post_lb(POST_ARGS)
-{
- struct roff_node *n;
- const char *stdlibname;
- char *libname;
-
- n = mdoc->last->child;
- assert(n->type == ROFFT_TEXT);
-
- if (NULL == (stdlibname = mdoc_a2lib(n->string)))
- mandoc_asprintf(&libname,
- "library \\(Lq%s\\(Rq", n->string);
- else
- libname = mandoc_strdup(stdlibname);
-
- free(n->string);
- n->string = libname;
-}
-
-static void
-post_eoln(POST_ARGS)
-{
- const struct roff_node *n;
-
- n = mdoc->last;
- if (n->child != NULL)
- mandoc_vmsg(MANDOCERR_ARG_SKIP,
- mdoc->parse, n->line, n->pos,
- "%s %s", mdoc_macronames[n->tok],
- n->child->string);
-}
-
-static void
post_fname(POST_ARGS)
{
const struct roff_node *n;
@@ -1449,27 +1602,6 @@ post_root(POST_ARGS)
}
static void
-post_st(POST_ARGS)
-{
- struct roff_node *n, *nch;
- const char *p;
-
- n = mdoc->last;
- nch = n->child;
-
- assert(nch->type == ROFFT_TEXT);
-
- if ((p = mdoc_a2st(nch->string)) == NULL) {
- mandoc_vmsg(MANDOCERR_ST_BAD, mdoc->parse,
- nch->line, nch->pos, "St %s", nch->string);
- roff_node_delete(mdoc, n);
- } else {
- free(nch->string);
- nch->string = mandoc_strdup(p);
- }
-}
-
-static void
post_rs(POST_ARGS)
{
struct roff_node *np, *nch, *next, *prev;
@@ -2203,32 +2335,6 @@ post_os(POST_ARGS)
#endif /*!OSNAME*/
}
-/*
- * If no argument is provided,
- * fill in the name of the current manual page.
- */
-static void
-post_ex(POST_ARGS)
-{
- struct roff_node *n;
-
- post_std(mdoc);
-
- n = mdoc->last;
- if (n->child != NULL)
- return;
-
- if (mdoc->meta.name == NULL) {
- mandoc_msg(MANDOCERR_EX_NONAME, mdoc->parse,
- n->line, n->pos, "Ex");
- return;
- }
-
- mdoc->next = ROFF_NEXT_CHILD;
- roff_word_alloc(mdoc, n->line, n->pos, mdoc->meta.name);
- mdoc->last = n;
-}
-
enum roff_sec
mdoc_a2sec(const char *p)
{