1*7ebbefbeSschwarze /* $OpenBSD: roff_validate.c,v 1.19 2020/02/27 01:25:58 schwarze Exp $ */
2c4d3fa85Sschwarze /*
3*7ebbefbeSschwarze * Copyright (c) 2010, 2017, 2018, 2020 Ingo Schwarze <schwarze@openbsd.org>
4c4d3fa85Sschwarze *
5c4d3fa85Sschwarze * Permission to use, copy, modify, and distribute this software for any
6c4d3fa85Sschwarze * purpose with or without fee is hereby granted, provided that the above
7c4d3fa85Sschwarze * copyright notice and this permission notice appear in all copies.
8c4d3fa85Sschwarze *
9c4d3fa85Sschwarze * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10c4d3fa85Sschwarze * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11c4d3fa85Sschwarze * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12c4d3fa85Sschwarze * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13c4d3fa85Sschwarze * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14c4d3fa85Sschwarze * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15c4d3fa85Sschwarze * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16c4d3fa85Sschwarze */
17c4d3fa85Sschwarze #include <sys/types.h>
18c4d3fa85Sschwarze
19c4d3fa85Sschwarze #include <assert.h>
20e501e731Sschwarze #include <stdio.h>
219b153f25Sschwarze #include <string.h>
22c4d3fa85Sschwarze
23c4d3fa85Sschwarze #include "mandoc.h"
24c4d3fa85Sschwarze #include "roff.h"
25c4d3fa85Sschwarze #include "libmandoc.h"
26c4d3fa85Sschwarze #include "roff_int.h"
27c4d3fa85Sschwarze
28c4d3fa85Sschwarze #define ROFF_VALID_ARGS struct roff_man *man, struct roff_node *n
29c4d3fa85Sschwarze
30c4d3fa85Sschwarze typedef void (*roff_valid_fp)(ROFF_VALID_ARGS);
31c4d3fa85Sschwarze
328251afdeSschwarze static void roff_valid_br(ROFF_VALID_ARGS);
330438bfdfSschwarze static void roff_valid_fi(ROFF_VALID_ARGS);
34c4d3fa85Sschwarze static void roff_valid_ft(ROFF_VALID_ARGS);
350438bfdfSschwarze static void roff_valid_nf(ROFF_VALID_ARGS);
368251afdeSschwarze static void roff_valid_sp(ROFF_VALID_ARGS);
37c4d3fa85Sschwarze
38c4d3fa85Sschwarze static const roff_valid_fp roff_valids[ROFF_MAX] = {
398251afdeSschwarze roff_valid_br, /* br */
40e13b4195Sschwarze NULL, /* ce */
410438bfdfSschwarze roff_valid_fi, /* fi */
42c4d3fa85Sschwarze roff_valid_ft, /* ft */
43644b390bSschwarze NULL, /* ll */
4424f1eaadSschwarze NULL, /* mc */
450438bfdfSschwarze roff_valid_nf, /* nf */
46af1e8f15Sschwarze NULL, /* po */
476de096f4Sschwarze NULL, /* rj */
488251afdeSschwarze roff_valid_sp, /* sp */
49f7242c43Sschwarze NULL, /* ta */
5011d70615Sschwarze NULL, /* ti */
51c4d3fa85Sschwarze };
52c4d3fa85Sschwarze
53c4d3fa85Sschwarze
54c4d3fa85Sschwarze void
roff_validate(struct roff_man * man)55c4d3fa85Sschwarze roff_validate(struct roff_man *man)
56c4d3fa85Sschwarze {
57c4d3fa85Sschwarze struct roff_node *n;
58c4d3fa85Sschwarze
59c4d3fa85Sschwarze n = man->last;
60c4d3fa85Sschwarze assert(n->tok < ROFF_MAX);
61c4d3fa85Sschwarze if (roff_valids[n->tok] != NULL)
62c4d3fa85Sschwarze (*roff_valids[n->tok])(man, n);
63c4d3fa85Sschwarze }
64c4d3fa85Sschwarze
65c4d3fa85Sschwarze static void
roff_valid_br(ROFF_VALID_ARGS)668251afdeSschwarze roff_valid_br(ROFF_VALID_ARGS)
678251afdeSschwarze {
688251afdeSschwarze struct roff_node *np;
698251afdeSschwarze
704a0fe8a5Sschwarze if (n->next != NULL && n->next->type == ROFFT_TEXT &&
714a0fe8a5Sschwarze *n->next->string == ' ') {
72a5a5f808Sschwarze mandoc_msg(MANDOCERR_PAR_SKIP, n->line, n->pos,
734a0fe8a5Sschwarze "br before text line with leading blank");
744a0fe8a5Sschwarze roff_node_delete(man, n);
754a0fe8a5Sschwarze return;
764a0fe8a5Sschwarze }
774a0fe8a5Sschwarze
78*7ebbefbeSschwarze if ((np = roff_node_prev(n)) == NULL)
798251afdeSschwarze return;
808251afdeSschwarze
818251afdeSschwarze switch (np->tok) {
828251afdeSschwarze case ROFF_br:
838251afdeSschwarze case ROFF_sp:
848251afdeSschwarze case MDOC_Pp:
85a5a5f808Sschwarze mandoc_msg(MANDOCERR_PAR_SKIP,
868251afdeSschwarze n->line, n->pos, "br after %s", roff_name[np->tok]);
878251afdeSschwarze roff_node_delete(man, n);
888251afdeSschwarze break;
898251afdeSschwarze default:
908251afdeSschwarze break;
918251afdeSschwarze }
928251afdeSschwarze }
938251afdeSschwarze
948251afdeSschwarze static void
roff_valid_fi(ROFF_VALID_ARGS)950438bfdfSschwarze roff_valid_fi(ROFF_VALID_ARGS)
960438bfdfSschwarze {
977faedc4aSschwarze if ((n->flags & NODE_NOFILL) == 0)
980438bfdfSschwarze mandoc_msg(MANDOCERR_FI_SKIP, n->line, n->pos, "fi");
990438bfdfSschwarze }
1000438bfdfSschwarze
1010438bfdfSschwarze static void
roff_valid_ft(ROFF_VALID_ARGS)102c4d3fa85Sschwarze roff_valid_ft(ROFF_VALID_ARGS)
103c4d3fa85Sschwarze {
1049b153f25Sschwarze const char *cp;
105c4d3fa85Sschwarze
106c4d3fa85Sschwarze if (n->child == NULL) {
107c4d3fa85Sschwarze man->next = ROFF_NEXT_CHILD;
108c4d3fa85Sschwarze roff_word_alloc(man, n->line, n->pos, "P");
109c4d3fa85Sschwarze man->last = n;
110c4d3fa85Sschwarze return;
111c4d3fa85Sschwarze }
112c4d3fa85Sschwarze
113c4d3fa85Sschwarze cp = n->child->string;
1142e362670Sschwarze if (mandoc_font(cp, (int)strlen(cp)) != ESCAPE_ERROR)
115c4d3fa85Sschwarze return;
116a5a5f808Sschwarze mandoc_msg(MANDOCERR_FT_BAD, n->line, n->pos, "ft %s", cp);
117c4d3fa85Sschwarze roff_node_delete(man, n);
118c4d3fa85Sschwarze }
1198251afdeSschwarze
1208251afdeSschwarze static void
roff_valid_nf(ROFF_VALID_ARGS)1210438bfdfSschwarze roff_valid_nf(ROFF_VALID_ARGS)
1220438bfdfSschwarze {
123072e1378Sschwarze if (n->flags & NODE_NOFILL)
1240438bfdfSschwarze mandoc_msg(MANDOCERR_NF_SKIP, n->line, n->pos, "nf");
1250438bfdfSschwarze }
1260438bfdfSschwarze
1270438bfdfSschwarze static void
roff_valid_sp(ROFF_VALID_ARGS)1288251afdeSschwarze roff_valid_sp(ROFF_VALID_ARGS)
1298251afdeSschwarze {
1308251afdeSschwarze struct roff_node *np;
1318251afdeSschwarze
132*7ebbefbeSschwarze if ((np = roff_node_prev(n)) == NULL)
1338251afdeSschwarze return;
1348251afdeSschwarze
1358251afdeSschwarze switch (np->tok) {
1368251afdeSschwarze case ROFF_br:
137a5a5f808Sschwarze mandoc_msg(MANDOCERR_PAR_SKIP,
1388251afdeSschwarze np->line, np->pos, "br before sp");
1398251afdeSschwarze roff_node_delete(man, np);
1408251afdeSschwarze break;
1418251afdeSschwarze case MDOC_Pp:
142a5a5f808Sschwarze mandoc_msg(MANDOCERR_PAR_SKIP,
1438251afdeSschwarze n->line, n->pos, "sp after Pp");
1448251afdeSschwarze roff_node_delete(man, n);
1458251afdeSschwarze break;
1468251afdeSschwarze default:
1478251afdeSschwarze break;
1488251afdeSschwarze }
1498251afdeSschwarze }
150