diff options
author | Ingo Schwarze <schwarze@openbsd.org> | 2014-08-06 15:09:05 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@openbsd.org> | 2014-08-06 15:09:05 +0000 |
commit | 24b160c265af79f44e54160d97249622ff07747a (patch) | |
tree | 6bab11dc37008079265c87f0b7d5ee5ad38955f6 | |
parent | 4e6374f6dccb1f26d1d9efc07a9ce9c9c600c3e7 (diff) | |
download | mandoc-24b160c265af79f44e54160d97249622ff07747a.tar.gz |
Bring the handling of defective prologues even closer to groff,
in particular relaxing the distinction between prologue and body
and further improving messages.
* The last .Dd wins and the last .Os wins, even in the body.
* The last .Dt before the first body macro wins.
* Missing title in .Dt defaults to UNTITLED. Warn about it.
* Missing section in .Dt does not default to 1. But warn about it.
* Do not warn multiple times about the same mdoc(7) prologue macro.
* Warn about missing .Os.
* Incomplete .TH defaults to empty strings. Warn about it.
-rw-r--r-- | man_validate.c | 19 | ||||
-rw-r--r-- | mandoc.h | 11 | ||||
-rw-r--r-- | mandocdb.c | 5 | ||||
-rw-r--r-- | mdoc.c | 59 | ||||
-rw-r--r-- | mdoc_html.c | 11 | ||||
-rw-r--r-- | mdoc_man.c | 5 | ||||
-rw-r--r-- | mdoc_term.c | 6 | ||||
-rw-r--r-- | mdoc_validate.c | 152 | ||||
-rw-r--r-- | read.c | 11 |
9 files changed, 137 insertions, 142 deletions
diff --git a/man_validate.c b/man_validate.c index 2091840d..76aebe1c 100644 --- a/man_validate.c +++ b/man_validate.c @@ -43,7 +43,6 @@ typedef int (*v_check)(CHKARGS); static int check_eq0(CHKARGS); static int check_eq2(CHKARGS); static int check_le1(CHKARGS); -static int check_ge2(CHKARGS); static int check_le5(CHKARGS); static int check_par(CHKARGS); static int check_part(CHKARGS); @@ -142,7 +141,7 @@ check_root(CHKARGS) man->meta.hasbody = 1; if (NULL == man->meta.title) { - mandoc_msg(MANDOCERR_TH_MISSING, man->parse, + mandoc_msg(MANDOCERR_TH_NOTITLE, man->parse, n->line, n->pos, NULL); /* @@ -150,8 +149,8 @@ check_root(CHKARGS) * implication, date and section also aren't set). */ - man->meta.title = mandoc_strdup("unknown"); - man->meta.msec = mandoc_strdup("1"); + man->meta.title = mandoc_strdup(""); + man->meta.msec = mandoc_strdup(""); man->meta.date = man->quick ? mandoc_strdup("") : mandoc_normdate(man->parse, NULL, n->line, n->pos); } @@ -189,7 +188,6 @@ check_##name(CHKARGS) \ INEQ_DEFINE(0, ==, eq0) INEQ_DEFINE(2, ==, eq2) INEQ_DEFINE(1, <=, le1) -INEQ_DEFINE(2, >=, ge2) INEQ_DEFINE(5, <=, le5) static int @@ -324,7 +322,6 @@ post_TH(CHKARGS) struct man_node *nb; const char *p; - check_ge2(man, n); check_le5(man, n); free(man->meta.title); @@ -354,8 +351,11 @@ post_TH(CHKARGS) } } man->meta.title = mandoc_strdup(n->string); - } else + } else { man->meta.title = mandoc_strdup(""); + mandoc_msg(MANDOCERR_TH_NOTITLE, man->parse, + nb->line, nb->pos, "TH"); + } /* TITLE ->MSEC<- DATE SOURCE VOL */ @@ -363,8 +363,11 @@ post_TH(CHKARGS) n = n->next; if (n && n->string) man->meta.msec = mandoc_strdup(n->string); - else + else { man->meta.msec = mandoc_strdup(""); + mandoc_vmsg(MANDOCERR_MSEC_MISSING, man->parse, + nb->line, nb->pos, "TH %s", man->meta.title); + } /* TITLE MSEC ->DATE<- SOURCE VOL */ @@ -49,16 +49,19 @@ enum mandocerr { MANDOCERR_WARNING, /* ===== start of warnings ===== */ /* related to the prologue */ - MANDOCERR_TH_MISSING, /* missing .TH macro, using "unknown 1" */ + MANDOCERR_DT_NOTITLE, /* missing manual title, using UNTITLED: line */ + MANDOCERR_TH_NOTITLE, /* missing manual title, using "": [macro] */ MANDOCERR_TITLE_CASE, /* lower case character in document title */ + MANDOCERR_MSEC_MISSING, /* missing manual section, using "": macro */ MANDOCERR_MSEC_BAD, /* unknown manual section: Dt ... section */ MANDOCERR_ARCH_BAD, /* unknown manual volume or arch: Dt ... volume */ MANDOCERR_DATE_MISSING, /* missing date, using today's date */ MANDOCERR_DATE_BAD, /* cannot parse date, using it verbatim: date */ - MANDOCERR_PROLOG_ORDER, /* prologue macros out of order: macro */ + MANDOCERR_OS_MISSING, /* missing Os macro, using "" */ MANDOCERR_PROLOG_REP, /* duplicate prologue macro: macro */ - MANDOCERR_PROLOG_BAD, /* incomplete prologue, terminated by: macro */ - MANDOCERR_PROLOG_ONLY, /* skipping prologue macro in body: macro */ + MANDOCERR_PROLOG_LATE, /* late prologue macro: macro */ + MANDOCERR_DT_LATE, /* skipping late title macro: Dt args */ + MANDOCERR_PROLOG_ORDER, /* prologue macros out of order: macros */ /* related to document structure */ MANDOCERR_SO, /* .so is fragile, better use ln(1): so path */ @@ -1198,8 +1198,9 @@ mpages_merge(struct mchars *mc, struct mparse *mp) goto nextpage; } else if (NULL != mdoc) { mpage->form = FORM_SRC; - mpage->sec = - mandoc_strdup(mdoc_meta(mdoc)->msec); + mpage->sec = mdoc_meta(mdoc)->msec; + mpage->sec = mandoc_strdup( + NULL == mpage->sec ? "" : mpage->sec); mpage->arch = mdoc_meta(mdoc)->arch; mpage->arch = mandoc_strdup( NULL == mpage->arch ? "" : mpage->arch); @@ -123,20 +123,13 @@ mdoc_free1(struct mdoc *mdoc) if (mdoc->first) mdoc_node_delete(mdoc, mdoc->first); - if (mdoc->meta.title) - free(mdoc->meta.title); - if (mdoc->meta.os) - free(mdoc->meta.os); - if (mdoc->meta.name) - free(mdoc->meta.name); - if (mdoc->meta.arch) - free(mdoc->meta.arch); - if (mdoc->meta.vol) - free(mdoc->meta.vol); - if (mdoc->meta.msec) - free(mdoc->meta.msec); - if (mdoc->meta.date) - free(mdoc->meta.date); + free(mdoc->meta.msec); + free(mdoc->meta.vol); + free(mdoc->meta.arch); + free(mdoc->meta.date); + free(mdoc->meta.title); + free(mdoc->meta.os); + free(mdoc->meta.name); } /* @@ -271,32 +264,22 @@ mdoc_macro(MACRO_PROT_ARGS) { assert(tok < MDOC_MAX); - /* If we're in the body, deny prologue calls. */ - - if (MDOC_PROLOGUE & mdoc_macros[tok].flags && - MDOC_PBODY & mdoc->flags) { - mandoc_vmsg(MANDOCERR_PROLOG_ONLY, mdoc->parse, - line, ppos, "%s", mdoc_macronames[tok]); - return(1); - } - - /* If we're in the prologue, deny "body" macros. */ - - if ( ! (MDOC_PROLOGUE & mdoc_macros[tok].flags) && - ! (MDOC_PBODY & mdoc->flags)) { - mandoc_vmsg(MANDOCERR_PROLOG_BAD, mdoc->parse, - line, ppos, "%s", mdoc_macronames[tok]); - if (NULL == mdoc->meta.msec) - mdoc->meta.msec = mandoc_strdup("1"); - if (NULL == mdoc->meta.title) - mdoc->meta.title = mandoc_strdup("UNKNOWN"); + if (mdoc->flags & MDOC_PBODY) { + if (tok == MDOC_Dt) { + mandoc_vmsg(MANDOCERR_DT_LATE, + mdoc->parse, line, ppos, + "Dt %s", buf + *pos); + return(1); + } + } 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"); - if (NULL == mdoc->meta.os) - mdoc->meta.os = mandoc_strdup("LOCAL"); - if (NULL == mdoc->meta.date) - mdoc->meta.date = mandoc_normdate - (mdoc->parse, NULL, line, ppos); mdoc->flags |= MDOC_PBODY; } diff --git a/mdoc_html.c b/mdoc_html.c index 43ff1d27..328cb9bc 100644 --- a/mdoc_html.c +++ b/mdoc_html.c @@ -380,8 +380,9 @@ print_mdoc_head(MDOC_ARGS) print_gen_head(h); bufinit(h); - bufcat_fmt(h, "%s(%s)", meta->title, meta->msec); - + bufcat(h, meta->title); + if (meta->msec) + bufcat_fmt(h, "(%s)", meta->msec); if (meta->arch) bufcat_fmt(h, " (%s)", meta->arch); @@ -525,7 +526,11 @@ mdoc_root_pre(MDOC_ARGS) mandoc_asprintf(&volume, "%s (%s)", meta->vol, meta->arch); - mandoc_asprintf(&title, "%s(%s)", meta->title, meta->msec); + if (NULL == meta->msec) + title = mandoc_strdup(meta->title); + else + mandoc_asprintf(&title, "%s(%s)", + meta->title, meta->msec); PAIR_SUMMARY_INIT(&tag[0], "Document Header"); PAIR_CLASS_INIT(&tag[1], "head"); @@ -548,8 +548,9 @@ man_mdoc(void *arg, const struct mdoc *mdoc) n = mdoc_node(mdoc); printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n", - meta->title, meta->msec, meta->date, - meta->os, meta->vol); + meta->title, + (meta->msec == NULL ? "" : meta->msec), + meta->date, meta->os, meta->vol); /* Disable hyphenation and if nroff, disable justification. */ printf(".nh\n.if n .ad l"); diff --git a/mdoc_term.c b/mdoc_term.c index ea34908c..9cb6e8e0 100644 --- a/mdoc_term.c +++ b/mdoc_term.c @@ -476,7 +476,11 @@ print_mdoc_head(struct termp *p, const void *arg) meta->vol, meta->arch); vollen = term_strlen(p, volume); - mandoc_asprintf(&title, "%s(%s)", meta->title, meta->msec); + if (NULL == meta->msec) + title = mandoc_strdup(meta->title); + else + mandoc_asprintf(&title, "%s(%s)", + meta->title, meta->msec); titlen = term_strlen(p, title); p->flags |= TERMP_NOBREAK | TERMP_NOSPACE; diff --git a/mdoc_validate.c b/mdoc_validate.c index 47dd6c39..a7fd30bf 100644 --- a/mdoc_validate.c +++ b/mdoc_validate.c @@ -114,7 +114,6 @@ static int post_nm(POST_ARGS); static int post_ns(POST_ARGS); static int post_os(POST_ARGS); static int post_par(POST_ARGS); -static int post_prol(POST_ARGS); static int post_root(POST_ARGS); static int post_rs(POST_ARGS); static int post_sh(POST_ARGS); @@ -843,14 +842,12 @@ static int pre_dt(PRE_ARGS) { - if (NULL == mdoc->meta.date || mdoc->meta.os) - mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse, - n->line, n->pos, "Dt"); - - if (mdoc->meta.title) + 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"); return(1); } @@ -858,14 +855,12 @@ static int pre_os(PRE_ARGS) { - if (NULL == mdoc->meta.title || NULL == mdoc->meta.date) - mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse, - n->line, n->pos, "Os"); - - if (mdoc->meta.os) + 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"); return(1); } @@ -873,14 +868,18 @@ static int pre_dd(PRE_ARGS) { - if (mdoc->meta.title || mdoc->meta.os) - mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse, - n->line, n->pos, "Dd"); - - if (mdoc->meta.date) + 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"); return(1); } @@ -1627,20 +1626,24 @@ post_root(POST_ARGS) /* Add missing prologue data. */ - if ( ! (MDOC_PBODY & mdoc->flags)) { - mandoc_msg(MANDOCERR_PROLOG_BAD, mdoc->parse, 0, 0, "EOF"); - if (mdoc->meta.date == NULL) - mdoc->meta.date = mdoc->quick ? - mandoc_strdup("") : - mandoc_normdate(mdoc->parse, NULL, 0, 0); - if (mdoc->meta.title == NULL) - mdoc->meta.title = mandoc_strdup("UNKNOWN"); - if (mdoc->meta.vol == NULL) - mdoc->meta.vol = mandoc_strdup("LOCAL"); - if (mdoc->meta.arch == NULL) - mdoc->meta.msec = mandoc_strdup("1"); - if (mdoc->meta.os == NULL) - mdoc->meta.os = mandoc_strdup("UNKNOWN"); + if (mdoc->meta.date == NULL) + mdoc->meta.date = mdoc->quick ? + mandoc_strdup("") : + mandoc_normdate(mdoc->parse, NULL, 0, 0); + + if (mdoc->meta.title == NULL) { + mandoc_msg(MANDOCERR_DT_NOTITLE, + mdoc->parse, 0, 0, "EOF"); + mdoc->meta.title = mandoc_strdup("UNTITLED"); + } + + if (mdoc->meta.vol == NULL) + mdoc->meta.vol = mandoc_strdup("LOCAL"); + + if (mdoc->meta.os == NULL) { + mandoc_msg(MANDOCERR_OS_MISSING, + mdoc->parse, 0, 0, NULL); + mdoc->meta.os = mandoc_strdup(""); } n = mdoc->first; @@ -1977,7 +1980,10 @@ post_sh_head(POST_ARGS) /* Check particular section/manual conventions. */ - assert(mdoc->meta.msec); + if (mdoc->meta.msec == NULL) { + free(secname); + return(1); + } goodsec = NULL; switch (sec) { @@ -2156,7 +2162,7 @@ post_dd(POST_ARGS) if (NULL == n->child || '\0' == n->child->string[0]) { mdoc->meta.date = mdoc->quick ? mandoc_strdup("") : mandoc_normdate(mdoc->parse, NULL, n->line, n->pos); - return(post_prol(mdoc)); + goto out; } datestr = NULL; @@ -2168,7 +2174,9 @@ post_dd(POST_ARGS) datestr, n->line, n->pos); free(datestr); } - return(post_prol(mdoc)); +out: + mdoc_node_delete(mdoc, n); + return(1); } static int @@ -2180,14 +2188,15 @@ post_dt(POST_ARGS) n = mdoc->last; - if (mdoc->meta.title) - free(mdoc->meta.title); - if (mdoc->meta.vol) - free(mdoc->meta.vol); - if (mdoc->meta.arch) - free(mdoc->meta.arch); + free(mdoc->meta.title); + free(mdoc->meta.msec); + free(mdoc->meta.vol); + free(mdoc->meta.arch); - mdoc->meta.title = mdoc->meta.vol = mdoc->meta.arch = NULL; + mdoc->meta.title = NULL; + mdoc->meta.msec = NULL; + mdoc->meta.vol = NULL; + mdoc->meta.arch = NULL; /* First check that all characters are uppercase. */ @@ -2202,32 +2211,27 @@ post_dt(POST_ARGS) break; } - /* Handles: `.Dt' - * title = unknown, volume = local, msec = 0, arch = NULL - */ + /* No argument: msec and arch remain NULL. */ if (NULL == (nn = n->child)) { - /* XXX: make these macro values. */ - /* FIXME: warn about missing values. */ - mdoc->meta.title = mandoc_strdup("UNKNOWN"); + mandoc_msg(MANDOCERR_DT_NOTITLE, + mdoc->parse, n->line, n->pos, "Dt"); + mdoc->meta.title = mandoc_strdup("UNTITLED"); mdoc->meta.vol = mandoc_strdup("LOCAL"); - mdoc->meta.msec = mandoc_strdup("1"); - return(post_prol(mdoc)); + goto out; } - /* Handles: `.Dt TITLE' - * title = TITLE, volume = local, msec = 0, arch = NULL - */ + /* One argument: msec and arch remain NULL. */ mdoc->meta.title = mandoc_strdup( - '\0' == nn->string[0] ? "UNKNOWN" : nn->string); + '\0' == nn->string[0] ? "UNTITLED" : nn->string); if (NULL == (nn = nn->next)) { - /* FIXME: warn about missing msec. */ - /* XXX: make this a macro value. */ + mandoc_vmsg(MANDOCERR_MSEC_MISSING, + mdoc->parse, n->line, n->pos, + "Dt %s", mdoc->meta.title); mdoc->meta.vol = mandoc_strdup("LOCAL"); - mdoc->meta.msec = mandoc_strdup("1"); - return(post_prol(mdoc)); + goto out; } /* Handles: `.Dt TITLE SEC' @@ -2249,7 +2253,7 @@ post_dt(POST_ARGS) } if (NULL == (nn = nn->next)) - return(post_prol(mdoc)); + goto out; /* Handles: `.Dt TITLE SEC VOL' * title = TITLE, @@ -2275,23 +2279,8 @@ post_dt(POST_ARGS) /* Ignore any subsequent parameters... */ /* FIXME: warn about subsequent parameters. */ - - return(post_prol(mdoc)); -} - -static int -post_prol(POST_ARGS) -{ - /* - * Remove prologue macros from the document after they're - * processed. The final document uses mdoc_meta for these - * values and discards the originals. - */ - - mdoc_node_delete(mdoc, mdoc->last); - if (mdoc->meta.title && mdoc->meta.date && mdoc->meta.os) - mdoc->flags |= MDOC_PBODY; - +out: + mdoc_node_delete(mdoc, n); return(1); } @@ -2337,11 +2326,11 @@ post_os(POST_ARGS) mdoc->meta.os = NULL; mdoc_deroff(&mdoc->meta.os, n); if (mdoc->meta.os) - return(post_prol(mdoc)); + goto out; if (mdoc->defos) { mdoc->meta.os = mandoc_strdup(mdoc->defos); - return(post_prol(mdoc)); + goto out; } #ifdef OSNAME @@ -2358,7 +2347,10 @@ post_os(POST_ARGS) } mdoc->meta.os = mandoc_strdup(defbuf); #endif /*!OSNAME*/ - return(post_prol(mdoc)); + +out: + mdoc_node_delete(mdoc, n); + return(1); } /* @@ -93,16 +93,19 @@ static const char * const mandocerrs[MANDOCERR_MAX] = { "generic warning", /* related to the prologue */ - "missing .TH macro, using \"unknown 1\"", + "missing manual title, using UNTITLED", + "missing manual title, using \"\"", "lower case character in document title", + "missing manual section, using \"\"", "unknown manual section", "unknown manual volume or arch", "missing date, using today's date", "cannot parse date, using it verbatim", - "prologue macros out of order", + "missing Os macro, using \"\"", "duplicate prologue macro", - "incomplete prologue, terminated by", - "skipping prologue macro in body", + "late prologue macro", + "skipping late title macro", + "prologue macros out of order", /* related to document structure */ ".so is fragile, better use ln(1)", |