xref: /freebsd/contrib/mandoc/tbl.c (revision 7648bc9fee8dec6cb3c4941e0165a930fbe8dcb0)
1*7295610fSBaptiste Daroussin /*	$Id: tbl.c,v 1.46 2018/12/14 06:33:14 schwarze Exp $ */
261d06d6bSBaptiste Daroussin /*
361d06d6bSBaptiste Daroussin  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
461d06d6bSBaptiste Daroussin  * Copyright (c) 2011, 2015 Ingo Schwarze <schwarze@openbsd.org>
561d06d6bSBaptiste Daroussin  *
661d06d6bSBaptiste Daroussin  * Permission to use, copy, modify, and distribute this software for any
761d06d6bSBaptiste Daroussin  * purpose with or without fee is hereby granted, provided that the above
861d06d6bSBaptiste Daroussin  * copyright notice and this permission notice appear in all copies.
961d06d6bSBaptiste Daroussin  *
1061d06d6bSBaptiste Daroussin  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1161d06d6bSBaptiste Daroussin  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1261d06d6bSBaptiste Daroussin  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1361d06d6bSBaptiste Daroussin  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1461d06d6bSBaptiste Daroussin  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1561d06d6bSBaptiste Daroussin  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1661d06d6bSBaptiste Daroussin  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1761d06d6bSBaptiste Daroussin  */
1861d06d6bSBaptiste Daroussin #include "config.h"
1961d06d6bSBaptiste Daroussin 
2061d06d6bSBaptiste Daroussin #include <sys/types.h>
2161d06d6bSBaptiste Daroussin 
2261d06d6bSBaptiste Daroussin #include <assert.h>
2361d06d6bSBaptiste Daroussin #include <stdio.h>
2461d06d6bSBaptiste Daroussin #include <stdlib.h>
2561d06d6bSBaptiste Daroussin #include <string.h>
2661d06d6bSBaptiste Daroussin #include <time.h>
2761d06d6bSBaptiste Daroussin 
2861d06d6bSBaptiste Daroussin #include "mandoc_aux.h"
29*7295610fSBaptiste Daroussin #include "mandoc.h"
30*7295610fSBaptiste Daroussin #include "tbl.h"
3161d06d6bSBaptiste Daroussin #include "libmandoc.h"
32*7295610fSBaptiste Daroussin #include "tbl_parse.h"
33*7295610fSBaptiste Daroussin #include "tbl_int.h"
3461d06d6bSBaptiste Daroussin 
3561d06d6bSBaptiste Daroussin 
3661d06d6bSBaptiste Daroussin void
tbl_read(struct tbl_node * tbl,int ln,const char * p,int pos)3761d06d6bSBaptiste Daroussin tbl_read(struct tbl_node *tbl, int ln, const char *p, int pos)
3861d06d6bSBaptiste Daroussin {
3961d06d6bSBaptiste Daroussin 	const char	*cp;
4061d06d6bSBaptiste Daroussin 	int		 active;
4161d06d6bSBaptiste Daroussin 
4261d06d6bSBaptiste Daroussin 	/*
4361d06d6bSBaptiste Daroussin 	 * In the options section, proceed to the layout section
4461d06d6bSBaptiste Daroussin 	 * after a semicolon, or right away if there is no semicolon.
4561d06d6bSBaptiste Daroussin 	 * Ignore semicolons in arguments.
4661d06d6bSBaptiste Daroussin 	 */
4761d06d6bSBaptiste Daroussin 
4861d06d6bSBaptiste Daroussin 	if (tbl->part == TBL_PART_OPTS) {
4961d06d6bSBaptiste Daroussin 		tbl->part = TBL_PART_LAYOUT;
5061d06d6bSBaptiste Daroussin 		active = 1;
5161d06d6bSBaptiste Daroussin 		for (cp = p + pos; *cp != '\0'; cp++) {
5261d06d6bSBaptiste Daroussin 			switch (*cp) {
5361d06d6bSBaptiste Daroussin 			case '(':
5461d06d6bSBaptiste Daroussin 				active = 0;
5561d06d6bSBaptiste Daroussin 				continue;
5661d06d6bSBaptiste Daroussin 			case ')':
5761d06d6bSBaptiste Daroussin 				active = 1;
5861d06d6bSBaptiste Daroussin 				continue;
5961d06d6bSBaptiste Daroussin 			case ';':
6061d06d6bSBaptiste Daroussin 				if (active)
6161d06d6bSBaptiste Daroussin 					break;
6261d06d6bSBaptiste Daroussin 				continue;
6361d06d6bSBaptiste Daroussin 			default:
6461d06d6bSBaptiste Daroussin 				continue;
6561d06d6bSBaptiste Daroussin 			}
6661d06d6bSBaptiste Daroussin 			break;
6761d06d6bSBaptiste Daroussin 		}
6861d06d6bSBaptiste Daroussin 		if (*cp == ';') {
6961d06d6bSBaptiste Daroussin 			tbl_option(tbl, ln, p, &pos);
7061d06d6bSBaptiste Daroussin 			if (p[pos] == '\0')
7161d06d6bSBaptiste Daroussin 				return;
7261d06d6bSBaptiste Daroussin 		}
7361d06d6bSBaptiste Daroussin 	}
7461d06d6bSBaptiste Daroussin 
7561d06d6bSBaptiste Daroussin 	/* Process the other section types.  */
7661d06d6bSBaptiste Daroussin 
7761d06d6bSBaptiste Daroussin 	switch (tbl->part) {
7861d06d6bSBaptiste Daroussin 	case TBL_PART_LAYOUT:
7961d06d6bSBaptiste Daroussin 		tbl_layout(tbl, ln, p, pos);
8061d06d6bSBaptiste Daroussin 		break;
8161d06d6bSBaptiste Daroussin 	case TBL_PART_CDATA:
8261d06d6bSBaptiste Daroussin 		tbl_cdata(tbl, ln, p, pos);
8361d06d6bSBaptiste Daroussin 		break;
8461d06d6bSBaptiste Daroussin 	default:
8561d06d6bSBaptiste Daroussin 		tbl_data(tbl, ln, p, pos);
8661d06d6bSBaptiste Daroussin 		break;
8761d06d6bSBaptiste Daroussin 	}
8861d06d6bSBaptiste Daroussin }
8961d06d6bSBaptiste Daroussin 
9061d06d6bSBaptiste Daroussin struct tbl_node *
tbl_alloc(int pos,int line,struct tbl_node * last_tbl)91*7295610fSBaptiste Daroussin tbl_alloc(int pos, int line, struct tbl_node *last_tbl)
9261d06d6bSBaptiste Daroussin {
9361d06d6bSBaptiste Daroussin 	struct tbl_node	*tbl;
9461d06d6bSBaptiste Daroussin 
9561d06d6bSBaptiste Daroussin 	tbl = mandoc_calloc(1, sizeof(*tbl));
96*7295610fSBaptiste Daroussin 	if (last_tbl != NULL)
97*7295610fSBaptiste Daroussin 		last_tbl->next = tbl;
9861d06d6bSBaptiste Daroussin 	tbl->line = line;
9961d06d6bSBaptiste Daroussin 	tbl->pos = pos;
10061d06d6bSBaptiste Daroussin 	tbl->part = TBL_PART_OPTS;
10161d06d6bSBaptiste Daroussin 	tbl->opts.tab = '\t';
10261d06d6bSBaptiste Daroussin 	tbl->opts.decimal = '.';
10361d06d6bSBaptiste Daroussin 	return tbl;
10461d06d6bSBaptiste Daroussin }
10561d06d6bSBaptiste Daroussin 
10661d06d6bSBaptiste Daroussin void
tbl_free(struct tbl_node * tbl)10761d06d6bSBaptiste Daroussin tbl_free(struct tbl_node *tbl)
10861d06d6bSBaptiste Daroussin {
109*7295610fSBaptiste Daroussin 	struct tbl_node	*old_tbl;
11061d06d6bSBaptiste Daroussin 	struct tbl_row	*rp;
11161d06d6bSBaptiste Daroussin 	struct tbl_cell	*cp;
11261d06d6bSBaptiste Daroussin 	struct tbl_span	*sp;
11361d06d6bSBaptiste Daroussin 	struct tbl_dat	*dp;
11461d06d6bSBaptiste Daroussin 
115*7295610fSBaptiste Daroussin 	while (tbl != NULL) {
11661d06d6bSBaptiste Daroussin 		while ((rp = tbl->first_row) != NULL) {
11761d06d6bSBaptiste Daroussin 			tbl->first_row = rp->next;
11861d06d6bSBaptiste Daroussin 			while (rp->first != NULL) {
11961d06d6bSBaptiste Daroussin 				cp = rp->first;
12061d06d6bSBaptiste Daroussin 				rp->first = cp->next;
12161d06d6bSBaptiste Daroussin 				free(cp->wstr);
12261d06d6bSBaptiste Daroussin 				free(cp);
12361d06d6bSBaptiste Daroussin 			}
12461d06d6bSBaptiste Daroussin 			free(rp);
12561d06d6bSBaptiste Daroussin 		}
12661d06d6bSBaptiste Daroussin 		while ((sp = tbl->first_span) != NULL) {
12761d06d6bSBaptiste Daroussin 			tbl->first_span = sp->next;
12861d06d6bSBaptiste Daroussin 			while (sp->first != NULL) {
12961d06d6bSBaptiste Daroussin 				dp = sp->first;
13061d06d6bSBaptiste Daroussin 				sp->first = dp->next;
13161d06d6bSBaptiste Daroussin 				free(dp->string);
13261d06d6bSBaptiste Daroussin 				free(dp);
13361d06d6bSBaptiste Daroussin 			}
13461d06d6bSBaptiste Daroussin 			free(sp);
13561d06d6bSBaptiste Daroussin 		}
136*7295610fSBaptiste Daroussin 		old_tbl = tbl;
137*7295610fSBaptiste Daroussin 		tbl = tbl->next;
138*7295610fSBaptiste Daroussin 		free(old_tbl);
139*7295610fSBaptiste Daroussin 	}
14061d06d6bSBaptiste Daroussin }
14161d06d6bSBaptiste Daroussin 
14261d06d6bSBaptiste Daroussin void
tbl_restart(int line,int pos,struct tbl_node * tbl)14361d06d6bSBaptiste Daroussin tbl_restart(int line, int pos, struct tbl_node *tbl)
14461d06d6bSBaptiste Daroussin {
14561d06d6bSBaptiste Daroussin 	if (tbl->part == TBL_PART_CDATA)
146*7295610fSBaptiste Daroussin 		mandoc_msg(MANDOCERR_TBLDATA_BLK, line, pos, "T&");
14761d06d6bSBaptiste Daroussin 
14861d06d6bSBaptiste Daroussin 	tbl->part = TBL_PART_LAYOUT;
14961d06d6bSBaptiste Daroussin 	tbl->line = line;
15061d06d6bSBaptiste Daroussin 	tbl->pos = pos;
15161d06d6bSBaptiste Daroussin }
15261d06d6bSBaptiste Daroussin 
153*7295610fSBaptiste Daroussin struct tbl_span *
tbl_span(struct tbl_node * tbl)15461d06d6bSBaptiste Daroussin tbl_span(struct tbl_node *tbl)
15561d06d6bSBaptiste Daroussin {
15661d06d6bSBaptiste Daroussin 	struct tbl_span	 *span;
15761d06d6bSBaptiste Daroussin 
15861d06d6bSBaptiste Daroussin 	span = tbl->current_span ? tbl->current_span->next
15961d06d6bSBaptiste Daroussin 				 : tbl->first_span;
160*7295610fSBaptiste Daroussin 	if (span != NULL)
16161d06d6bSBaptiste Daroussin 		tbl->current_span = span;
16261d06d6bSBaptiste Daroussin 	return span;
16361d06d6bSBaptiste Daroussin }
16461d06d6bSBaptiste Daroussin 
16561d06d6bSBaptiste Daroussin int
tbl_end(struct tbl_node * tbl,int still_open)166*7295610fSBaptiste Daroussin tbl_end(struct tbl_node *tbl, int still_open)
16761d06d6bSBaptiste Daroussin {
16861d06d6bSBaptiste Daroussin 	struct tbl_span *sp;
16961d06d6bSBaptiste Daroussin 
170*7295610fSBaptiste Daroussin 	if (still_open)
171*7295610fSBaptiste Daroussin 		mandoc_msg(MANDOCERR_BLK_NOEND, tbl->line, tbl->pos, "TS");
172*7295610fSBaptiste Daroussin 	else if (tbl->part == TBL_PART_CDATA)
173*7295610fSBaptiste Daroussin 		mandoc_msg(MANDOCERR_TBLDATA_BLK, tbl->line, tbl->pos, "TE");
17461d06d6bSBaptiste Daroussin 
17561d06d6bSBaptiste Daroussin 	sp = tbl->first_span;
17661d06d6bSBaptiste Daroussin 	while (sp != NULL && sp->first == NULL)
17761d06d6bSBaptiste Daroussin 		sp = sp->next;
17861d06d6bSBaptiste Daroussin 	if (sp == NULL) {
179*7295610fSBaptiste Daroussin 		mandoc_msg(MANDOCERR_TBLDATA_NONE, tbl->line, tbl->pos, NULL);
18061d06d6bSBaptiste Daroussin 		return 0;
18161d06d6bSBaptiste Daroussin 	}
18261d06d6bSBaptiste Daroussin 	return 1;
18361d06d6bSBaptiste Daroussin }
184