xref: /freebsd/contrib/mandoc/tbl.c (revision 61d06d6bd19dafe8ea971dd43e8328fa1b473456)
1*61d06d6bSBaptiste Daroussin /*	$Id: tbl.c,v 1.42 2017/07/08 17:52:50 schwarze Exp $ */
2*61d06d6bSBaptiste Daroussin /*
3*61d06d6bSBaptiste Daroussin  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4*61d06d6bSBaptiste Daroussin  * Copyright (c) 2011, 2015 Ingo Schwarze <schwarze@openbsd.org>
5*61d06d6bSBaptiste Daroussin  *
6*61d06d6bSBaptiste Daroussin  * Permission to use, copy, modify, and distribute this software for any
7*61d06d6bSBaptiste Daroussin  * purpose with or without fee is hereby granted, provided that the above
8*61d06d6bSBaptiste Daroussin  * copyright notice and this permission notice appear in all copies.
9*61d06d6bSBaptiste Daroussin  *
10*61d06d6bSBaptiste Daroussin  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11*61d06d6bSBaptiste Daroussin  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12*61d06d6bSBaptiste Daroussin  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13*61d06d6bSBaptiste Daroussin  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14*61d06d6bSBaptiste Daroussin  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15*61d06d6bSBaptiste Daroussin  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16*61d06d6bSBaptiste Daroussin  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*61d06d6bSBaptiste Daroussin  */
18*61d06d6bSBaptiste Daroussin #include "config.h"
19*61d06d6bSBaptiste Daroussin 
20*61d06d6bSBaptiste Daroussin #include <sys/types.h>
21*61d06d6bSBaptiste Daroussin 
22*61d06d6bSBaptiste Daroussin #include <assert.h>
23*61d06d6bSBaptiste Daroussin #include <stdio.h>
24*61d06d6bSBaptiste Daroussin #include <stdlib.h>
25*61d06d6bSBaptiste Daroussin #include <string.h>
26*61d06d6bSBaptiste Daroussin #include <time.h>
27*61d06d6bSBaptiste Daroussin 
28*61d06d6bSBaptiste Daroussin #include "mandoc.h"
29*61d06d6bSBaptiste Daroussin #include "mandoc_aux.h"
30*61d06d6bSBaptiste Daroussin #include "libmandoc.h"
31*61d06d6bSBaptiste Daroussin #include "libroff.h"
32*61d06d6bSBaptiste Daroussin 
33*61d06d6bSBaptiste Daroussin 
34*61d06d6bSBaptiste Daroussin void
35*61d06d6bSBaptiste Daroussin tbl_read(struct tbl_node *tbl, int ln, const char *p, int pos)
36*61d06d6bSBaptiste Daroussin {
37*61d06d6bSBaptiste Daroussin 	const char	*cp;
38*61d06d6bSBaptiste Daroussin 	int		 active;
39*61d06d6bSBaptiste Daroussin 
40*61d06d6bSBaptiste Daroussin 	/*
41*61d06d6bSBaptiste Daroussin 	 * In the options section, proceed to the layout section
42*61d06d6bSBaptiste Daroussin 	 * after a semicolon, or right away if there is no semicolon.
43*61d06d6bSBaptiste Daroussin 	 * Ignore semicolons in arguments.
44*61d06d6bSBaptiste Daroussin 	 */
45*61d06d6bSBaptiste Daroussin 
46*61d06d6bSBaptiste Daroussin 	if (tbl->part == TBL_PART_OPTS) {
47*61d06d6bSBaptiste Daroussin 		tbl->part = TBL_PART_LAYOUT;
48*61d06d6bSBaptiste Daroussin 		active = 1;
49*61d06d6bSBaptiste Daroussin 		for (cp = p + pos; *cp != '\0'; cp++) {
50*61d06d6bSBaptiste Daroussin 			switch (*cp) {
51*61d06d6bSBaptiste Daroussin 			case '(':
52*61d06d6bSBaptiste Daroussin 				active = 0;
53*61d06d6bSBaptiste Daroussin 				continue;
54*61d06d6bSBaptiste Daroussin 			case ')':
55*61d06d6bSBaptiste Daroussin 				active = 1;
56*61d06d6bSBaptiste Daroussin 				continue;
57*61d06d6bSBaptiste Daroussin 			case ';':
58*61d06d6bSBaptiste Daroussin 				if (active)
59*61d06d6bSBaptiste Daroussin 					break;
60*61d06d6bSBaptiste Daroussin 				continue;
61*61d06d6bSBaptiste Daroussin 			default:
62*61d06d6bSBaptiste Daroussin 				continue;
63*61d06d6bSBaptiste Daroussin 			}
64*61d06d6bSBaptiste Daroussin 			break;
65*61d06d6bSBaptiste Daroussin 		}
66*61d06d6bSBaptiste Daroussin 		if (*cp == ';') {
67*61d06d6bSBaptiste Daroussin 			tbl_option(tbl, ln, p, &pos);
68*61d06d6bSBaptiste Daroussin 			if (p[pos] == '\0')
69*61d06d6bSBaptiste Daroussin 				return;
70*61d06d6bSBaptiste Daroussin 		}
71*61d06d6bSBaptiste Daroussin 	}
72*61d06d6bSBaptiste Daroussin 
73*61d06d6bSBaptiste Daroussin 	/* Process the other section types.  */
74*61d06d6bSBaptiste Daroussin 
75*61d06d6bSBaptiste Daroussin 	switch (tbl->part) {
76*61d06d6bSBaptiste Daroussin 	case TBL_PART_LAYOUT:
77*61d06d6bSBaptiste Daroussin 		tbl_layout(tbl, ln, p, pos);
78*61d06d6bSBaptiste Daroussin 		break;
79*61d06d6bSBaptiste Daroussin 	case TBL_PART_CDATA:
80*61d06d6bSBaptiste Daroussin 		tbl_cdata(tbl, ln, p, pos);
81*61d06d6bSBaptiste Daroussin 		break;
82*61d06d6bSBaptiste Daroussin 	default:
83*61d06d6bSBaptiste Daroussin 		tbl_data(tbl, ln, p, pos);
84*61d06d6bSBaptiste Daroussin 		break;
85*61d06d6bSBaptiste Daroussin 	}
86*61d06d6bSBaptiste Daroussin }
87*61d06d6bSBaptiste Daroussin 
88*61d06d6bSBaptiste Daroussin struct tbl_node *
89*61d06d6bSBaptiste Daroussin tbl_alloc(int pos, int line, struct mparse *parse)
90*61d06d6bSBaptiste Daroussin {
91*61d06d6bSBaptiste Daroussin 	struct tbl_node	*tbl;
92*61d06d6bSBaptiste Daroussin 
93*61d06d6bSBaptiste Daroussin 	tbl = mandoc_calloc(1, sizeof(*tbl));
94*61d06d6bSBaptiste Daroussin 	tbl->line = line;
95*61d06d6bSBaptiste Daroussin 	tbl->pos = pos;
96*61d06d6bSBaptiste Daroussin 	tbl->parse = parse;
97*61d06d6bSBaptiste Daroussin 	tbl->part = TBL_PART_OPTS;
98*61d06d6bSBaptiste Daroussin 	tbl->opts.tab = '\t';
99*61d06d6bSBaptiste Daroussin 	tbl->opts.decimal = '.';
100*61d06d6bSBaptiste Daroussin 	return tbl;
101*61d06d6bSBaptiste Daroussin }
102*61d06d6bSBaptiste Daroussin 
103*61d06d6bSBaptiste Daroussin void
104*61d06d6bSBaptiste Daroussin tbl_free(struct tbl_node *tbl)
105*61d06d6bSBaptiste Daroussin {
106*61d06d6bSBaptiste Daroussin 	struct tbl_row	*rp;
107*61d06d6bSBaptiste Daroussin 	struct tbl_cell	*cp;
108*61d06d6bSBaptiste Daroussin 	struct tbl_span	*sp;
109*61d06d6bSBaptiste Daroussin 	struct tbl_dat	*dp;
110*61d06d6bSBaptiste Daroussin 
111*61d06d6bSBaptiste Daroussin 	while ((rp = tbl->first_row) != NULL) {
112*61d06d6bSBaptiste Daroussin 		tbl->first_row = rp->next;
113*61d06d6bSBaptiste Daroussin 		while (rp->first != NULL) {
114*61d06d6bSBaptiste Daroussin 			cp = rp->first;
115*61d06d6bSBaptiste Daroussin 			rp->first = cp->next;
116*61d06d6bSBaptiste Daroussin 			free(cp->wstr);
117*61d06d6bSBaptiste Daroussin 			free(cp);
118*61d06d6bSBaptiste Daroussin 		}
119*61d06d6bSBaptiste Daroussin 		free(rp);
120*61d06d6bSBaptiste Daroussin 	}
121*61d06d6bSBaptiste Daroussin 
122*61d06d6bSBaptiste Daroussin 	while ((sp = tbl->first_span) != NULL) {
123*61d06d6bSBaptiste Daroussin 		tbl->first_span = sp->next;
124*61d06d6bSBaptiste Daroussin 		while (sp->first != NULL) {
125*61d06d6bSBaptiste Daroussin 			dp = sp->first;
126*61d06d6bSBaptiste Daroussin 			sp->first = dp->next;
127*61d06d6bSBaptiste Daroussin 			free(dp->string);
128*61d06d6bSBaptiste Daroussin 			free(dp);
129*61d06d6bSBaptiste Daroussin 		}
130*61d06d6bSBaptiste Daroussin 		free(sp);
131*61d06d6bSBaptiste Daroussin 	}
132*61d06d6bSBaptiste Daroussin 
133*61d06d6bSBaptiste Daroussin 	free(tbl);
134*61d06d6bSBaptiste Daroussin }
135*61d06d6bSBaptiste Daroussin 
136*61d06d6bSBaptiste Daroussin void
137*61d06d6bSBaptiste Daroussin tbl_restart(int line, int pos, struct tbl_node *tbl)
138*61d06d6bSBaptiste Daroussin {
139*61d06d6bSBaptiste Daroussin 	if (tbl->part == TBL_PART_CDATA)
140*61d06d6bSBaptiste Daroussin 		mandoc_msg(MANDOCERR_TBLDATA_BLK, tbl->parse,
141*61d06d6bSBaptiste Daroussin 		    line, pos, "T&");
142*61d06d6bSBaptiste Daroussin 
143*61d06d6bSBaptiste Daroussin 	tbl->part = TBL_PART_LAYOUT;
144*61d06d6bSBaptiste Daroussin 	tbl->line = line;
145*61d06d6bSBaptiste Daroussin 	tbl->pos = pos;
146*61d06d6bSBaptiste Daroussin }
147*61d06d6bSBaptiste Daroussin 
148*61d06d6bSBaptiste Daroussin const struct tbl_span *
149*61d06d6bSBaptiste Daroussin tbl_span(struct tbl_node *tbl)
150*61d06d6bSBaptiste Daroussin {
151*61d06d6bSBaptiste Daroussin 	struct tbl_span	 *span;
152*61d06d6bSBaptiste Daroussin 
153*61d06d6bSBaptiste Daroussin 	assert(tbl);
154*61d06d6bSBaptiste Daroussin 	span = tbl->current_span ? tbl->current_span->next
155*61d06d6bSBaptiste Daroussin 				 : tbl->first_span;
156*61d06d6bSBaptiste Daroussin 	if (span)
157*61d06d6bSBaptiste Daroussin 		tbl->current_span = span;
158*61d06d6bSBaptiste Daroussin 	return span;
159*61d06d6bSBaptiste Daroussin }
160*61d06d6bSBaptiste Daroussin 
161*61d06d6bSBaptiste Daroussin int
162*61d06d6bSBaptiste Daroussin tbl_end(struct tbl_node *tbl)
163*61d06d6bSBaptiste Daroussin {
164*61d06d6bSBaptiste Daroussin 	struct tbl_span *sp;
165*61d06d6bSBaptiste Daroussin 
166*61d06d6bSBaptiste Daroussin 	if (tbl->part == TBL_PART_CDATA)
167*61d06d6bSBaptiste Daroussin 		mandoc_msg(MANDOCERR_TBLDATA_BLK, tbl->parse,
168*61d06d6bSBaptiste Daroussin 		    tbl->line, tbl->pos, "TE");
169*61d06d6bSBaptiste Daroussin 
170*61d06d6bSBaptiste Daroussin 	sp = tbl->first_span;
171*61d06d6bSBaptiste Daroussin 	while (sp != NULL && sp->first == NULL)
172*61d06d6bSBaptiste Daroussin 		sp = sp->next;
173*61d06d6bSBaptiste Daroussin 	if (sp == NULL) {
174*61d06d6bSBaptiste Daroussin 		mandoc_msg(MANDOCERR_TBLDATA_NONE, tbl->parse,
175*61d06d6bSBaptiste Daroussin 		    tbl->line, tbl->pos, NULL);
176*61d06d6bSBaptiste Daroussin 		return 0;
177*61d06d6bSBaptiste Daroussin 	}
178*61d06d6bSBaptiste Daroussin 	return 1;
179*61d06d6bSBaptiste Daroussin }
180