1241675Suqs/*	$Id: tbl.c,v 1.26 2011/07/25 15:37:00 kristaps Exp $ */
2241675Suqs/*
3241675Suqs * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4241675Suqs * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
5241675Suqs *
6241675Suqs * Permission to use, copy, modify, and distribute this software for any
7241675Suqs * purpose with or without fee is hereby granted, provided that the above
8241675Suqs * copyright notice and this permission notice appear in all copies.
9241675Suqs *
10241675Suqs * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11241675Suqs * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12241675Suqs * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13241675Suqs * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14241675Suqs * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15241675Suqs * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16241675Suqs * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17241675Suqs */
18241675Suqs#ifdef HAVE_CONFIG_H
19241675Suqs#include "config.h"
20241675Suqs#endif
21241675Suqs
22241675Suqs#include <assert.h>
23241675Suqs#include <stdio.h>
24241675Suqs#include <stdlib.h>
25241675Suqs#include <string.h>
26241675Suqs#include <time.h>
27241675Suqs
28241675Suqs#include "mandoc.h"
29241675Suqs#include "libmandoc.h"
30241675Suqs#include "libroff.h"
31241675Suqs
32241675Suqsenum rofferr
33241675Suqstbl_read(struct tbl_node *tbl, int ln, const char *p, int offs)
34241675Suqs{
35241675Suqs	int		 len;
36241675Suqs	const char	*cp;
37241675Suqs
38241675Suqs	cp = &p[offs];
39241675Suqs	len = (int)strlen(cp);
40241675Suqs
41241675Suqs	/*
42241675Suqs	 * If we're in the options section and we don't have a
43241675Suqs	 * terminating semicolon, assume we've moved directly into the
44241675Suqs	 * layout section.  No need to report a warning: this is,
45241675Suqs	 * apparently, standard behaviour.
46241675Suqs	 */
47241675Suqs
48241675Suqs	if (TBL_PART_OPTS == tbl->part && len)
49241675Suqs		if (';' != cp[len - 1])
50241675Suqs			tbl->part = TBL_PART_LAYOUT;
51241675Suqs
52241675Suqs	/* Now process each logical section of the table.  */
53241675Suqs
54241675Suqs	switch (tbl->part) {
55241675Suqs	case (TBL_PART_OPTS):
56241675Suqs		return(tbl_option(tbl, ln, p) ? ROFF_IGN : ROFF_ERR);
57241675Suqs	case (TBL_PART_LAYOUT):
58241675Suqs		return(tbl_layout(tbl, ln, p) ? ROFF_IGN : ROFF_ERR);
59241675Suqs	case (TBL_PART_CDATA):
60241675Suqs		return(tbl_cdata(tbl, ln, p) ? ROFF_TBL : ROFF_IGN);
61241675Suqs	default:
62241675Suqs		break;
63241675Suqs	}
64241675Suqs
65241675Suqs	/*
66241675Suqs	 * This only returns zero if the line is empty, so we ignore it
67241675Suqs	 * and continue on.
68241675Suqs	 */
69241675Suqs	return(tbl_data(tbl, ln, p) ? ROFF_TBL : ROFF_IGN);
70241675Suqs}
71241675Suqs
72241675Suqsstruct tbl_node *
73241675Suqstbl_alloc(int pos, int line, struct mparse *parse)
74241675Suqs{
75241675Suqs	struct tbl_node	*p;
76241675Suqs
77241675Suqs	p = mandoc_calloc(1, sizeof(struct tbl_node));
78241675Suqs	p->line = line;
79241675Suqs	p->pos = pos;
80241675Suqs	p->parse = parse;
81241675Suqs	p->part = TBL_PART_OPTS;
82241675Suqs	p->opts.tab = '\t';
83241675Suqs	p->opts.linesize = 12;
84241675Suqs	p->opts.decimal = '.';
85241675Suqs	return(p);
86241675Suqs}
87241675Suqs
88241675Suqsvoid
89241675Suqstbl_free(struct tbl_node *p)
90241675Suqs{
91241675Suqs	struct tbl_row	*rp;
92241675Suqs	struct tbl_cell	*cp;
93241675Suqs	struct tbl_span	*sp;
94241675Suqs	struct tbl_dat	*dp;
95241675Suqs	struct tbl_head	*hp;
96241675Suqs
97241675Suqs	while (NULL != (rp = p->first_row)) {
98241675Suqs		p->first_row = rp->next;
99241675Suqs		while (rp->first) {
100241675Suqs			cp = rp->first;
101241675Suqs			rp->first = cp->next;
102241675Suqs			free(cp);
103241675Suqs		}
104241675Suqs		free(rp);
105241675Suqs	}
106241675Suqs
107241675Suqs	while (NULL != (sp = p->first_span)) {
108241675Suqs		p->first_span = sp->next;
109241675Suqs		while (sp->first) {
110241675Suqs			dp = sp->first;
111241675Suqs			sp->first = dp->next;
112241675Suqs			if (dp->string)
113241675Suqs				free(dp->string);
114241675Suqs			free(dp);
115241675Suqs		}
116241675Suqs		free(sp);
117241675Suqs	}
118241675Suqs
119241675Suqs	while (NULL != (hp = p->first_head)) {
120241675Suqs		p->first_head = hp->next;
121241675Suqs		free(hp);
122241675Suqs	}
123241675Suqs
124241675Suqs	free(p);
125241675Suqs}
126241675Suqs
127241675Suqsvoid
128241675Suqstbl_restart(int line, int pos, struct tbl_node *tbl)
129241675Suqs{
130241675Suqs	if (TBL_PART_CDATA == tbl->part)
131241675Suqs		mandoc_msg(MANDOCERR_TBLBLOCK, tbl->parse,
132241675Suqs				tbl->line, tbl->pos, NULL);
133241675Suqs
134241675Suqs	tbl->part = TBL_PART_LAYOUT;
135241675Suqs	tbl->line = line;
136241675Suqs	tbl->pos = pos;
137241675Suqs
138241675Suqs	if (NULL == tbl->first_span || NULL == tbl->first_span->first)
139241675Suqs		mandoc_msg(MANDOCERR_TBLNODATA, tbl->parse,
140241675Suqs				tbl->line, tbl->pos, NULL);
141241675Suqs}
142241675Suqs
143241675Suqsconst struct tbl_span *
144241675Suqstbl_span(struct tbl_node *tbl)
145241675Suqs{
146241675Suqs	struct tbl_span	 *span;
147241675Suqs
148241675Suqs	assert(tbl);
149241675Suqs	span = tbl->current_span ? tbl->current_span->next
150241675Suqs				 : tbl->first_span;
151241675Suqs	if (span)
152241675Suqs		tbl->current_span = span;
153241675Suqs	return(span);
154241675Suqs}
155241675Suqs
156241675Suqsvoid
157241675Suqstbl_end(struct tbl_node **tblp)
158241675Suqs{
159241675Suqs	struct tbl_node	*tbl;
160241675Suqs
161241675Suqs	tbl = *tblp;
162241675Suqs	*tblp = NULL;
163241675Suqs
164241675Suqs	if (NULL == tbl->first_span || NULL == tbl->first_span->first)
165241675Suqs		mandoc_msg(MANDOCERR_TBLNODATA, tbl->parse,
166241675Suqs				tbl->line, tbl->pos, NULL);
167241675Suqs
168241675Suqs	if (tbl->last_span)
169241675Suqs		tbl->last_span->flags |= TBL_SPAN_LAST;
170241675Suqs
171241675Suqs	if (TBL_PART_CDATA == tbl->part)
172241675Suqs		mandoc_msg(MANDOCERR_TBLBLOCK, tbl->parse,
173241675Suqs				tbl->line, tbl->pos, NULL);
174241675Suqs}
175241675Suqs
176