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