Print this page
Update to 1.12.3.

*** 1,9 **** ! /* $Id: man_validate.c,v 1.80 2012/01/03 15:16:24 kristaps Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> ! * Copyright (c) 2010 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. * --- 1,9 ---- ! /* $Id: man_validate.c,v 1.86 2013/10/17 20:54:58 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> ! * Copyright (c) 2010, 2012, 2013 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. *
*** 33,43 **** #include "man.h" #include "mandoc.h" #include "libman.h" #include "libmandoc.h" ! #define CHKARGS struct man *m, struct man_node *n typedef int (*v_check)(CHKARGS); struct man_valid { v_check *pres; --- 33,43 ---- #include "man.h" #include "mandoc.h" #include "libman.h" #include "libmandoc.h" ! #define CHKARGS struct man *man, struct man_node *n typedef int (*v_check)(CHKARGS); struct man_valid { v_check *pres;
*** 47,62 **** --- 47,64 ---- 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_head1(CHKARGS); static int check_par(CHKARGS); static int check_part(CHKARGS); static int check_root(CHKARGS); static void check_text(CHKARGS); static int post_AT(CHKARGS); + static int post_IP(CHKARGS); static int post_vs(CHKARGS); static int post_fi(CHKARGS); static int post_ft(CHKARGS); static int post_nf(CHKARGS); static int post_sec(CHKARGS);
*** 68,84 **** --- 70,89 ---- static v_check posts_br[] = { post_vs, check_eq0, NULL }; static v_check posts_eq0[] = { check_eq0, NULL }; static v_check posts_eq2[] = { check_eq2, NULL }; static v_check posts_fi[] = { check_eq0, post_fi, NULL }; static v_check posts_ft[] = { post_ft, NULL }; + static v_check posts_ip[] = { post_IP, NULL }; + static v_check posts_le1[] = { check_le1, NULL }; static v_check posts_nf[] = { check_eq0, post_nf, NULL }; static v_check posts_par[] = { check_par, NULL }; static v_check posts_part[] = { check_part, NULL }; static v_check posts_sec[] = { post_sec, NULL }; 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_br }, /* br */ { NULL, posts_th }, /* TH */
*** 86,96 **** { pres_sec, posts_sec }, /* SS */ { NULL, NULL }, /* TP */ { NULL, posts_par }, /* LP */ { NULL, posts_par }, /* PP */ { NULL, posts_par }, /* P */ ! { NULL, NULL }, /* IP */ { NULL, NULL }, /* HP */ { NULL, NULL }, /* SM */ { NULL, NULL }, /* SB */ { NULL, NULL }, /* BI */ { NULL, NULL }, /* IB */ --- 91,101 ---- { pres_sec, posts_sec }, /* SS */ { NULL, NULL }, /* TP */ { NULL, posts_par }, /* LP */ { NULL, posts_par }, /* PP */ { NULL, posts_par }, /* P */ ! { NULL, posts_ip }, /* IP */ { NULL, NULL }, /* HP */ { NULL, NULL }, /* SM */ { NULL, NULL }, /* SB */ { NULL, NULL }, /* BI */ { NULL, NULL }, /* IB */
*** 107,126 **** { NULL, posts_fi }, /* fi */ { NULL, NULL }, /* RE */ { NULL, posts_part }, /* RS */ { NULL, NULL }, /* DT */ { NULL, posts_uc }, /* UC */ ! { NULL, NULL }, /* PD */ { NULL, posts_at }, /* AT */ { NULL, NULL }, /* in */ { NULL, posts_ft }, /* ft */ { NULL, posts_eq2 }, /* OP */ }; int ! man_valid_pre(struct man *m, struct man_node *n) { v_check *cp; switch (n->type) { case (MAN_TEXT): --- 112,135 ---- { NULL, posts_fi }, /* fi */ { NULL, NULL }, /* RE */ { NULL, posts_part }, /* RS */ { NULL, NULL }, /* DT */ { NULL, posts_uc }, /* UC */ ! { NULL, posts_le1 }, /* PD */ { NULL, posts_at }, /* AT */ { NULL, NULL }, /* in */ { NULL, posts_ft }, /* ft */ { NULL, posts_eq2 }, /* OP */ + { NULL, posts_nf }, /* EX */ + { NULL, posts_fi }, /* EE */ + { NULL, posts_ur }, /* UR */ + { NULL, NULL }, /* UE */ }; int ! man_valid_pre(struct man *man, struct man_node *n) { v_check *cp; switch (n->type) { case (MAN_TEXT):
*** 136,178 **** } if (NULL == (cp = man_valids[n->tok].pres)) return(1); for ( ; *cp; cp++) ! if ( ! (*cp)(m, n)) return(0); return(1); } int ! man_valid_post(struct man *m) { v_check *cp; ! if (MAN_VALID & m->last->flags) return(1); ! m->last->flags |= MAN_VALID; ! switch (m->last->type) { case (MAN_TEXT): ! check_text(m, m->last); return(1); case (MAN_ROOT): ! return(check_root(m, m->last)); case (MAN_EQN): /* FALLTHROUGH */ case (MAN_TBL): return(1); default: break; } ! if (NULL == (cp = man_valids[m->last->tok].posts)) return(1); for ( ; *cp; cp++) ! if ( ! (*cp)(m, m->last)) return(0); return(1); } --- 145,187 ---- } if (NULL == (cp = man_valids[n->tok].pres)) return(1); for ( ; *cp; cp++) ! if ( ! (*cp)(man, n)) return(0); return(1); } int ! man_valid_post(struct man *man) { v_check *cp; ! if (MAN_VALID & man->last->flags) return(1); ! man->last->flags |= MAN_VALID; ! switch (man->last->type) { case (MAN_TEXT): ! check_text(man, man->last); return(1); case (MAN_ROOT): ! return(check_root(man, man->last)); case (MAN_EQN): /* FALLTHROUGH */ case (MAN_TBL): return(1); default: break; } ! if (NULL == (cp = man_valids[man->last->tok].posts)) return(1); for ( ; *cp; cp++) ! if ( ! (*cp)(man, man->last)) return(0); return(1); }
*** 179,211 **** static int check_root(CHKARGS) { ! if (MAN_BLINE & m->flags) ! man_nmsg(m, n, MANDOCERR_SCOPEEXIT); ! else if (MAN_ELINE & m->flags) ! man_nmsg(m, n, MANDOCERR_SCOPEEXIT); ! m->flags &= ~MAN_BLINE; ! m->flags &= ~MAN_ELINE; ! if (NULL == m->first->child) { ! man_nmsg(m, n, MANDOCERR_NODOCBODY); return(0); ! } else if (NULL == m->meta.title) { ! man_nmsg(m, n, MANDOCERR_NOTITLE); /* * If a title hasn't been set, do so now (by * implication, date and section also aren't set). */ ! m->meta.title = mandoc_strdup("unknown"); ! m->meta.msec = mandoc_strdup("1"); ! m->meta.date = mandoc_normdate ! (m->parse, NULL, n->line, n->pos); } return(1); } --- 188,220 ---- static int check_root(CHKARGS) { ! if (MAN_BLINE & man->flags) ! man_nmsg(man, n, MANDOCERR_SCOPEEXIT); ! else if (MAN_ELINE & man->flags) ! man_nmsg(man, n, MANDOCERR_SCOPEEXIT); ! 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 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.msec = mandoc_strdup("1"); ! man->meta.date = mandoc_normdate ! (man->parse, NULL, n->line, n->pos); } return(1); }
*** 212,236 **** static void check_text(CHKARGS) { char *cp, *p; ! if (MAN_LITERAL & m->flags) return; cp = n->string; for (p = cp; NULL != (p = strchr(p, '\t')); p++) ! man_pmsg(m, n->line, (int)(p - cp), MANDOCERR_BADTAB); } #define INEQ_DEFINE(x, ineq, name) \ static int \ check_##name(CHKARGS) \ { \ if (n->nchild ineq (x)) \ return(1); \ ! mandoc_vmsg(MANDOCERR_ARGCOUNT, m->parse, n->line, n->pos, \ "line arguments %s %d (have %d)", \ #ineq, (x), n->nchild); \ return(1); \ } --- 221,245 ---- static void check_text(CHKARGS) { char *cp, *p; ! if (MAN_LITERAL & man->flags) return; cp = n->string; for (p = cp; NULL != (p = strchr(p, '\t')); p++) ! man_pmsg(man, n->line, (int)(p - cp), MANDOCERR_BADTAB); } #define INEQ_DEFINE(x, ineq, name) \ static int \ check_##name(CHKARGS) \ { \ 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); \ return(1); \ }
*** 239,248 **** --- 248,268 ---- INEQ_DEFINE(1, <=, le1) 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) { char *cp; int ok;
*** 280,297 **** break; } if (0 == ok) { mandoc_vmsg ! (MANDOCERR_BADFONT, m->parse, n->line, n->pos, "%s", cp); *cp = '\0'; } if (1 < n->nchild) mandoc_vmsg ! (MANDOCERR_ARGCOUNT, m->parse, n->line, n->pos, "want one child (have %d)", n->nchild); return(1); } --- 300,317 ---- break; } if (0 == ok) { 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); return(1); }
*** 299,309 **** static int pre_sec(CHKARGS) { if (MAN_BLOCK == n->type) ! m->flags &= ~MAN_LITERAL; return(1); } static int post_sec(CHKARGS) --- 319,329 ---- static int pre_sec(CHKARGS) { if (MAN_BLOCK == n->type) ! man->flags &= ~MAN_LITERAL; return(1); } static int post_sec(CHKARGS)
*** 310,329 **** { if ( ! (MAN_HEAD == n->type && 0 == n->nchild)) return(1); ! man_nmsg(m, n, MANDOCERR_SYNTARGCOUNT); return(0); } static int check_part(CHKARGS) { if (MAN_BODY == n->type && 0 == n->nchild) ! mandoc_msg(MANDOCERR_ARGCWARN, m->parse, n->line, n->pos, "want children (have none)"); return(1); } --- 330,349 ---- { if ( ! (MAN_HEAD == n->type && 0 == n->nchild)) return(1); ! man_nmsg(man, n, MANDOCERR_SYNTARGCOUNT); return(0); } static int check_part(CHKARGS) { if (MAN_BODY == n->type && 0 == n->nchild) ! mandoc_msg(MANDOCERR_ARGCWARN, man->parse, n->line, n->pos, "want children (have none)"); return(1); }
*** 333,459 **** { switch (n->type) { case (MAN_BLOCK): if (0 == n->body->nchild) ! man_node_delete(m, n); break; case (MAN_BODY): if (0 == n->nchild) ! man_nmsg(m, n, MANDOCERR_IGNPAR); break; case (MAN_HEAD): if (n->nchild) ! man_nmsg(m, n, MANDOCERR_ARGSLOST); break; default: break; } return(1); } static int post_TH(CHKARGS) { const char *p; int line, pos; ! if (m->meta.title) ! free(m->meta.title); ! if (m->meta.vol) ! free(m->meta.vol); ! if (m->meta.source) ! free(m->meta.source); ! if (m->meta.msec) ! free(m->meta.msec); ! if (m->meta.date) ! free(m->meta.date); line = n->line; pos = n->pos; ! m->meta.title = m->meta.vol = m->meta.date = ! m->meta.msec = m->meta.source = NULL; /* ->TITLE<- MSEC DATE SOURCE VOL */ n = n->child; 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(m, n, MANDOCERR_UPPERCASE); break; } } ! m->meta.title = mandoc_strdup(n->string); } else ! m->meta.title = mandoc_strdup(""); /* TITLE ->MSEC<- DATE SOURCE VOL */ if (n) n = n->next; if (n && n->string) ! m->meta.msec = mandoc_strdup(n->string); else ! m->meta.msec = mandoc_strdup(""); /* TITLE MSEC ->DATE<- SOURCE VOL */ if (n) n = n->next; if (n && n->string && '\0' != n->string[0]) { pos = n->pos; ! m->meta.date = mandoc_normdate ! (m->parse, n->string, line, pos); } else ! m->meta.date = mandoc_strdup(""); /* TITLE MSEC DATE ->SOURCE<- VOL */ if (n && (n = n->next)) ! m->meta.source = mandoc_strdup(n->string); /* TITLE MSEC DATE SOURCE ->VOL<- */ /* If missing, use the default VOL name for MSEC. */ if (n && (n = n->next)) ! m->meta.vol = mandoc_strdup(n->string); ! else if ('\0' != m->meta.msec[0] && ! (NULL != (p = mandoc_a2msec(m->meta.msec)))) ! m->meta.vol = mandoc_strdup(p); /* * Remove the `TH' node after we've processed it for our * meta-data. */ ! man_node_delete(m, m->last); return(1); } static int post_nf(CHKARGS) { ! if (MAN_LITERAL & m->flags) ! man_nmsg(m, n, MANDOCERR_SCOPEREP); ! m->flags |= MAN_LITERAL; return(1); } static int post_fi(CHKARGS) { ! if ( ! (MAN_LITERAL & m->flags)) ! man_nmsg(m, n, MANDOCERR_WNOSCOPE); ! m->flags &= ~MAN_LITERAL; return(1); } static int post_UC(CHKARGS) --- 353,492 ---- { switch (n->type) { case (MAN_BLOCK): if (0 == n->body->nchild) ! man_node_delete(man, n); break; case (MAN_BODY): if (0 == n->nchild) ! man_nmsg(man, n, MANDOCERR_IGNPAR); break; case (MAN_HEAD): if (n->nchild) ! man_nmsg(man, n, MANDOCERR_ARGSLOST); break; default: break; } return(1); } + static int + post_IP(CHKARGS) + { + switch (n->type) { + case (MAN_BLOCK): + if (0 == n->head->nchild && 0 == n->body->nchild) + man_node_delete(man, n); + break; + case (MAN_BODY): + if (0 == n->parent->head->nchild && 0 == n->nchild) + man_nmsg(man, n, MANDOCERR_IGNPAR); + break; + default: + break; + } + return(1); + } + static int post_TH(CHKARGS) { const char *p; int line, pos; ! free(man->meta.title); ! free(man->meta.vol); ! free(man->meta.source); ! 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; /* ->TITLE<- MSEC DATE SOURCE VOL */ n = n->child; 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); break; } } ! man->meta.title = mandoc_strdup(n->string); } else ! man->meta.title = mandoc_strdup(""); /* TITLE ->MSEC<- DATE SOURCE VOL */ if (n) n = n->next; if (n && n->string) ! man->meta.msec = mandoc_strdup(n->string); else ! man->meta.msec = mandoc_strdup(""); /* TITLE MSEC ->DATE<- SOURCE VOL */ 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 = mandoc_strdup(""); /* TITLE MSEC DATE ->SOURCE<- VOL */ if (n && (n = n->next)) ! man->meta.source = mandoc_strdup(n->string); /* TITLE MSEC DATE SOURCE ->VOL<- */ /* If missing, use the default VOL name for MSEC. */ if (n && (n = n->next)) ! man->meta.vol = mandoc_strdup(n->string); ! else if ('\0' != man->meta.msec[0] && ! (NULL != (p = mandoc_a2msec(man->meta.msec)))) ! man->meta.vol = mandoc_strdup(p); /* * Remove the `TH' node after we've processed it for our * meta-data. */ ! man_node_delete(man, man->last); return(1); } static int post_nf(CHKARGS) { ! if (MAN_LITERAL & man->flags) ! man_nmsg(man, n, MANDOCERR_SCOPEREP); ! man->flags |= MAN_LITERAL; return(1); } static int post_fi(CHKARGS) { ! if ( ! (MAN_LITERAL & man->flags)) ! man_nmsg(man, n, MANDOCERR_WNOSCOPE); ! man->flags &= ~MAN_LITERAL; return(1); } static int post_UC(CHKARGS)
*** 486,499 **** p = bsd_versions[4]; else p = bsd_versions[0]; } ! if (m->meta.source) ! free(m->meta.source); ! ! m->meta.source = mandoc_strdup(p); return(1); } static int post_AT(CHKARGS) --- 519,530 ---- p = bsd_versions[4]; else p = bsd_versions[0]; } ! free(man->meta.source); ! man->meta.source = mandoc_strdup(p); return(1); } static int post_AT(CHKARGS)
*** 526,550 **** p = unix_versions[2]; } else p = unix_versions[0]; } ! if (m->meta.source) ! free(m->meta.source); ! ! m->meta.source = mandoc_strdup(p); return(1); } static int post_vs(CHKARGS) { /* ! * Don't warn about this because it occurs in pod2man and would ! * cause considerable (unfixable) warnage. */ ! if (NULL == n->prev && MAN_ROOT == n->parent->type) ! man_node_delete(m, n); return(1); } --- 557,592 ---- p = unix_versions[2]; } else p = unix_versions[0]; } ! free(man->meta.source); ! man->meta.source = mandoc_strdup(p); return(1); } static int post_vs(CHKARGS) { + if (NULL != n->prev) + return(1); + + switch (n->parent->tok) { + case (MAN_SH): + /* FALLTHROUGH */ + case (MAN_SS): + man_nmsg(man, n, MANDOCERR_IGNPAR); + /* FALLTHROUGH */ + case (MAN_MAX): /* ! * Don't warn about this because it occurs in pod2man ! * and would cause considerable (unfixable) warnage. */ ! man_node_delete(man, n); ! break; ! default: ! break; ! } return(1); }