1 /* $OpenBSD: roff_validate.c,v 1.10 2018/08/10 20:40:43 schwarze Exp $ */ 2 /* 3 * Copyright (c) 2010, 2017, 2018 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 #include <string.h> 22 23 #include "mandoc.h" 24 #include "roff.h" 25 #include "libmandoc.h" 26 #include "roff_int.h" 27 28 #define ROFF_VALID_ARGS struct roff_man *man, struct roff_node *n 29 30 typedef void (*roff_valid_fp)(ROFF_VALID_ARGS); 31 32 static void roff_valid_ft(ROFF_VALID_ARGS); 33 34 static const roff_valid_fp roff_valids[ROFF_MAX] = { 35 NULL, /* br */ 36 NULL, /* ce */ 37 roff_valid_ft, /* ft */ 38 NULL, /* ll */ 39 NULL, /* mc */ 40 NULL, /* po */ 41 NULL, /* rj */ 42 NULL, /* sp */ 43 NULL, /* ta */ 44 NULL, /* ti */ 45 }; 46 47 48 void 49 roff_validate(struct roff_man *man) 50 { 51 struct roff_node *n; 52 53 n = man->last; 54 assert(n->tok < ROFF_MAX); 55 if (roff_valids[n->tok] != NULL) 56 (*roff_valids[n->tok])(man, n); 57 } 58 59 static void 60 roff_valid_ft(ROFF_VALID_ARGS) 61 { 62 const char *cp; 63 64 if (n->child == NULL) { 65 man->next = ROFF_NEXT_CHILD; 66 roff_word_alloc(man, n->line, n->pos, "P"); 67 man->last = n; 68 return; 69 } 70 71 cp = n->child->string; 72 switch (*cp) { 73 case '1': 74 case '2': 75 case '3': 76 case '4': 77 case 'I': 78 case 'P': 79 case 'R': 80 if (cp[1] == '\0') 81 return; 82 break; 83 case 'B': 84 if (cp[1] == '\0' || (cp[1] == 'I' && cp[2] == '\0')) 85 return; 86 break; 87 case 'C': 88 if (cp[1] != '\0' && cp[2] == '\0' && 89 strchr("BIRW", cp[1]) != NULL) 90 return; 91 break; 92 default: 93 break; 94 } 95 96 mandoc_vmsg(MANDOCERR_FT_BAD, man->parse, 97 n->line, n->pos, "ft %s", cp); 98 roff_node_delete(man, n); 99 } 100