roff_validate.c revision 1.7
1/* $OpenBSD: roff_validate.c,v 1.7 2017/06/06 15:00:56 schwarze Exp $ */ 2/* 3 * Copyright (c) 2010, 2017 Ingo Schwarze <schwarze@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17#include <sys/types.h> 18 19#include <assert.h> 20#include <stddef.h> 21 22#include "mandoc.h" 23#include "roff.h" 24#include "libmandoc.h" 25#include "roff_int.h" 26 27#define ROFF_VALID_ARGS struct roff_man *man, struct roff_node *n 28 29typedef void (*roff_valid_fp)(ROFF_VALID_ARGS); 30 31static void roff_valid_ft(ROFF_VALID_ARGS); 32 33static const roff_valid_fp roff_valids[ROFF_MAX] = { 34 NULL, /* br */ 35 NULL, /* ce */ 36 roff_valid_ft, /* ft */ 37 NULL, /* ll */ 38 NULL, /* mc */ 39 NULL, /* sp */ 40 NULL, /* ta */ 41 NULL, /* ti */ 42}; 43 44 45void 46roff_validate(struct roff_man *man) 47{ 48 struct roff_node *n; 49 50 n = man->last; 51 assert(n->tok < ROFF_MAX); 52 if (roff_valids[n->tok] != NULL) 53 (*roff_valids[n->tok])(man, n); 54} 55 56static void 57roff_valid_ft(ROFF_VALID_ARGS) 58{ 59 char *cp; 60 61 if (n->child == NULL) { 62 man->next = ROFF_NEXT_CHILD; 63 roff_word_alloc(man, n->line, n->pos, "P"); 64 man->last = n; 65 return; 66 } 67 68 cp = n->child->string; 69 switch (*cp) { 70 case '1': 71 case '2': 72 case '3': 73 case '4': 74 case 'I': 75 case 'P': 76 case 'R': 77 if (cp[1] == '\0') 78 return; 79 break; 80 case 'B': 81 if (cp[1] == '\0' || (cp[1] == 'I' && cp[2] == '\0')) 82 return; 83 break; 84 case 'C': 85 if (cp[1] == 'W' && cp[2] == '\0') 86 return; 87 break; 88 default: 89 break; 90 } 91 92 mandoc_vmsg(MANDOCERR_FT_BAD, man->parse, 93 n->line, n->pos, "ft %s", cp); 94 roff_node_delete(man, n); 95} 96