-/* $Id: man_validate.c,v 1.85 2012/11/17 00:26:33 schwarze Exp $ */
+/* $Id: man_validate.c,v 1.96 2014/07/02 11:43:20 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010, 2012 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
#include "man.h"
#include "mandoc.h"
+#include "mandoc_aux.h"
#include "libman.h"
#include "libmandoc.h"
static int check_le1(CHKARGS);
static int check_ge2(CHKARGS);
static int check_le5(CHKARGS);
+static int check_head1(CHKARGS);
static int check_par(CHKARGS);
static int check_part(CHKARGS);
static int check_root(CHKARGS);
static v_check posts_sp[] = { post_vs, check_le1, NULL };
static v_check posts_th[] = { check_ge2, check_le5, post_TH, NULL };
static v_check posts_uc[] = { post_UC, NULL };
+static v_check posts_ur[] = { check_head1, check_part, NULL };
static v_check pres_sec[] = { pre_sec, NULL };
static const struct man_valid man_valids[MAN_MAX] = {
{ NULL, posts_eq2 }, /* OP */
{ NULL, posts_nf }, /* EX */
{ NULL, posts_fi }, /* EE */
+ { NULL, posts_ur }, /* UR */
+ { NULL, NULL }, /* UE */
+ { NULL, NULL }, /* ll */
};
v_check *cp;
switch (n->type) {
- case (MAN_TEXT):
+ case MAN_TEXT:
/* FALLTHROUGH */
- case (MAN_ROOT):
+ case MAN_ROOT:
/* FALLTHROUGH */
- case (MAN_EQN):
+ case MAN_EQN:
/* FALLTHROUGH */
- case (MAN_TBL):
+ case MAN_TBL:
return(1);
default:
break;
if (NULL == (cp = man_valids[n->tok].pres))
return(1);
for ( ; *cp; cp++)
- if ( ! (*cp)(man, n))
+ if ( ! (*cp)(man, n))
return(0);
return(1);
}
-
int
man_valid_post(struct man *man)
{
man->last->flags |= MAN_VALID;
switch (man->last->type) {
- case (MAN_TEXT):
+ case MAN_TEXT:
check_text(man, man->last);
return(1);
- case (MAN_ROOT):
+ case MAN_ROOT:
return(check_root(man, man->last));
- case (MAN_EQN):
+ case MAN_EQN:
/* FALLTHROUGH */
- case (MAN_TBL):
+ case MAN_TBL:
return(1);
default:
break;
return(1);
}
-
static int
-check_root(CHKARGS)
+check_root(CHKARGS)
{
if (MAN_BLINE & man->flags)
man->flags &= ~MAN_BLINE;
man->flags &= ~MAN_ELINE;
- if (NULL == man->first->child) {
- man_nmsg(man, n, MANDOCERR_NODOCBODY);
- return(0);
- } else if (NULL == man->meta.title) {
- man_nmsg(man, n, MANDOCERR_NOTITLE);
+ if (NULL == man->first->child)
+ man_nmsg(man, n, MANDOCERR_DOC_EMPTY);
+ else
+ man->meta.hasbody = 1;
+
+ if (NULL == man->meta.title) {
+ man_nmsg(man, n, MANDOCERR_TH_MISSING);
/*
* If a title hasn't been set, do so now (by
* implication, date and section also aren't set).
*/
- man->meta.title = mandoc_strdup("unknown");
+ man->meta.title = mandoc_strdup("unknown");
man->meta.msec = mandoc_strdup("1");
- man->meta.date = mandoc_normdate
- (man->parse, NULL, n->line, n->pos);
+ man->meta.date = man->quick ? mandoc_strdup("") :
+ mandoc_normdate(man->parse, NULL, n->line, n->pos);
}
return(1);
if (n->nchild ineq (x)) \
return(1); \
mandoc_vmsg(MANDOCERR_ARGCOUNT, man->parse, n->line, n->pos, \
- "line arguments %s %d (have %d)", \
- #ineq, (x), n->nchild); \
+ "line arguments %s %d (have %d)", \
+ #ineq, (x), n->nchild); \
return(1); \
}
INEQ_DEFINE(2, >=, ge2)
INEQ_DEFINE(5, <=, le5)
+static int
+check_head1(CHKARGS)
+{
+
+ if (MAN_HEAD == n->type && 1 != n->nchild)
+ mandoc_vmsg(MANDOCERR_ARGCOUNT, man->parse, n->line,
+ n->pos, "line arguments eq 1 (have %d)", n->nchild);
+
+ return(1);
+}
+
static int
post_ft(CHKARGS)
{
ok = 0;
cp = n->child->string;
switch (*cp) {
- case ('1'):
+ case '1':
/* FALLTHROUGH */
- case ('2'):
+ case '2':
/* FALLTHROUGH */
- case ('3'):
+ case '3':
/* FALLTHROUGH */
- case ('4'):
+ case '4':
/* FALLTHROUGH */
- case ('I'):
+ case 'I':
/* FALLTHROUGH */
- case ('P'):
+ case 'P':
/* FALLTHROUGH */
- case ('R'):
+ case 'R':
if ('\0' == cp[1])
ok = 1;
break;
- case ('B'):
+ case 'B':
if ('\0' == cp[1] || ('I' == cp[1] && '\0' == cp[2]))
ok = 1;
break;
- case ('C'):
+ case 'C':
if ('W' == cp[1] && '\0' == cp[2])
ok = 1;
break;
}
if (0 == ok) {
- mandoc_vmsg
- (MANDOCERR_BADFONT, man->parse,
- n->line, n->pos, "%s", cp);
+ mandoc_vmsg(MANDOCERR_BADFONT, man->parse, n->line,
+ n->pos, "%s", cp);
*cp = '\0';
}
if (1 < n->nchild)
- mandoc_vmsg
- (MANDOCERR_ARGCOUNT, man->parse, n->line,
- n->pos, "want one child (have %d)",
- n->nchild);
+ mandoc_vmsg(MANDOCERR_ARGCOUNT, man->parse, n->line,
+ n->pos, "want one child (have %d)", n->nchild);
return(1);
}
post_sec(CHKARGS)
{
- if ( ! (MAN_HEAD == n->type && 0 == n->nchild))
+ if ( ! (MAN_HEAD == n->type && 0 == n->nchild))
return(1);
man_nmsg(man, n, MANDOCERR_SYNTARGCOUNT);
{
if (MAN_BODY == n->type && 0 == n->nchild)
- mandoc_msg(MANDOCERR_ARGCWARN, man->parse, n->line,
- n->pos, "want children (have none)");
+ mandoc_msg(MANDOCERR_ARGCWARN, man->parse, n->line,
+ n->pos, "want children (have none)");
return(1);
}
-
static int
check_par(CHKARGS)
{
switch (n->type) {
- case (MAN_BLOCK):
+ case MAN_BLOCK:
if (0 == n->body->nchild)
man_node_delete(man, n);
break;
- case (MAN_BODY):
+ case MAN_BODY:
if (0 == n->nchild)
- man_nmsg(man, n, MANDOCERR_IGNPAR);
+ mandoc_vmsg(MANDOCERR_PAR_SKIP,
+ man->parse, n->line, n->pos,
+ "%s empty", man_macronames[n->tok]);
break;
- case (MAN_HEAD):
+ case MAN_HEAD:
if (n->nchild)
man_nmsg(man, n, MANDOCERR_ARGSLOST);
break;
{
switch (n->type) {
- case (MAN_BLOCK):
+ case MAN_BLOCK:
if (0 == n->head->nchild && 0 == n->body->nchild)
man_node_delete(man, n);
break;
- case (MAN_BODY):
+ case MAN_BODY:
if (0 == n->parent->head->nchild && 0 == n->nchild)
- man_nmsg(man, n, MANDOCERR_IGNPAR);
+ mandoc_vmsg(MANDOCERR_PAR_SKIP,
+ man->parse, n->line, n->pos,
+ "%s empty", man_macronames[n->tok]);
break;
default:
break;
static int
post_TH(CHKARGS)
{
+ struct man_node *nb;
const char *p;
- int line, pos;
free(man->meta.title);
free(man->meta.vol);
free(man->meta.msec);
free(man->meta.date);
- line = n->line;
- pos = n->pos;
man->meta.title = man->meta.vol = man->meta.date =
- man->meta.msec = man->meta.source = NULL;
+ man->meta.msec = man->meta.source = NULL;
+
+ nb = n;
/* ->TITLE<- MSEC DATE SOURCE VOL */
if (n && n->string) {
for (p = n->string; '\0' != *p; p++) {
/* Only warn about this once... */
- if (isalpha((unsigned char)*p) &&
- ! isupper((unsigned char)*p)) {
- man_nmsg(man, n, MANDOCERR_UPPERCASE);
+ if (isalpha((unsigned char)*p) &&
+ ! isupper((unsigned char)*p)) {
+ mandoc_msg(MANDOCERR_TITLE_CASE,
+ man->parse, n->line,
+ n->pos + (p - n->string),
+ n->string);
break;
}
}
if (n)
n = n->next;
if (n && n->string && '\0' != n->string[0]) {
- pos = n->pos;
- man->meta.date = mandoc_normdate
- (man->parse, n->string, line, pos);
- } else
+ man->meta.date = man->quick ?
+ mandoc_strdup(n->string) :
+ mandoc_normdate(man->parse, n->string,
+ n->line, n->pos);
+ } else {
man->meta.date = mandoc_strdup("");
+ man_nmsg(man, n ? n : nb, MANDOCERR_DATE_MISSING);
+ }
/* TITLE MSEC DATE ->SOURCE<- VOL */
{
if (MAN_LITERAL & man->flags)
- man_nmsg(man, n, MANDOCERR_SCOPEREP);
+ man_nmsg(man, n, MANDOCERR_NF_SKIP);
man->flags |= MAN_LITERAL;
return(1);
{
if ( ! (MAN_LITERAL & man->flags))
- man_nmsg(man, n, MANDOCERR_WNOSCOPE);
+ man_nmsg(man, n, MANDOCERR_FI_SKIP);
man->flags &= ~MAN_LITERAL;
return(1);
return(1);
switch (n->parent->tok) {
- case (MAN_SH):
+ case MAN_SH:
/* FALLTHROUGH */
- case (MAN_SS):
- man_nmsg(man, n, MANDOCERR_IGNPAR);
+ case MAN_SS:
+ mandoc_vmsg(MANDOCERR_PAR_SKIP, man->parse, n->line, n->pos,
+ "%s after %s", man_macronames[n->tok],
+ man_macronames[n->parent->tok]);
/* FALLTHROUGH */
- case (MAN_MAX):
- /*
+ case MAN_MAX:
+ /*
* Don't warn about this because it occurs in pod2man
* and would cause considerable (unfixable) warnage.
*/