GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/mandoc/mdoc_state.c Lines: 61 61 100.0 %
Date: 2017-11-13 Branches: 45 48 93.8 %

Line Branch Exec Source
1
/*	$OpenBSD: mdoc_state.c,v 1.8 2017/05/05 15:16:25 schwarze Exp $ */
2
/*
3
 * Copyright (c) 2014, 2015, 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 <stdlib.h>
21
#include <string.h>
22
23
#include "mandoc.h"
24
#include "roff.h"
25
#include "mdoc.h"
26
#include "libmandoc.h"
27
#include "libmdoc.h"
28
29
#define STATE_ARGS  struct roff_man *mdoc, struct roff_node *n
30
31
typedef	void	(*state_handler)(STATE_ARGS);
32
33
static	void	 state_bd(STATE_ARGS);
34
static	void	 state_bl(STATE_ARGS);
35
static	void	 state_dl(STATE_ARGS);
36
static	void	 state_sh(STATE_ARGS);
37
static	void	 state_sm(STATE_ARGS);
38
39
static	const state_handler __state_handlers[MDOC_MAX - MDOC_Dd] = {
40
	NULL,		/* Dd */
41
	NULL,		/* Dt */
42
	NULL,		/* Os */
43
	state_sh,	/* Sh */
44
	NULL,		/* Ss */
45
	NULL,		/* Pp */
46
	NULL,		/* D1 */
47
	state_dl,	/* Dl */
48
	state_bd,	/* Bd */
49
	NULL,		/* Ed */
50
	state_bl,	/* Bl */
51
	NULL,		/* El */
52
	NULL,		/* It */
53
	NULL,		/* Ad */
54
	NULL,		/* An */
55
	NULL,		/* Ap */
56
	NULL,		/* Ar */
57
	NULL,		/* Cd */
58
	NULL,		/* Cm */
59
	NULL,		/* Dv */
60
	NULL,		/* Er */
61
	NULL,		/* Ev */
62
	NULL,		/* Ex */
63
	NULL,		/* Fa */
64
	NULL,		/* Fd */
65
	NULL,		/* Fl */
66
	NULL,		/* Fn */
67
	NULL,		/* Ft */
68
	NULL,		/* Ic */
69
	NULL,		/* In */
70
	NULL,		/* Li */
71
	NULL,		/* Nd */
72
	NULL,		/* Nm */
73
	NULL,		/* Op */
74
	NULL,		/* Ot */
75
	NULL,		/* Pa */
76
	NULL,		/* Rv */
77
	NULL,		/* St */
78
	NULL,		/* Va */
79
	NULL,		/* Vt */
80
	NULL,		/* Xr */
81
	NULL,		/* %A */
82
	NULL,		/* %B */
83
	NULL,		/* %D */
84
	NULL,		/* %I */
85
	NULL,		/* %J */
86
	NULL,		/* %N */
87
	NULL,		/* %O */
88
	NULL,		/* %P */
89
	NULL,		/* %R */
90
	NULL,		/* %T */
91
	NULL,		/* %V */
92
	NULL,		/* Ac */
93
	NULL,		/* Ao */
94
	NULL,		/* Aq */
95
	NULL,		/* At */
96
	NULL,		/* Bc */
97
	NULL,		/* Bf */
98
	NULL,		/* Bo */
99
	NULL,		/* Bq */
100
	NULL,		/* Bsx */
101
	NULL,		/* Bx */
102
	NULL,		/* Db */
103
	NULL,		/* Dc */
104
	NULL,		/* Do */
105
	NULL,		/* Dq */
106
	NULL,		/* Ec */
107
	NULL,		/* Ef */
108
	NULL,		/* Em */
109
	NULL,		/* Eo */
110
	NULL,		/* Fx */
111
	NULL,		/* Ms */
112
	NULL,		/* No */
113
	NULL,		/* Ns */
114
	NULL,		/* Nx */
115
	NULL,		/* Ox */
116
	NULL,		/* Pc */
117
	NULL,		/* Pf */
118
	NULL,		/* Po */
119
	NULL,		/* Pq */
120
	NULL,		/* Qc */
121
	NULL,		/* Ql */
122
	NULL,		/* Qo */
123
	NULL,		/* Qq */
124
	NULL,		/* Re */
125
	NULL,		/* Rs */
126
	NULL,		/* Sc */
127
	NULL,		/* So */
128
	NULL,		/* Sq */
129
	state_sm,	/* Sm */
130
	NULL,		/* Sx */
131
	NULL,		/* Sy */
132
	NULL,		/* Tn */
133
	NULL,		/* Ux */
134
	NULL,		/* Xc */
135
	NULL,		/* Xo */
136
	NULL,		/* Fo */
137
	NULL,		/* Fc */
138
	NULL,		/* Oo */
139
	NULL,		/* Oc */
140
	NULL,		/* Bk */
141
	NULL,		/* Ek */
142
	NULL,		/* Bt */
143
	NULL,		/* Hf */
144
	NULL,		/* Fr */
145
	NULL,		/* Ud */
146
	NULL,		/* Lb */
