GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/mandoc/tbl_data.c Lines: 0 99 0.0 %
Date: 2016-12-06 Branches: 0 79 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: tbl_data.c,v 1.28 2015/10/06 18:30:44 schwarze Exp $ */
2
/*
3
 * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4
 * Copyright (c) 2011, 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 <assert.h>
21
#include <ctype.h>
22
#include <stdlib.h>
23
#include <string.h>
24
#include <time.h>
25
26
#include "mandoc.h"
27
#include "mandoc_aux.h"
28
#include "libmandoc.h"
29
#include "libroff.h"
30
31
static	void		 getdata(struct tbl_node *, struct tbl_span *,
32
				int, const char *, int *);
33
static	struct tbl_span	*newspan(struct tbl_node *, int,
34
				struct tbl_row *);
35
36
37
static void
38
getdata(struct tbl_node *tbl, struct tbl_span *dp,
39
		int ln, const char *p, int *pos)
40
{
41
	struct tbl_dat	*dat;
42
	struct tbl_cell	*cp;
43
	int		 sv;
44
45
	/* Advance to the next layout cell, skipping spanners. */
46
47
	cp = dp->last == NULL ? dp->layout->first : dp->last->layout->next;
48
	while (cp != NULL && cp->pos == TBL_CELL_SPAN)
49
		cp = cp->next;
50
51
	/*
52
	 * Stop processing when we reach the end of the available layout
53
	 * cells.  This means that we have extra input.
54
	 */
55
56
	if (cp == NULL) {
57
		mandoc_msg(MANDOCERR_TBLDATA_EXTRA, tbl->parse,
58
		    ln, *pos, p + *pos);
59
		/* Skip to the end... */
60
		while (p[*pos])
61
			(*pos)++;
62
		return;
63
	}
64
65
	dat = mandoc_calloc(1, sizeof(*dat));
66
	dat->layout = cp;
67
	dat->pos = TBL_DATA_NONE;
68
	dat->spans = 0;
69
	for (cp = cp->next; cp != NULL; cp = cp->next)
70
		if (cp->pos == TBL_CELL_SPAN)
71
			dat->spans++;
72
		else
73
			break;
74
75
	if (dp->last == NULL)
76
		dp->first = dat;
77
	else
78
		dp->last->next = dat;
79
	dp->last = dat;
80
81
	sv = *pos;
82
	while (p[*pos] && p[*pos] != tbl->opts.tab)
83
		(*pos)++;
84
85
	/*
86
	 * Check for a continued-data scope opening.  This consists of a
87
	 * trailing `T{' at the end of the line.  Subsequent lines,
88
	 * until a standalone `T}', are included in our cell.
89
	 */
90
91
	if (*pos - sv == 2 && p[sv] == 'T' && p[sv + 1] == '{') {
92
		tbl->part = TBL_PART_CDATA;
93
		return;
94
	}
95
96
	dat->string = mandoc_strndup(p + sv, *pos - sv);
97
98
	if (p[*pos])
99
		(*pos)++;
100
101
	if ( ! strcmp(dat->string, "_"))
102
		dat->pos = TBL_DATA_HORIZ;
103
	else if ( ! strcmp(dat->string, "="))
104
		dat->pos = TBL_DATA_DHORIZ;
105
	else if ( ! strcmp(dat->string, "\\_"))
106
		dat->pos = TBL_DATA_NHORIZ;
107
	else if ( ! strcmp(dat->string, "\\="))
108
		dat->pos = TBL_DATA_NDHORIZ;
109
	else
110
		dat->pos = TBL_DATA_DATA;
111
112
	if ((dat->layout->pos == TBL_CELL_HORIZ ||
113
	    dat->layout->pos == TBL_CELL_DHORIZ ||
114
	    dat->layout->pos == TBL_CELL_DOWN) &&
115
	    dat->pos == TBL_DATA_DATA && *dat->string != '\0')
116
		mandoc_msg(MANDOCERR_TBLDATA_SPAN,
117
		    tbl->parse, ln, sv, dat->string);
