xref: /netbsd-src/external/bsd/mdocml/dist/tbl.c (revision 6167eca2d062f3691f8b22e3b8ea212d6dde852a)
1*6167eca2Schristos /*	Id: tbl.c,v 1.46 2018/12/14 06:33:14 schwarze Exp  */
2c0d9444aSjoerg /*
39c655dd9Sjoerg  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
45c413d0cSchristos  * Copyright (c) 2011, 2015 Ingo Schwarze <schwarze@openbsd.org>
5c0d9444aSjoerg  *
6c0d9444aSjoerg  * Permission to use, copy, modify, and distribute this software for any
7c0d9444aSjoerg  * purpose with or without fee is hereby granted, provided that the above
8c0d9444aSjoerg  * copyright notice and this permission notice appear in all copies.
9c0d9444aSjoerg  *
10c0d9444aSjoerg  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11c0d9444aSjoerg  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12c0d9444aSjoerg  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13c0d9444aSjoerg  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14c0d9444aSjoerg  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15c0d9444aSjoerg  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16c0d9444aSjoerg  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17c0d9444aSjoerg  */
18c09c2a7bSnakayama #include "config.h"
195c413d0cSchristos 
205c413d0cSchristos #include <sys/types.h>
21c09c2a7bSnakayama 
22c0d9444aSjoerg #include <assert.h>
23c0d9444aSjoerg #include <stdio.h>
24c0d9444aSjoerg #include <stdlib.h>
25c0d9444aSjoerg #include <string.h>
26c0d9444aSjoerg #include <time.h>
27c0d9444aSjoerg 
285c413d0cSchristos #include "mandoc_aux.h"
29*6167eca2Schristos #include "mandoc.h"
30*6167eca2Schristos #include "tbl.h"
31c0d9444aSjoerg #include "libmandoc.h"
32*6167eca2Schristos #include "tbl_parse.h"
33*6167eca2Schristos #include "tbl_int.h"
34c0d9444aSjoerg 
35c0d9444aSjoerg 
3614e7489eSchristos void
tbl_read(struct tbl_node * tbl,int ln,const char * p,int pos)375c413d0cSchristos tbl_read(struct tbl_node *tbl, int ln, const char *p, int pos)
385c413d0cSchristos {
395c413d0cSchristos 	const char	*cp;
405c413d0cSchristos 	int		 active;
41c0d9444aSjoerg 
42c0d9444aSjoerg 	/*
435c413d0cSchristos 	 * In the options section, proceed to the layout section
445c413d0cSchristos 	 * after a semicolon, or right away if there is no semicolon.
455c413d0cSchristos 	 * Ignore semicolons in arguments.
46c0d9444aSjoerg 	 */
47c0d9444aSjoerg 
485c413d0cSchristos 	if (tbl->part == TBL_PART_OPTS) {
49c0d9444aSjoerg 		tbl->part = TBL_PART_LAYOUT;
505c413d0cSchristos 		active = 1;
515c413d0cSchristos 		for (cp = p + pos; *cp != '\0'; cp++) {
525c413d0cSchristos 			switch (*cp) {
535c413d0cSchristos 			case '(':
545c413d0cSchristos 				active = 0;
555c413d0cSchristos 				continue;
565c413d0cSchristos 			case ')':
575c413d0cSchristos 				active = 1;
585c413d0cSchristos 				continue;
595c413d0cSchristos 			case ';':
605c413d0cSchristos 				if (active)
615c413d0cSchristos 					break;
625c413d0cSchristos 				continue;
635c413d0cSchristos 			default:
645c413d0cSchristos 				continue;
655c413d0cSchristos 			}
665c413d0cSchristos 			break;
675c413d0cSchristos 		}
685c413d0cSchristos 		if (*cp == ';') {
695c413d0cSchristos 			tbl_option(tbl, ln, p, &pos);
705c413d0cSchristos 			if (p[pos] == '\0')
7114e7489eSchristos 				return;
725c413d0cSchristos 		}
735c413d0cSchristos 	}
74c0d9444aSjoerg 
755c413d0cSchristos 	/* Process the other section types.  */
76c0d9444aSjoerg 
77c0d9444aSjoerg 	switch (tbl->part) {
785c413d0cSchristos 	case TBL_PART_LAYOUT:
795c413d0cSchristos 		tbl_layout(tbl, ln, p, pos);
8014e7489eSchristos 		break;
815c413d0cSchristos 	case TBL_PART_CDATA:
8214e7489eSchristos 		tbl_cdata(tbl, ln, p, pos);
8314e7489eSchristos 		break;
84c0d9444aSjoerg 	default:
8514e7489eSchristos 		tbl_data(tbl, ln, p, pos);
86c0d9444aSjoerg 		break;
87c0d9444aSjoerg 	}
88c0d9444aSjoerg }
89c0d9444aSjoerg 
90c0d9444aSjoerg struct tbl_node *
tbl_alloc(int pos,int line,struct tbl_node * last_tbl)91*6167eca2Schristos tbl_alloc(int pos, int line, struct tbl_node *last_tbl)
92c0d9444aSjoerg {
93603fc4ebSjoerg 	struct tbl_node	*tbl;
94c0d9444aSjoerg 
955c413d0cSchristos 	tbl = mandoc_calloc(1, sizeof(*tbl));
96*6167eca2Schristos 	if (last_tbl != NULL)
97*6167eca2Schristos 		last_tbl->next = tbl;
98603fc4ebSjoerg 	tbl->line = line;
99603fc4ebSjoerg 	tbl->pos = pos;
100603fc4ebSjoerg 	tbl->part = TBL_PART_OPTS;
101603fc4ebSjoerg 	tbl->opts.tab = '\t';
102603fc4ebSjoerg 	tbl->opts.decimal = '.';
103f47368cfSchristos 	return tbl;
104c0d9444aSjoerg }
105c0d9444aSjoerg 
106c0d9444aSjoerg void
tbl_free(struct tbl_node * tbl)107603fc4ebSjoerg tbl_free(struct tbl_node *tbl)
108c0d9444aSjoerg {
109*6167eca2Schristos 	struct tbl_node	*old_tbl;
110c0d9444aSjoerg 	struct tbl_row	*rp;
111c0d9444aSjoerg 	struct tbl_cell	*cp;
112c0d9444aSjoerg 	struct tbl_span	*sp;
113c0d9444aSjoerg 	struct tbl_dat	*dp;
114c0d9444aSjoerg 
115*6167eca2Schristos 	while (tbl != NULL) {
1165c413d0cSchristos 		while ((rp = tbl->first_row) != NULL) {
117603fc4ebSjoerg 			tbl->first_row = rp->next;
1185c413d0cSchristos 			while (rp->first != NULL) {
119c0d9444aSjoerg 				cp = rp->first;
120c0d9444aSjoerg 				rp->first = cp->next;
12114e7489eSchristos 				free(cp->wstr);
122c0d9444aSjoerg 				free(cp);
123c0d9444aSjoerg 			}
124c0d9444aSjoerg 			free(rp);
125c0d9444aSjoerg 		}
1265c413d0cSchristos 		while ((sp = tbl->first_span) != NULL) {
127603fc4ebSjoerg 			tbl->first_span = sp->next;
1285c413d0cSchristos 			while (sp->first != NULL) {
129c0d9444aSjoerg 				dp = sp->first;
130c0d9444aSjoerg 				sp->first = dp->next;
131c0d9444aSjoerg 				free(dp->string);
132c0d9444aSjoerg 				free(dp);
133c0d9444aSjoerg 			}
134c0d9444aSjoerg 			free(sp);
135c0d9444aSjoerg 		}
136*6167eca2Schristos 		old_tbl = tbl;
137*6167eca2Schristos 		tbl = tbl->next;
138*6167eca2Schristos 		free(old_tbl);
139*6167eca2Schristos 	}
140c0d9444aSjoerg }
141c0d9444aSjoerg 
142c0d9444aSjoerg void
tbl_restart(int line,int pos,struct tbl_node * tbl)143c0d9444aSjoerg tbl_restart(int line, int pos, struct tbl_node *tbl)
144c0d9444aSjoerg {
1455c413d0cSchristos 	if (tbl->part == TBL_PART_CDATA)
146*6167eca2Schristos 		mandoc_msg(MANDOCERR_TBLDATA_BLK, line, pos, "T&");
147c0d9444aSjoerg 
148c0d9444aSjoerg 	tbl->part = TBL_PART_LAYOUT;
149c0d9444aSjoerg 	tbl->line = line;
150c0d9444aSjoerg 	tbl->pos = pos;
151c0d9444aSjoerg }
152c0d9444aSjoerg 
153*6167eca2Schristos struct tbl_span *
tbl_span(struct tbl_node * tbl)1549c655dd9Sjoerg tbl_span(struct tbl_node *tbl)
155c0d9444aSjoerg {
1569c655dd9Sjoerg 	struct tbl_span	 *span;
157c0d9444aSjoerg 
1589c655dd9Sjoerg 	span = tbl->current_span ? tbl->current_span->next
1599c655dd9Sjoerg 				 : tbl->first_span;
160*6167eca2Schristos 	if (span != NULL)
1619c655dd9Sjoerg 		tbl->current_span = span;
162f47368cfSchristos 	return span;
163c0d9444aSjoerg }
164c0d9444aSjoerg 
1655c413d0cSchristos int
tbl_end(struct tbl_node * tbl,int still_open)166*6167eca2Schristos tbl_end(struct tbl_node *tbl, int still_open)
167c0d9444aSjoerg {
1685c413d0cSchristos 	struct tbl_span *sp;
169b1e8115bSjoerg 
170*6167eca2Schristos 	if (still_open)
171*6167eca2Schristos 		mandoc_msg(MANDOCERR_BLK_NOEND, tbl->line, tbl->pos, "TS");
172*6167eca2Schristos 	else if (tbl->part == TBL_PART_CDATA)
173*6167eca2Schristos 		mandoc_msg(MANDOCERR_TBLDATA_BLK, tbl->line, tbl->pos, "TE");
174c0d9444aSjoerg 
1755c413d0cSchristos 	sp = tbl->first_span;
1765c413d0cSchristos 	while (sp != NULL && sp->first == NULL)
1775c413d0cSchristos 		sp = sp->next;
1785c413d0cSchristos 	if (sp == NULL) {
179*6167eca2Schristos 		mandoc_msg(MANDOCERR_TBLDATA_NONE, tbl->line, tbl->pos, NULL);
180f47368cfSchristos 		return 0;
181c0d9444aSjoerg 	}
182f47368cfSchristos 	return 1;
1835c413d0cSchristos }
184