=================================================================== RCS file: /cvs/mandoc/mdoc_validate.c,v retrieving revision 1.124 retrieving revision 1.127 diff -u -p -r1.124 -r1.127 --- mandoc/mdoc_validate.c 2010/11/29 13:12:24 1.124 +++ mandoc/mdoc_validate.c 2010/11/29 14:56:43 1.127 @@ -1,4 +1,4 @@ -/* $Id: mdoc_validate.c,v 1.124 2010/11/29 13:12:24 kristaps Exp $ */ +/* $Id: mdoc_validate.c,v 1.127 2010/11/29 14:56:43 kristaps Exp $ */ /* * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons * @@ -112,7 +112,7 @@ static int pre_sh(PRE_ARGS); static int pre_ss(PRE_ARGS); static v_post posts_an[] = { post_an, NULL }; -static v_post posts_at[] = { post_at, NULL }; +static v_post posts_at[] = { post_at, post_defaults, NULL }; static v_post posts_bd_bk[] = { hwarn_eq0, bwarn_ge1, NULL }; static v_post posts_bf[] = { hwarn_le1, post_bf, NULL }; static v_post posts_bl[] = { bwarn_ge1, post_bl, NULL }; @@ -1077,17 +1077,38 @@ post_bf(POST_ARGS) return(1); } - static int post_lb(POST_ARGS) { + const char *p; + char *buf; + size_t sz; - if (mdoc_a2lib(mdoc->last->child->string)) + assert(mdoc->last->child); + assert(MDOC_TEXT == mdoc->last->child->type); + + p = mdoc_a2lib(mdoc->last->child->string); + + /* If lookup ok, replace with table value. */ + + if (p) { + free(mdoc->last->child->string); + mdoc->last->child->string = mandoc_strdup(p); return(1); - return(mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADLIB)); -} + } + /* If not, use "library ``xxxx''. */ + sz = strlen(mdoc->last->child->string) + + 2 + strlen("\\(lqlibrary\\(rq"); + buf = mandoc_malloc(sz); + snprintf(buf, sz, "library \\(lq%s\\(rq", + mdoc->last->child->string); + free(mdoc->last->child->string); + mdoc->last->child->string = buf; + return(1); +} + static int post_eoln(POST_ARGS) { @@ -1159,6 +1180,12 @@ post_defaults(POST_ARGS) if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "...")) return(0); break; + case (MDOC_At): + if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "AT&T")) + return(0); + if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "UNIX")) + return(0); + break; case (MDOC_Li): if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "")) return(0); @@ -1179,16 +1206,40 @@ post_defaults(POST_ARGS) static int post_at(POST_ARGS) { + const char *p, *q; + char *buf; + size_t sz; + /* + * If we have a child, look it up in the standard keys. If a + * key exist, use that instead of the child; if it doesn't, + * prefix "AT&T UNIX " to the existing data. + */ + if (NULL == mdoc->last->child) return(1); + assert(MDOC_TEXT == mdoc->last->child->type); - if (mdoc_a2att(mdoc->last->child->string)) - return(1); - return(mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADATT)); -} + p = mdoc_a2att(mdoc->last->child->string); + if (p) { + free(mdoc->last->child->string); + mdoc->last->child->string = mandoc_strdup(p); + } else { + mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADATT); + p = "AT&T UNIX "; + q = mdoc->last->child->string; + sz = strlen(p) + strlen(q) + 1; + buf = mandoc_malloc(sz); + strlcpy(buf, p, sz); + strlcat(buf, q, sz); + free(mdoc->last->child->string); + mdoc->last->child->string = buf; + } + return(1); +} + static int post_an(POST_ARGS) { @@ -1544,34 +1595,33 @@ post_sh_body(POST_ARGS) static int post_sh_head(POST_ARGS) { - char buf[BUFSIZ]; - enum mdoc_sec sec; - const struct mdoc_node *n; + char buf[BUFSIZ]; + enum mdoc_sec sec; + struct mdoc_node *n; /* * Process a new section. Sections are either "named" or - * "custom"; custom sections are user-defined, while named ones - * usually follow a conventional order and may only appear in - * certain manual sections. + * "custom". Custom sections are user-defined, while named ones + * follow a conventional order and may only appear in certain + * manual sections. */ buf[0] = '\0'; - /* - * FIXME: yes, these can use a dynamic buffer, but I don't do so - * in the interests of simplicity. - */ + /* FIXME: use dynamic buffer... */ for (n = mdoc->last->child; n; n = n->next) { - /* XXX - copied from compact(). */ + /* XXX - copied from concat(). */ assert(MDOC_TEXT == n->type); if (strlcat(buf, n->string, BUFSIZ) >= BUFSIZ) { mdoc_nmsg(mdoc, n, MANDOCERR_MEM); return(0); } + if (NULL == n->next) continue; + if (strlcat(buf, " ", BUFSIZ) >= BUFSIZ) { mdoc_nmsg(mdoc, n, MANDOCERR_MEM); return(0); @@ -1580,41 +1630,60 @@ post_sh_head(POST_ARGS) sec = mdoc_str2sec(buf); - /* - * Check: NAME should always be first, CUSTOM has no roles, - * non-CUSTOM has a conventional order to be followed. - */ + /* The NAME should be first. */ if (SEC_NAME != sec && SEC_NONE == mdoc->lastnamed) - if ( ! mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NAMESECFIRST)) - return(0); + mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NAMESECFIRST); + /* The SYNOPSIS gets special attention in other areas. */ + + if (SEC_SYNOPSIS == sec) + mdoc->flags |= MDOC_SYNOPSIS; + else + mdoc->flags &= ~MDOC_SYNOPSIS; + + /* Mark our last section. */ + + mdoc->lastsec = sec; + + /* We don't care about custom sections after this. */ + if (SEC_CUSTOM == sec) return(1); + /* + * Check whether our non-custom section is being repeated or is + * out of order. + */ + if (sec == mdoc->lastnamed) - if ( ! mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_SECREP)) - return(0); + mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_SECREP); if (sec < mdoc->lastnamed) - if ( ! mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_SECOOO)) - return(0); + mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_SECOOO); - /* - * Check particular section/manual conventions. LIBRARY can - * only occur in manual section 2, 3, and 9. - */ + /* Mark the last named section. */ + mdoc->lastnamed = sec; + + /* Check particular section/manual conventions. */ + + assert(mdoc->meta.msec); + switch (sec) { + case (SEC_RETURN_VALUES): + /* FALLTHROUGH */ + case (SEC_ERRORS): + /* FALLTHROUGH */ case (SEC_LIBRARY): - assert(mdoc->meta.msec); if (*mdoc->meta.msec == '2') break; if (*mdoc->meta.msec == '3') break; if (*mdoc->meta.msec == '9') break; - return(mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_SECMSEC)); + mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_SECMSEC); + break; default: break; }