=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/mandoc/man_validate.c,v retrieving revision 1.120 retrieving revision 1.121 diff -c -r1.120 -r1.121 *** src/usr.bin/mandoc/man_validate.c 2020/01/19 16:16:32 1.120 --- src/usr.bin/mandoc/man_validate.c 2020/03/13 00:31:05 1.121 *************** *** 1,7 **** ! /* $OpenBSD: man_validate.c,v 1.120 2020/01/19 16:16:32 schwarze Exp $ */ /* - * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * Copyright (c) 2010, 2012-2020 Ingo Schwarze * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above --- 1,7 ---- ! /* $OpenBSD: man_validate.c,v 1.121 2020/03/13 00:31:05 schwarze Exp $ */ /* * Copyright (c) 2010, 2012-2020 Ingo Schwarze + * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above *************** *** 14,19 **** --- 14,21 ---- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Validation module for man(7) syntax trees used by mandoc(1). */ #include *************** *** 30,35 **** --- 32,38 ---- #include "mandoc_aux.h" #include "mandoc.h" #include "roff.h" + #include "tag.h" #include "man.h" #include "libmandoc.h" #include "roff_int.h" *************** *** 43,48 **** --- 46,52 ---- static void check_par(CHKARGS); static void check_part(CHKARGS); static void check_root(CHKARGS); + static void check_tag(struct roff_node *, struct roff_node *); static void check_text(CHKARGS); static void post_AT(CHKARGS); *************** *** 52,57 **** --- 56,62 ---- static void post_OP(CHKARGS); static void post_SH(CHKARGS); static void post_TH(CHKARGS); + static void post_TP(CHKARGS); static void post_UC(CHKARGS); static void post_UR(CHKARGS); static void post_in(CHKARGS); *************** *** 60,67 **** post_TH, /* TH */ post_SH, /* SH */ post_SH, /* SS */ ! NULL, /* TP */ ! NULL, /* TQ */ check_abort,/* LP */ check_par, /* PP */ check_abort,/* P */ --- 65,72 ---- post_TH, /* TH */ post_SH, /* SH */ post_SH, /* SS */ ! post_TP, /* TP */ ! post_TP, /* TQ */ check_abort,/* LP */ check_par, /* PP */ check_abort,/* P */ *************** *** 199,205 **** --- 204,270 ---- abort(); } + /* + * Skip leading whitespace, dashes, backslashes, and font escapes, + * then create a tag if the first following byte is a letter. + * Priority is high unless whitespace is present. + */ static void + check_tag(struct roff_node *n, struct roff_node *nt) + { + const char *cp, *arg; + int prio, sz; + + if (nt == NULL || nt->type != ROFFT_TEXT) + return; + + cp = nt->string; + prio = TAG_STRONG; + for (;;) { + switch (*cp) { + case ' ': + case '\t': + prio = TAG_WEAK; + /* FALLTHROUGH */ + case '-': + cp++; + break; + case '\\': + cp++; + switch (mandoc_escape(&cp, &arg, &sz)) { + case ESCAPE_FONT: + case ESCAPE_FONTBOLD: + case ESCAPE_FONTITALIC: + case ESCAPE_FONTBI: + case ESCAPE_FONTROMAN: + case ESCAPE_FONTCW: + case ESCAPE_FONTPREV: + case ESCAPE_IGNORE: + break; + case ESCAPE_SPECIAL: + if (sz != 1) + return; + switch (*arg) { + case '-': + case 'e': + break; + default: + return; + } + break; + default: + return; + } + break; + default: + if (isalpha((unsigned char)*cp)) + tag_put(cp, prio, n); + return; + } + } + } + + static void check_text(CHKARGS) { char *cp, *p; *************** *** 330,341 **** static void post_IP(CHKARGS) { - switch (n->type) { case ROFFT_BLOCK: if (n->head->child == NULL && n->body->child == NULL) roff_node_delete(man, n); break; case ROFFT_BODY: if (n->parent->head->child == NULL && n->child == NULL) mandoc_msg(MANDOCERR_PAR_SKIP, n->line, n->pos, --- 395,408 ---- static void post_IP(CHKARGS) { switch (n->type) { case ROFFT_BLOCK: if (n->head->child == NULL && n->body->child == NULL) roff_node_delete(man, n); break; + case ROFFT_HEAD: + check_tag(n, n->child); + break; case ROFFT_BODY: if (n->parent->head->child == NULL && n->child == NULL) mandoc_msg(MANDOCERR_PAR_SKIP, n->line, n->pos, *************** *** 344,349 **** --- 411,447 ---- default: break; } + } + + /* + * The first next-line element in the head is the tag. + * If that's a font macro, use its first child instead. + */ + static void + post_TP(CHKARGS) + { + struct roff_node *nt; + + if (n->type != ROFFT_HEAD || (nt = n->child) == NULL) + return; + + while ((nt->flags & NODE_LINE) == 0) + if ((nt = nt->next) == NULL) + return; + + switch (nt->tok) { + case MAN_B: + case MAN_BI: + case MAN_BR: + case MAN_I: + case MAN_IB: + case MAN_IR: + nt = nt->child; + break; + default: + break; + } + check_tag(n, nt); } static void