147
	NULL,		/* Lp */
148
	NULL,		/* Lk */
149
	NULL,		/* Mt */
150
	NULL,		/* Brq */
151
	NULL,		/* Bro */
152
	NULL,		/* Brc */
153
	NULL,		/* %C */
154
	NULL,		/* Es */
155
	NULL,		/* En */
156
	NULL,		/* Dx */
157
	NULL,		/* %Q */
158
	NULL,		/* %U */
159
	NULL,		/* Ta */
160
};
161
static const state_handler *const state_handlers = __state_handlers - MDOC_Dd;
162
163
164
void
165
mdoc_state(struct roff_man *mdoc, struct roff_node *n)
166
{
167
	state_handler handler;
168
169

4300505
	if (n->tok == TOKEN_NONE || n->tok < ROFF_MAX)
170
306344
		return;
171
172

2458498
	assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX);
173
1229249
	if ( ! (mdoc_macros[n->tok].flags & MDOC_PROLOGUE))
174
1194569
		mdoc->flags |= MDOC_PBODY;
175
176
1229249
	handler = state_handlers[n->tok];
177
1229249
	if (*handler)
178
234911
		(*handler)(mdoc, n);
179
2764842
}
180
181
void
182
mdoc_state_reset(struct roff_man *mdoc)
183
{
184
185
23044
	roff_setreg(mdoc->roff, "nS", 0, '=');
186
11522
	mdoc->flags = 0;
187
11522
}
188
189
static void
190
state_bd(STATE_ARGS)
191
{
192
	enum mdocargt arg;
193
194

51186
	if (n->type != ROFFT_HEAD &&
195
24087
	    (n->type != ROFFT_BODY || n->end != ENDBODY_NOT))
196
6627
		return;
197
198
14598
	if (n->parent->args == NULL)
199
60
		return;
200
201
14538
	arg = n->parent->args->argv[0].arg;
202
14538
	if (arg != MDOC_Literal && arg != MDOC_Unfilled)
203
2318
		return;
204
205
12220
	state_dl(mdoc, n);
206
33445
}
207
208
static void
209
state_bl(STATE_ARGS)
210
{
211
212

122610
	if (n->type != ROFFT_HEAD || n->parent->args == NULL)
213
		return;
214
215
55294
	switch(n->parent->args->argv[0].arg) {
216
	case MDOC_Diag:
217
422
		n->norm->Bl.type = LIST_diag;
218
422
		break;
219
	case MDOC_Column:
220
854
		n->norm->Bl.type = LIST_column;
221
854
		break;
222
	default:
223
		break;
224
	}
225
54018
}
226
227
static void
228
state_dl(STATE_ARGS)
229
{
230
231
53334
	switch (n->type) {
232
	case ROFFT_HEAD:
233
6614
		mdoc->flags |= MDOC_LITERAL;
234
6614
		break;
235
	case ROFFT_BODY:
236
9918
		mdoc->flags &= ~MDOC_LITERAL;
237
9918
		break;
238
	default:
239
		break;
240
	}
241
18401
}
242
243
static void
244
state_sh(STATE_ARGS)
245
{
246
	struct roff_node *nch;
247
303216
	char		 *secname;
248
249
151608
	if (n->type != ROFFT_HEAD)
250
101072
		return;
251
252
50536
	if ( ! (n->flags & NODE_VALID)) {
253
25268
		secname = NULL;
254
25268
		deroff(&secname, n);
255
256
		/*
257
		 * Set the section attribute for the BLOCK, HEAD,
258
		 * and HEAD children; the latter can only be TEXT
259
		 * nodes, so no recursion is needed.  For other
260
		 * nodes, including the .Sh BODY, this is done
261
		 * when allocating the node data structures, but
262
		 * for .Sh BLOCK and HEAD, the section is still
263
		 * unknown at that time.
264
		 */
265
266
75804
		n->sec = n->parent->sec = secname == NULL ?
267
25268
		    SEC_CUSTOM : mdoc_a2sec(secname);
268
101120
		for (nch = n->child; nch != NULL; nch = nch->next)
269
25292
			nch->sec = n->sec;
270
25268
		free(secname);
271
25268
	}
272
273
50536
	if ((mdoc->lastsec = n->sec) == SEC_SYNOPSIS) {
274
5860
		roff_setreg(mdoc->roff, "nS", 1, '=');
275
5860
		mdoc->flags |= MDOC_SYNOPSIS;
276
5860
	} else {
277
44676
		roff_setreg(mdoc->roff, "nS", 0, '=');
278
44676
		mdoc->flags &= ~MDOC_SYNOPSIS;
279
	}
280
202144
}
281
282
static void
283
state_sm(STATE_ARGS)
284
{
285
286
3758
	if (n->child == NULL)
287
36
		mdoc->flags ^= MDOC_SMOFF;
288
1843
	else if ( ! strcmp(n->child->string, "on"))
289
908
		mdoc->flags &= ~MDOC_SMOFF;
290
935
	else if ( ! strcmp(n->child->string, "off"))
291
899
		mdoc->flags |= MDOC_SMOFF;
292
1879
}