xref: /openbsd-src/usr.bin/mandoc/tbl.c (revision 60395358bd468881069c44744132008b5b82170f)
1*60395358Sschwarze /*	$OpenBSD: tbl.c,v 1.28 2025/01/05 18:03:51 schwarze Exp $ */
2393cb51eSschwarze /*
32791bd1cSschwarze  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4bdf8ed0fSschwarze  * Copyright (c) 2011, 2015 Ingo Schwarze <schwarze@openbsd.org>
5393cb51eSschwarze  *
6393cb51eSschwarze  * Permission to use, copy, modify, and distribute this software for any
7393cb51eSschwarze  * purpose with or without fee is hereby granted, provided that the above
8393cb51eSschwarze  * copyright notice and this permission notice appear in all copies.
9393cb51eSschwarze  *
10393cb51eSschwarze  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11393cb51eSschwarze  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12393cb51eSschwarze  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13393cb51eSschwarze  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14393cb51eSschwarze  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15393cb51eSschwarze  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16393cb51eSschwarze  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17393cb51eSschwarze  */
1830997c59Sschwarze #include <sys/types.h>
1930997c59Sschwarze 
20393cb51eSschwarze #include <assert.h>
21393cb51eSschwarze #include <stdio.h>
22393cb51eSschwarze #include <stdlib.h>
23393cb51eSschwarze #include <string.h>
242791bd1cSschwarze #include <time.h>
25393cb51eSschwarze 
264f4f7972Sschwarze #include "mandoc_aux.h"
27fae2491eSschwarze #include "mandoc.h"
28fae2491eSschwarze #include "tbl.h"
292791bd1cSschwarze #include "libmandoc.h"
30fb382a01Sschwarze #include "tbl_parse.h"
31fb382a01Sschwarze #include "tbl_int.h"
32393cb51eSschwarze 
3349aff9f8Sschwarze 
34d93f8561Sschwarze void
3539aede77Sschwarze tbl_read(struct tbl_node *tbl, int ln, const char *p, int pos)
36393cb51eSschwarze {
372791bd1cSschwarze 	const char	*cp;
38bdf8ed0fSschwarze 	int		 active;
39393cb51eSschwarze 
402791bd1cSschwarze 	/*
41bdf8ed0fSschwarze 	 * In the options section, proceed to the layout section
42bdf8ed0fSschwarze 	 * after a semicolon, or right away if there is no semicolon.
43bdf8ed0fSschwarze 	 * Ignore semicolons in arguments.
442791bd1cSschwarze 	 */
45393cb51eSschwarze 
46bdf8ed0fSschwarze 	if (tbl->part == TBL_PART_OPTS) {
47393cb51eSschwarze 		tbl->part = TBL_PART_LAYOUT;
48bdf8ed0fSschwarze 		active = 1;
4939aede77Sschwarze 		for (cp = p + pos; *cp != '\0'; cp++) {
50bdf8ed0fSschwarze 			switch (*cp) {
51bdf8ed0fSschwarze 			case '(':
52bdf8ed0fSschwarze 				active = 0;
53bdf8ed0fSschwarze 				continue;
54bdf8ed0fSschwarze 			case ')':
55bdf8ed0fSschwarze 				active = 1;
56bdf8ed0fSschwarze 				continue;
57bdf8ed0fSschwarze 			case ';':
58bdf8ed0fSschwarze 				if (active)
59bdf8ed0fSschwarze 					break;
60bdf8ed0fSschwarze 				continue;
61bdf8ed0fSschwarze 			default:
62bdf8ed0fSschwarze 				continue;
63bdf8ed0fSschwarze 			}
64bdf8ed0fSschwarze 			break;
65bdf8ed0fSschwarze 		}
66bdf8ed0fSschwarze 		if (*cp == ';') {
6739aede77Sschwarze 			tbl_option(tbl, ln, p, &pos);
6839aede77Sschwarze 			if (p[pos] == '\0')
69d93f8561Sschwarze 				return;
70bdf8ed0fSschwarze 		}
71bdf8ed0fSschwarze 	}
72393cb51eSschwarze 
73bdf8ed0fSschwarze 	/* Process the other section types.  */
742791bd1cSschwarze 
75393cb51eSschwarze 	switch (tbl->part) {
7649aff9f8Sschwarze 	case TBL_PART_LAYOUT:
7739aede77Sschwarze 		tbl_layout(tbl, ln, p, pos);
78d93f8561Sschwarze 		break;
7949aff9f8Sschwarze 	case TBL_PART_CDATA:
80d93f8561Sschwarze 		tbl_cdata(tbl, ln, p, pos);
81d93f8561Sschwarze 		break;
82393cb51eSschwarze 	default:
83d93f8561Sschwarze 		tbl_data(tbl, ln, p, pos);
84393cb51eSschwarze 		break;
85393cb51eSschwarze 	}
86393cb51eSschwarze }
87393cb51eSschwarze 
882791bd1cSschwarze struct tbl_node *
8991305757Sschwarze tbl_alloc(int pos, int line, struct tbl_node *last_tbl)
90393cb51eSschwarze {
91e263f8eaSschwarze 	struct tbl_node	*tbl;
92393cb51eSschwarze 
9321da0636Sschwarze 	tbl = mandoc_calloc(1, sizeof(*tbl));
94fb382a01Sschwarze 	if (last_tbl != NULL)
95fb382a01Sschwarze 		last_tbl->next = tbl;
96e263f8eaSschwarze 	tbl->line = line;
97e263f8eaSschwarze 	tbl->pos = pos;
98e263f8eaSschwarze 	tbl->part = TBL_PART_OPTS;
99e263f8eaSschwarze 	tbl->opts.tab = '\t';
100e263f8eaSschwarze 	tbl->opts.decimal = '.';
101526e306bSschwarze 	return tbl;
102393cb51eSschwarze }
103393cb51eSschwarze 
1042791bd1cSschwarze void
105e263f8eaSschwarze tbl_free(struct tbl_node *tbl)
106393cb51eSschwarze {
107fb382a01Sschwarze 	struct tbl_node	*old_tbl;
1082791bd1cSschwarze 	struct tbl_row	*rp;
109393cb51eSschwarze 	struct tbl_cell	*cp;
1102791bd1cSschwarze 	struct tbl_span	*sp;
1112791bd1cSschwarze 	struct tbl_dat	*dp;
112393cb51eSschwarze 
113fb382a01Sschwarze 	while (tbl != NULL) {
11421da0636Sschwarze 		while ((rp = tbl->first_row) != NULL) {
115e263f8eaSschwarze 			tbl->first_row = rp->next;
11621da0636Sschwarze 			while (rp->first != NULL) {
1172791bd1cSschwarze 				cp = rp->first;
1182791bd1cSschwarze 				rp->first = cp->next;
1192791bd1cSschwarze 				free(cp);
1202791bd1cSschwarze 			}
1212791bd1cSschwarze 			free(rp);
122393cb51eSschwarze 		}
12321da0636Sschwarze 		while ((sp = tbl->first_span) != NULL) {
124e263f8eaSschwarze 			tbl->first_span = sp->next;
12521da0636Sschwarze 			while (sp->first != NULL) {
1262791bd1cSschwarze 				dp = sp->first;
1272791bd1cSschwarze 				sp->first = dp->next;
1282791bd1cSschwarze 				free(dp->string);
1292791bd1cSschwarze 				free(dp);
1302791bd1cSschwarze 			}
1312791bd1cSschwarze 			free(sp);
132393cb51eSschwarze 		}
133fb382a01Sschwarze 		old_tbl = tbl;
134fb382a01Sschwarze 		tbl = tbl->next;
135fb382a01Sschwarze 		free(old_tbl);
136fb382a01Sschwarze 	}
137393cb51eSschwarze }
138393cb51eSschwarze 
1392791bd1cSschwarze void
1402791bd1cSschwarze tbl_restart(int line, int pos, struct tbl_node *tbl)
1412791bd1cSschwarze {
14292ff8da6Sschwarze 	if (tbl->part == TBL_PART_CDATA)
143a5a5f808Sschwarze 		mandoc_msg(MANDOCERR_TBLDATA_BLK, line, pos, "T&");
144393cb51eSschwarze 
1452791bd1cSschwarze 	tbl->part = TBL_PART_LAYOUT;
1462791bd1cSschwarze 	tbl->line = line;
1472791bd1cSschwarze 	tbl->pos = pos;
1482791bd1cSschwarze }
1492791bd1cSschwarze 
150fb382a01Sschwarze struct tbl_span *
1517374e4feSschwarze tbl_span(struct tbl_node *tbl)
152393cb51eSschwarze {
1537374e4feSschwarze 	struct tbl_span	 *span;
154393cb51eSschwarze 
1557374e4feSschwarze 	span = tbl->current_span ? tbl->current_span->next
1567374e4feSschwarze 				 : tbl->first_span;
157fb382a01Sschwarze 	if (span != NULL)
1587374e4feSschwarze 		tbl->current_span = span;
159526e306bSschwarze 	return span;
160393cb51eSschwarze }
161393cb51eSschwarze 
16292ff8da6Sschwarze int
163fb382a01Sschwarze tbl_end(struct tbl_node *tbl, int still_open)
164393cb51eSschwarze {
165fd9b947eSschwarze 	struct tbl_span *sp;
166f8618d99Sschwarze 
167fb382a01Sschwarze 	if (still_open)
168a5a5f808Sschwarze 		mandoc_msg(MANDOCERR_BLK_NOEND, tbl->line, tbl->pos, "TS");
169fb382a01Sschwarze 	else if (tbl->part == TBL_PART_CDATA)
170a5a5f808Sschwarze 		mandoc_msg(MANDOCERR_TBLDATA_BLK, tbl->line, tbl->pos, "TE");
17192ff8da6Sschwarze 
172fd9b947eSschwarze 	sp = tbl->first_span;
173fd9b947eSschwarze 	while (sp != NULL && sp->first == NULL)
174fd9b947eSschwarze 		sp = sp->next;
17592ff8da6Sschwarze 	if (sp == NULL) {
176a5a5f808Sschwarze 		mandoc_msg(MANDOCERR_TBLDATA_NONE, tbl->line, tbl->pos, NULL);
177526e306bSschwarze 		return 0;
17892ff8da6Sschwarze 	}
179526e306bSschwarze 	return 1;
180393cb51eSschwarze }
181