xref: /dflybsd-src/contrib/mdocml/tbl.c (revision 54ba96075f5891e4574304da6ba88f1a1afe520b)
1*54ba9607SSascha Wildner /*	$Id: tbl.c,v 1.46 2018/12/14 06:33:14 schwarze Exp $ */
280387638SSascha Wildner /*
360e1e752SSascha Wildner  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4*54ba9607SSascha Wildner  * Copyright (c) 2011, 2015 Ingo Schwarze <schwarze@openbsd.org>
580387638SSascha Wildner  *
680387638SSascha Wildner  * Permission to use, copy, modify, and distribute this software for any
780387638SSascha Wildner  * purpose with or without fee is hereby granted, provided that the above
880387638SSascha Wildner  * copyright notice and this permission notice appear in all copies.
980387638SSascha Wildner  *
1080387638SSascha Wildner  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1180387638SSascha Wildner  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1280387638SSascha Wildner  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1380387638SSascha Wildner  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1480387638SSascha Wildner  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1580387638SSascha Wildner  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1680387638SSascha Wildner  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1780387638SSascha Wildner  */
18a4c7eb57SSascha Wildner #include "config.h"
19*54ba9607SSascha Wildner 
20*54ba9607SSascha Wildner #include <sys/types.h>
21a4c7eb57SSascha Wildner 
2280387638SSascha Wildner #include <assert.h>
2380387638SSascha Wildner #include <stdio.h>
2480387638SSascha Wildner #include <stdlib.h>
2580387638SSascha Wildner #include <string.h>
2680387638SSascha Wildner #include <time.h>
2780387638SSascha Wildner 
28070c62a6SFranco Fichtner #include "mandoc_aux.h"
29*54ba9607SSascha Wildner #include "mandoc.h"
30*54ba9607SSascha Wildner #include "tbl.h"
3180387638SSascha Wildner #include "libmandoc.h"
32*54ba9607SSascha Wildner #include "tbl_parse.h"
33*54ba9607SSascha Wildner #include "tbl_int.h"
3480387638SSascha Wildner 
35070c62a6SFranco Fichtner 
36*54ba9607SSascha Wildner void
tbl_read(struct tbl_node * tbl,int ln,const char * p,int pos)37*54ba9607SSascha Wildner tbl_read(struct tbl_node *tbl, int ln, const char *p, int pos)
3880387638SSascha Wildner {
3980387638SSascha Wildner 	const char	*cp;
40*54ba9607SSascha Wildner 	int		 active;
4180387638SSascha Wildner 
4280387638SSascha Wildner 	/*
43*54ba9607SSascha Wildner 	 * In the options section, proceed to the layout section
44*54ba9607SSascha Wildner 	 * after a semicolon, or right away if there is no semicolon.
45*54ba9607SSascha Wildner 	 * Ignore semicolons in arguments.
4680387638SSascha Wildner 	 */
4780387638SSascha Wildner 
48*54ba9607SSascha Wildner 	if (tbl->part == TBL_PART_OPTS) {
4980387638SSascha Wildner 		tbl->part = TBL_PART_LAYOUT;
50*54ba9607SSascha Wildner 		active = 1;
51*54ba9607SSascha Wildner 		for (cp = p + pos; *cp != '\0'; cp++) {
52*54ba9607SSascha Wildner 			switch (*cp) {
53*54ba9607SSascha Wildner 			case '(':
54*54ba9607SSascha Wildner 				active = 0;
55*54ba9607SSascha Wildner 				continue;
56*54ba9607SSascha Wildner 			case ')':
57*54ba9607SSascha Wildner 				active = 1;
58*54ba9607SSascha Wildner 				continue;
59*54ba9607SSascha Wildner 			case ';':
60*54ba9607SSascha Wildner 				if (active)
61*54ba9607SSascha Wildner 					break;
62*54ba9607SSascha Wildner 				continue;
6380387638SSascha Wildner 			default:
64*54ba9607SSascha Wildner 				continue;
65*54ba9607SSascha Wildner 			}
6680387638SSascha Wildner 			break;
6780387638SSascha Wildner 		}
68*54ba9607SSascha Wildner 		if (*cp == ';') {
69*54ba9607SSascha Wildner 			tbl_option(tbl, ln, p, &pos);
70*54ba9607SSascha Wildner 			if (p[pos] == '\0')
71*54ba9607SSascha Wildner 				return;
72*54ba9607SSascha Wildner 		}
73*54ba9607SSascha Wildner 	}
7480387638SSascha Wildner 
75*54ba9607SSascha Wildner 	/* Process the other section types.  */
76*54ba9607SSascha Wildner 
77*54ba9607SSascha Wildner 	switch (tbl->part) {
78*54ba9607SSascha Wildner 	case TBL_PART_LAYOUT:
79*54ba9607SSascha Wildner 		tbl_layout(tbl, ln, p, pos);
80*54ba9607SSascha Wildner 		break;
81*54ba9607SSascha Wildner 	case TBL_PART_CDATA:
82*54ba9607SSascha Wildner 		tbl_cdata(tbl, ln, p, pos);
83*54ba9607SSascha Wildner 		break;
84*54ba9607SSascha Wildner 	default:
85*54ba9607SSascha Wildner 		tbl_data(tbl, ln, p, pos);
86*54ba9607SSascha Wildner 		break;
87*54ba9607SSascha Wildner 	}
8880387638SSascha Wildner }
8980387638SSascha Wildner 
9080387638SSascha Wildner struct tbl_node *
tbl_alloc(int pos,int line,struct tbl_node * last_tbl)91*54ba9607SSascha Wildner tbl_alloc(int pos, int line, struct tbl_node *last_tbl)
9280387638SSascha Wildner {
93f88b6c16SFranco Fichtner 	struct tbl_node	*tbl;
9480387638SSascha Wildner 
95*54ba9607SSascha Wildner 	tbl = mandoc_calloc(1, sizeof(*tbl));
96*54ba9607SSascha Wildner 	if (last_tbl != NULL)
97*54ba9607SSascha Wildner 		last_tbl->next = tbl;
98f88b6c16SFranco Fichtner 	tbl->line = line;
99f88b6c16SFranco Fichtner 	tbl->pos = pos;
100f88b6c16SFranco Fichtner 	tbl->part = TBL_PART_OPTS;
101f88b6c16SFranco Fichtner 	tbl->opts.tab = '\t';
102f88b6c16SFranco Fichtner 	tbl->opts.decimal = '.';
103*54ba9607SSascha Wildner 	return tbl;
10480387638SSascha Wildner }
10580387638SSascha Wildner 
10680387638SSascha Wildner void
tbl_free(struct tbl_node * tbl)107f88b6c16SFranco Fichtner tbl_free(struct tbl_node *tbl)
10880387638SSascha Wildner {
109*54ba9607SSascha Wildner 	struct tbl_node	*old_tbl;
11080387638SSascha Wildner 	struct tbl_row	*rp;
11180387638SSascha Wildner 	struct tbl_cell	*cp;
11280387638SSascha Wildner 	struct tbl_span	*sp;
11380387638SSascha Wildner 	struct tbl_dat	*dp;
11480387638SSascha Wildner 
115*54ba9607SSascha Wildner 	while (tbl != NULL) {
116*54ba9607SSascha Wildner 		while ((rp = tbl->first_row) != NULL) {
117f88b6c16SFranco Fichtner 			tbl->first_row = rp->next;
118*54ba9607SSascha Wildner 			while (rp->first != NULL) {
11980387638SSascha Wildner 				cp = rp->first;
12080387638SSascha Wildner 				rp->first = cp->next;
121*54ba9607SSascha Wildner 				free(cp->wstr);
12280387638SSascha Wildner 				free(cp);
12380387638SSascha Wildner 			}
12480387638SSascha Wildner 			free(rp);
12580387638SSascha Wildner 		}
126*54ba9607SSascha Wildner 		while ((sp = tbl->first_span) != NULL) {
127f88b6c16SFranco Fichtner 			tbl->first_span = sp->next;
128*54ba9607SSascha Wildner 			while (sp->first != NULL) {
12980387638SSascha Wildner 				dp = sp->first;
13080387638SSascha Wildner 				sp->first = dp->next;
13180387638SSascha Wildner 				free(dp->string);
13280387638SSascha Wildner 				free(dp);
13380387638SSascha Wildner 			}
13480387638SSascha Wildner 			free(sp);
13580387638SSascha Wildner 		}
136*54ba9607SSascha Wildner 		old_tbl = tbl;
137*54ba9607SSascha Wildner 		tbl = tbl->next;
138*54ba9607SSascha Wildner 		free(old_tbl);
13980387638SSascha Wildner 	}
14080387638SSascha Wildner }
14180387638SSascha Wildner 
14280387638SSascha Wildner void
tbl_restart(int line,int pos,struct tbl_node * tbl)14380387638SSascha Wildner tbl_restart(int line, int pos, struct tbl_node *tbl)
14480387638SSascha Wildner {
145*54ba9607SSascha Wildner 	if (tbl->part == TBL_PART_CDATA)
146*54ba9607SSascha Wildner 		mandoc_msg(MANDOCERR_TBLDATA_BLK, line, pos, "T&");
14780387638SSascha Wildner 
14880387638SSascha Wildner 	tbl->part = TBL_PART_LAYOUT;
14980387638SSascha Wildner 	tbl->line = line;
15080387638SSascha Wildner 	tbl->pos = pos;
15180387638SSascha Wildner }
15280387638SSascha Wildner 
153*54ba9607SSascha Wildner struct tbl_span *
tbl_span(struct tbl_node * tbl)15460e1e752SSascha Wildner tbl_span(struct tbl_node *tbl)
15580387638SSascha Wildner {
15660e1e752SSascha Wildner 	struct tbl_span	 *span;
15780387638SSascha Wildner 
15860e1e752SSascha Wildner 	span = tbl->current_span ? tbl->current_span->next
15960e1e752SSascha Wildner 				 : tbl->first_span;
160*54ba9607SSascha Wildner 	if (span != NULL)
16160e1e752SSascha Wildner 		tbl->current_span = span;
162*54ba9607SSascha Wildner 	return span;
16380387638SSascha Wildner }
16480387638SSascha Wildner 
165*54ba9607SSascha Wildner int
tbl_end(struct tbl_node * tbl,int still_open)166*54ba9607SSascha Wildner tbl_end(struct tbl_node *tbl, int still_open)
16780387638SSascha Wildner {
168*54ba9607SSascha Wildner 	struct tbl_span *sp;
16936342e81SSascha Wildner 
170*54ba9607SSascha Wildner 	if (still_open)
171*54ba9607SSascha Wildner 		mandoc_msg(MANDOCERR_BLK_NOEND, tbl->line, tbl->pos, "TS");
172*54ba9607SSascha Wildner 	else if (tbl->part == TBL_PART_CDATA)
173*54ba9607SSascha Wildner 		mandoc_msg(MANDOCERR_TBLDATA_BLK, tbl->line, tbl->pos, "TE");
17480387638SSascha Wildner 
175*54ba9607SSascha Wildner 	sp = tbl->first_span;
176*54ba9607SSascha Wildner 	while (sp != NULL && sp->first == NULL)
177*54ba9607SSascha Wildner 		sp = sp->next;
178*54ba9607SSascha Wildner 	if (sp == NULL) {
179*54ba9607SSascha Wildner 		mandoc_msg(MANDOCERR_TBLDATA_NONE, tbl->line, tbl->pos, NULL);
180*54ba9607SSascha Wildner 		return 0;
181*54ba9607SSascha Wildner 	}
182*54ba9607SSascha Wildner 	return 1;
18380387638SSascha Wildner }
184