118
}
119
120
int
121
tbl_cdata(struct tbl_node *tbl, int ln, const char *p, int pos)
122
{
123
	struct tbl_dat	*dat;
124
	size_t		 sz;
125
126
	dat = tbl->last_span->last;
127
128
	if (p[pos] == 'T' && p[pos + 1] == '}') {
129
		pos += 2;
130
		if (p[pos] == tbl->opts.tab) {
131
			tbl->part = TBL_PART_DATA;
132
			pos++;
133
			while (p[pos] != '\0')
134
				getdata(tbl, tbl->last_span, ln, p, &pos);
135
			return 1;
136
		} else if (p[pos] == '\0') {
137
			tbl->part = TBL_PART_DATA;
138
			return 1;
139
		}
140
141
		/* Fallthrough: T} is part of a word. */
142
	}
143
144
	dat->pos = TBL_DATA_DATA;
145
146
	if (dat->string != NULL) {
147
		sz = strlen(p + pos) + strlen(dat->string) + 2;
148
		dat->string = mandoc_realloc(dat->string, sz);
149
		(void)strlcat(dat->string, " ", sz);
150
		(void)strlcat(dat->string, p + pos, sz);
151
	} else
152
		dat->string = mandoc_strdup(p + pos);
153
154
	if (dat->layout->pos == TBL_CELL_DOWN)
155
		mandoc_msg(MANDOCERR_TBLDATA_SPAN, tbl->parse,
156
		    ln, pos, dat->string);
157
158
	return 0;
159
}
160
161
static struct tbl_span *
162
newspan(struct tbl_node *tbl, int line, struct tbl_row *rp)
163
{
164
	struct tbl_span	*dp;
165
166
	dp = mandoc_calloc(1, sizeof(*dp));
167
	dp->line = line;
168
	dp->opts = &tbl->opts;
169
	dp->layout = rp;
170
	dp->prev = tbl->last_span;
171
172
	if (dp->prev == NULL) {
173
		tbl->first_span = dp;
174
		tbl->current_span = NULL;
175
	} else
176
		dp->prev->next = dp;
177
	tbl->last_span = dp;
178
179
	return dp;
180
}
181
182
void
183
tbl_data(struct tbl_node *tbl, int ln, const char *p, int pos)
184
{
185
	struct tbl_span	*dp;
186
	struct tbl_row	*rp;
187
188
	/*
189
	 * Choose a layout row: take the one following the last parsed
190
	 * span's.  If that doesn't exist, use the last parsed span's.
191
	 * If there's no last parsed span, use the first row.  Lastly,
192
	 * if the last span was a horizontal line, use the same layout
193
	 * (it doesn't "consume" the layout).
194
	 */
195
196
	if (tbl->last_span != NULL) {
197
		if (tbl->last_span->pos == TBL_SPAN_DATA) {
198
			for (rp = tbl->last_span->layout->next;
199
			     rp != NULL && rp->first != NULL;
200
			     rp = rp->next) {
201
				switch (rp->first->pos) {
202
				case TBL_CELL_HORIZ:
203
					dp = newspan(tbl, ln, rp);
204
					dp->pos = TBL_SPAN_HORIZ;
205
					continue;
206
				case TBL_CELL_DHORIZ:
207
					dp = newspan(tbl, ln, rp);
208
					dp->pos = TBL_SPAN_DHORIZ;
209
					continue;
210
				default:
211
					break;
212
				}
213
				break;
214
			}
215
		} else
216
			rp = tbl->last_span->layout;
217
218
		if (rp == NULL)
219
			rp = tbl->last_span->layout;
220
	} else
221
		rp = tbl->first_row;
222
223
	assert(rp);
224
225
	dp = newspan(tbl, ln, rp);
226
227
	if ( ! strcmp(p, "_")) {
228
		dp->pos = TBL_SPAN_HORIZ;
229
		return;
230
	} else if ( ! strcmp(p, "=")) {
231
		dp->pos = TBL_SPAN_DHORIZ;
232
		return;
233
	}
234
235
	dp->pos = TBL_SPAN_DATA;
236
237
	while (p[pos] != '\0')
238
		getdata(tbl, dp, ln, p, &pos);
239
}