1*cec8643bSMichal Nowak /* $Id: tbl.c,v 1.46 2018/12/14 06:33:14 schwarze Exp $ */
295c635efSGarrett D'Amore /*
395c635efSGarrett D'Amore * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4260e9a87SYuri Pankov * Copyright (c) 2011, 2015 Ingo Schwarze <schwarze@openbsd.org>
595c635efSGarrett D'Amore *
695c635efSGarrett D'Amore * Permission to use, copy, modify, and distribute this software for any
795c635efSGarrett D'Amore * purpose with or without fee is hereby granted, provided that the above
895c635efSGarrett D'Amore * copyright notice and this permission notice appear in all copies.
995c635efSGarrett D'Amore *
1095c635efSGarrett D'Amore * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1195c635efSGarrett D'Amore * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1295c635efSGarrett D'Amore * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1395c635efSGarrett D'Amore * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1495c635efSGarrett D'Amore * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1595c635efSGarrett D'Amore * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1695c635efSGarrett D'Amore * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1795c635efSGarrett D'Amore */
1895c635efSGarrett D'Amore #include "config.h"
19260e9a87SYuri Pankov
20260e9a87SYuri Pankov #include <sys/types.h>
2195c635efSGarrett D'Amore
2295c635efSGarrett D'Amore #include <assert.h>
2395c635efSGarrett D'Amore #include <stdio.h>
2495c635efSGarrett D'Amore #include <stdlib.h>
2595c635efSGarrett D'Amore #include <string.h>
2695c635efSGarrett D'Amore #include <time.h>
2795c635efSGarrett D'Amore
28260e9a87SYuri Pankov #include "mandoc_aux.h"
29*cec8643bSMichal Nowak #include "mandoc.h"
30*cec8643bSMichal Nowak #include "tbl.h"
3195c635efSGarrett D'Amore #include "libmandoc.h"
32*cec8643bSMichal Nowak #include "tbl_parse.h"
33*cec8643bSMichal Nowak #include "tbl_int.h"
3495c635efSGarrett D'Amore
35260e9a87SYuri Pankov
36c66b8046SYuri Pankov void
tbl_read(struct tbl_node * tbl,int ln,const char * p,int pos)37260e9a87SYuri Pankov tbl_read(struct tbl_node *tbl, int ln, const char *p, int pos)
3895c635efSGarrett D'Amore {
3995c635efSGarrett D'Amore const char *cp;
40260e9a87SYuri Pankov int active;
4195c635efSGarrett D'Amore
4295c635efSGarrett D'Amore /*
43260e9a87SYuri Pankov * In the options section, proceed to the layout section
44260e9a87SYuri Pankov * after a semicolon, or right away if there is no semicolon.
45260e9a87SYuri Pankov * Ignore semicolons in arguments.
4695c635efSGarrett D'Amore */
4795c635efSGarrett D'Amore
48260e9a87SYuri Pankov if (tbl->part == TBL_PART_OPTS) {
49260e9a87SYuri Pankov tbl->part = TBL_PART_LAYOUT;
50260e9a87SYuri Pankov active = 1;
51260e9a87SYuri Pankov for (cp = p + pos; *cp != '\0'; cp++) {
52260e9a87SYuri Pankov switch (*cp) {
53260e9a87SYuri Pankov case '(':
54260e9a87SYuri Pankov active = 0;
55260e9a87SYuri Pankov continue;
56260e9a87SYuri Pankov case ')':
57260e9a87SYuri Pankov active = 1;
58260e9a87SYuri Pankov continue;
59260e9a87SYuri Pankov case ';':
60260e9a87SYuri Pankov if (active)
61260e9a87SYuri Pankov break;
62260e9a87SYuri Pankov continue;
63260e9a87SYuri Pankov default:
64260e9a87SYuri Pankov continue;
65260e9a87SYuri Pankov }
66260e9a87SYuri Pankov break;
67260e9a87SYuri Pankov }
68260e9a87SYuri Pankov if (*cp == ';') {
69260e9a87SYuri Pankov tbl_option(tbl, ln, p, &pos);
70260e9a87SYuri Pankov if (p[pos] == '\0')
71c66b8046SYuri Pankov return;
72260e9a87SYuri Pankov }
73260e9a87SYuri Pankov }
7495c635efSGarrett D'Amore
75260e9a87SYuri Pankov /* Process the other section types. */
7695c635efSGarrett D'Amore
7795c635efSGarrett D'Amore switch (tbl->part) {
78260e9a87SYuri Pankov case TBL_PART_LAYOUT:
79260e9a87SYuri Pankov tbl_layout(tbl, ln, p, pos);
80c66b8046SYuri Pankov break;
81260e9a87SYuri Pankov case TBL_PART_CDATA:
82c66b8046SYuri Pankov tbl_cdata(tbl, ln, p, pos);
83c66b8046SYuri Pankov break;
8495c635efSGarrett D'Amore default:
85c66b8046SYuri Pankov tbl_data(tbl, ln, p, pos);
8695c635efSGarrett D'Amore break;
8795c635efSGarrett D'Amore }
8895c635efSGarrett D'Amore }
8995c635efSGarrett D'Amore
9095c635efSGarrett D'Amore struct tbl_node *
tbl_alloc(int pos,int line,struct tbl_node * last_tbl)91*cec8643bSMichal Nowak tbl_alloc(int pos, int line, struct tbl_node *last_tbl)
9295c635efSGarrett D'Amore {
93698f87a4SGarrett D'Amore struct tbl_node *tbl;
94698f87a4SGarrett D'Amore
95260e9a87SYuri Pankov tbl = mandoc_calloc(1, sizeof(*tbl));
96*cec8643bSMichal Nowak if (last_tbl != NULL)
97*cec8643bSMichal Nowak last_tbl->next = tbl;
98698f87a4SGarrett D'Amore tbl->line = line;
99698f87a4SGarrett D'Amore tbl->pos = pos;
100698f87a4SGarrett D'Amore tbl->part = TBL_PART_OPTS;
101698f87a4SGarrett D'Amore tbl->opts.tab = '\t';
102698f87a4SGarrett D'Amore tbl->opts.decimal = '.';
103371584c2SYuri Pankov return tbl;
10495c635efSGarrett D'Amore }
10595c635efSGarrett D'Amore
10695c635efSGarrett D'Amore void
tbl_free(struct tbl_node * tbl)107698f87a4SGarrett D'Amore tbl_free(struct tbl_node *tbl)
10895c635efSGarrett D'Amore {
109*cec8643bSMichal Nowak struct tbl_node *old_tbl;
11095c635efSGarrett D'Amore struct tbl_row *rp;
11195c635efSGarrett D'Amore struct tbl_cell *cp;
11295c635efSGarrett D'Amore struct tbl_span *sp;
11395c635efSGarrett D'Amore struct tbl_dat *dp;
11495c635efSGarrett D'Amore
115*cec8643bSMichal Nowak while (tbl != NULL) {
116*cec8643bSMichal Nowak while ((rp = tbl->first_row) != NULL) {
117*cec8643bSMichal Nowak tbl->first_row = rp->next;
118*cec8643bSMichal Nowak while (rp->first != NULL) {
119*cec8643bSMichal Nowak cp = rp->first;
120*cec8643bSMichal Nowak rp->first = cp->next;
121*cec8643bSMichal Nowak free(cp->wstr);
122*cec8643bSMichal Nowak free(cp);
123*cec8643bSMichal Nowak }
124*cec8643bSMichal Nowak free(rp);
12595c635efSGarrett D'Amore }
126*cec8643bSMichal Nowak while ((sp = tbl->first_span) != NULL) {
127*cec8643bSMichal Nowak tbl->first_span = sp->next;
128*cec8643bSMichal Nowak while (sp->first != NULL) {
129*cec8643bSMichal Nowak dp = sp->first;
130*cec8643bSMichal Nowak sp->first = dp->next;
131*cec8643bSMichal Nowak free(dp->string);
132*cec8643bSMichal Nowak free(dp);
133*cec8643bSMichal Nowak }
134*cec8643bSMichal Nowak free(sp);
13595c635efSGarrett D'Amore }
136*cec8643bSMichal Nowak old_tbl = tbl;
137*cec8643bSMichal Nowak tbl = tbl->next;
138*cec8643bSMichal Nowak free(old_tbl);
13995c635efSGarrett D'Amore }
14095c635efSGarrett D'Amore }
14195c635efSGarrett D'Amore
14295c635efSGarrett D'Amore void
tbl_restart(int line,int pos,struct tbl_node * tbl)14395c635efSGarrett D'Amore tbl_restart(int line, int pos, struct tbl_node *tbl)
14495c635efSGarrett D'Amore {
145260e9a87SYuri Pankov if (tbl->part == TBL_PART_CDATA)
146*cec8643bSMichal Nowak mandoc_msg(MANDOCERR_TBLDATA_BLK, line, pos, "T&");
14795c635efSGarrett D'Amore
14895c635efSGarrett D'Amore tbl->part = TBL_PART_LAYOUT;
14995c635efSGarrett D'Amore tbl->line = line;
15095c635efSGarrett D'Amore tbl->pos = pos;
15195c635efSGarrett D'Amore }
15295c635efSGarrett D'Amore
153*cec8643bSMichal Nowak struct tbl_span *
tbl_span(struct tbl_node * tbl)15495c635efSGarrett D'Amore tbl_span(struct tbl_node *tbl)
15595c635efSGarrett D'Amore {
15695c635efSGarrett D'Amore struct tbl_span *span;
15795c635efSGarrett D'Amore
15895c635efSGarrett D'Amore span = tbl->current_span ? tbl->current_span->next
15995c635efSGarrett D'Amore : tbl->first_span;
160*cec8643bSMichal Nowak if (span != NULL)
16195c635efSGarrett D'Amore tbl->current_span = span;
162371584c2SYuri Pankov return span;
16395c635efSGarrett D'Amore }
16495c635efSGarrett D'Amore
165260e9a87SYuri Pankov int
tbl_end(struct tbl_node * tbl,int still_open)166*cec8643bSMichal Nowak tbl_end(struct tbl_node *tbl, int still_open)
16795c635efSGarrett D'Amore {
168260e9a87SYuri Pankov struct tbl_span *sp;
16995c635efSGarrett D'Amore
170*cec8643bSMichal Nowak if (still_open)
171*cec8643bSMichal Nowak mandoc_msg(MANDOCERR_BLK_NOEND, tbl->line, tbl->pos, "TS");
172*cec8643bSMichal Nowak else if (tbl->part == TBL_PART_CDATA)
173*cec8643bSMichal Nowak mandoc_msg(MANDOCERR_TBLDATA_BLK, tbl->line, tbl->pos, "TE");
174260e9a87SYuri Pankov
175260e9a87SYuri Pankov sp = tbl->first_span;
176260e9a87SYuri Pankov while (sp != NULL && sp->first == NULL)
177260e9a87SYuri Pankov sp = sp->next;
178260e9a87SYuri Pankov if (sp == NULL) {
179*cec8643bSMichal Nowak mandoc_msg(MANDOCERR_TBLDATA_NONE, tbl->line, tbl->pos, NULL);
180371584c2SYuri Pankov return 0;
181260e9a87SYuri Pankov }
182371584c2SYuri Pankov return 1;
18395c635efSGarrett D'Amore }
184