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