GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/mandoc/tbl_opts.c Lines: 52 55 94.5 %
Date: 2017-11-07 Branches: 42 47 89.4 %

Line Branch Exec Source
1
/*	$OpenBSD: tbl_opts.c,v 1.13 2015/09/26 00:53:15 schwarze Exp $ */
2
/*
3
 * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4
 * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
#include <sys/types.h>
19
20
#include <ctype.h>
21
#include <stdio.h>
22
#include <stdlib.h>
23
#include <string.h>
24
25
#include "mandoc.h"
26
#include "libmandoc.h"
27
#include "libroff.h"
28
29
#define	KEY_DPOINT	0
30
#define	KEY_DELIM	1
31
#define	KEY_LINESIZE	2
32
#define	KEY_TAB		3
33
34
struct	tbl_phrase {
35
	const char	*name;
36
	int		 key;
37
};
38
39
static	const struct tbl_phrase keys[] = {
40
	{"decimalpoint", 0},
41
	{"delim",	 0},
42
	{"linesize",	 0},
43
	{"tab",		 0},
44
	{"allbox",	 TBL_OPT_ALLBOX | TBL_OPT_BOX},
45
	{"box",		 TBL_OPT_BOX},
46
	{"frame",	 TBL_OPT_BOX},
47
	{"center",	 TBL_OPT_CENTRE},
48
	{"centre",	 TBL_OPT_CENTRE},
49
	{"doublebox",	 TBL_OPT_DBOX},
50
	{"doubleframe",  TBL_OPT_DBOX},
51
	{"expand",	 TBL_OPT_EXPAND},
52
	{"nokeep",	 TBL_OPT_NOKEEP},
53
	{"nospaces",	 TBL_OPT_NOSPACE},
54
	{"nowarn",	 TBL_OPT_NOWARN},
55
};
56
57
#define KEY_MAXKEYS ((int)(sizeof(keys)/sizeof(keys[0])))
58
59
static	void	 arg(struct tbl_node *, int, const char *, int *, int);
60
61
62
static void
63
arg(struct tbl_node *tbl, int ln, const char *p, int *pos, int key)
64
{
65
	int		 len, want;
66
67

26032
	while (p[*pos] == ' ' || p[*pos] == '\t')
68
42
		(*pos)++;
69
70
	/* Arguments are enclosed in parentheses. */
71
72
	len = 0;
73
6487
	if (p[*pos] == '(') {
74
6469
		(*pos)++;
75
25948
		while (p[*pos + len] != ')')
76
6505
			len++;
77
	}
78
79

6487
	switch (key) {
80
	case KEY_DELIM:
81
36
		mandoc_vmsg(MANDOCERR_TBLOPT_EQN, tbl->parse,
82
18
		    ln, *pos, "%.*s", len, p + *pos);
83
		want = 2;
84
18
		break;
85
	case KEY_TAB:
86
		want = 1;
87
6451
		if (len == want)
88
6433
			tbl->opts.tab = p[*pos];
89
		break;
90
	case KEY_LINESIZE:
91
		want = 0;
92
		break;
93
	case KEY_DPOINT:
94
		want = 1;
95
18
		if (len == want)
96
			tbl->opts.decimal = p[*pos];
97
		break;
98
	default:
99
		abort();
100
	}
101
102
6487
	if (len == 0)
103
18
		mandoc_msg(MANDOCERR_TBLOPT_NOARG,
104
18
		    tbl->parse, ln, *pos, keys[key].name);
105

12938
	else if (want && len != want)
106
18
		mandoc_vmsg(MANDOCERR_TBLOPT_ARGSZ,
107
18
		    tbl->parse, ln, *pos, "%s want %d have %d",
108
18
		    keys[key].name, want, len);
109
110
6487
	*pos += len;
111
6487
	if (p[*pos] == ')')
112
6469
		(*pos)++;
113
6487
}
114
115
/*
116
 * Parse one line of options up to the semicolon.
117
 * Each option can be preceded by blanks and/or commas,
118
 * and some options are followed by arguments.
119
 */
120
void
121
tbl_option(struct tbl_node *tbl, int ln, const char *p, int *offs)
122
{
123
13430
	int		 i, pos, len;
124
125
6715
	pos = *offs;
126
6715
	for (;;) {
127

89792
		while (p[pos] == ' ' || p[pos] == '\t' || p[pos] == ',')
128
6027
			pos++;
129
130
19412
		if (p[pos] == ';') {
131
6715
			*offs = pos + 1;
132
			return;
133
		}
134
135
		/* Parse one option name. */
136
137
		len = 0;
138
143624
		while (isalpha((unsigned char)p[pos + len]))
139
59115
			len++;
140
141
12697
		if (len == 0) {
142
18
			mandoc_vmsg(MANDOCERR_TBLOPT_ALPHA,
143
18
			    tbl->parse, ln, pos, "%c", p[pos]);
144
18
			pos++;
145
18
			continue;
146
		}
147
148
		/* Look up the option name. */
149
150
		i = 0;
151

210918
		while (i < KEY_MAXKEYS &&
152
82949
		    (strncasecmp(p + pos, keys[i].name, len) ||
153
12661
		     keys[i].name[len] != '\0'))
154
57627
			i++;
155
156
12679
		if (i == KEY_MAXKEYS) {
157
36
			mandoc_vmsg(MANDOCERR_TBLOPT_BAD, tbl->parse,
158
18
			    ln, pos, "%.*s", len, p + pos);
159
18
			pos += len;
160
18
			continue;
161
		}
162
163
		/* Handle the option. */
164
165
12661
		pos += len;
166
12661
		if (keys[i].key)
167
6174
			tbl->opts.opts |= keys[i].key;
168
		else
169
6487
			arg(tbl, ln, p, &pos, i);
170
	}
171
6715
}