Home | History | Annotate | Line # | Download | only in dist
      1 /*	Id: tbl.c,v 1.46 2018/12/14 06:33:14 schwarze Exp  */
      2 /*
      3  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps (at) bsd.lv>
      4  * Copyright (c) 2011, 2015 Ingo Schwarze <schwarze (at) openbsd.org>
      5  *
      6  * Permission to use, copy, modify, and distribute this software for any
      7  * purpose with or without fee is hereby granted, provided that the above
      8  * copyright notice and this permission notice appear in all copies.
      9  *
     10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     17  */
     18 #include "config.h"
     19 
     20 #include <sys/types.h>
     21 
     22 #include <assert.h>
     23 #include <stdio.h>
     24 #include <stdlib.h>
     25 #include <string.h>
     26 #include <time.h>
     27 
     28 #include "mandoc_aux.h"
     29 #include "mandoc.h"
     30 #include "tbl.h"
     31 #include "libmandoc.h"
     32 #include "tbl_parse.h"
     33 #include "tbl_int.h"
     34 
     35 
     36 void
     37 tbl_read(struct tbl_node *tbl, int ln, const char *p, int pos)
     38 {
     39 	const char	*cp;
     40 	int		 active;
     41 
     42 	/*
     43 	 * In the options section, proceed to the layout section
     44 	 * after a semicolon, or right away if there is no semicolon.
     45 	 * Ignore semicolons in arguments.
     46 	 */
     47 
     48 	if (tbl->part == TBL_PART_OPTS) {
     49 		tbl->part = TBL_PART_LAYOUT;
     50 		active = 1;
     51 		for (cp = p + pos; *cp != '\0'; cp++) {
     52 			switch (*cp) {
     53 			case '(':
     54 				active = 0;
     55 				continue;
     56 			case ')':
     57 				active = 1;
     58 				continue;
     59 			case ';':
     60 				if (active)
     61 					break;
     62 				continue;
     63 			default:
     64 				continue;
     65 			}
     66 			break;
     67 		}
     68 		if (*cp == ';') {
     69 			tbl_option(tbl, ln, p, &pos);
     70 			if (p[pos] == '\0')
     71 				return;
     72 		}
     73 	}
     74 
     75 	/* Process the other section types.  */
     76 
     77 	switch (tbl->part) {
     78 	case TBL_PART_LAYOUT:
     79 		tbl_layout(tbl, ln, p, pos);
     80 		break;
     81 	case TBL_PART_CDATA:
     82 		tbl_cdata(tbl, ln, p, pos);
     83 		break;
     84 	default:
     85 		tbl_data(tbl, ln, p, pos);
     86 		break;
     87 	}
     88 }
     89 
     90 struct tbl_node *
     91 tbl_alloc(int pos, int line, struct tbl_node *last_tbl)
     92 {
     93 	struct tbl_node	*tbl;
     94 
     95 	tbl = mandoc_calloc(1, sizeof(*tbl));
     96 	if (last_tbl != NULL)
     97 		last_tbl->next = tbl;
     98 	tbl->line = line;
     99 	tbl->pos = pos;
    100 	tbl->part = TBL_PART_OPTS;
    101 	tbl->opts.tab = '\t';
    102 	tbl->opts.decimal = '.';
    103 	return tbl;
    104 }
    105 
    106 void
    107 tbl_free(struct tbl_node *tbl)
    108 {
    109 	struct tbl_node	*old_tbl;
    110 	struct tbl_row	*rp;
    111 	struct tbl_cell	*cp;
    112 	struct tbl_span	*sp;
    113 	struct tbl_dat	*dp;
    114 
    115 	while (tbl != NULL) {
    116 		while ((rp = tbl->first_row) != NULL) {
    117 			tbl->first_row = rp->next;
    118 			while (rp->first != NULL) {
    119 				cp = rp->first;
    120 				rp->first = cp->next;
    121 				free(cp->wstr);
    122 				free(cp);
    123 			}
    124 			free(rp);
    125 		}
    126 		while ((sp = tbl->first_span) != NULL) {
    127 			tbl->first_span = sp->next;
    128 			while (sp->first != NULL) {
    129 				dp = sp->first;
    130 				sp->first = dp->next;
    131 				free(dp->string);
    132 				free(dp);
    133 			}
    134 			free(sp);
    135 		}
    136 		old_tbl = tbl;
    137 		tbl = tbl->next;
    138 		free(old_tbl);
    139 	}
    140 }
    141 
    142 void
    143 tbl_restart(int line, int pos, struct tbl_node *tbl)
    144 {
    145 	if (tbl->part == TBL_PART_CDATA)
    146 		mandoc_msg(MANDOCERR_TBLDATA_BLK, line, pos, "T&");
    147 
    148 	tbl->part = TBL_PART_LAYOUT;
    149 	tbl->line = line;
    150 	tbl->pos = pos;
    151 }
    152 
    153 struct tbl_span *
    154 tbl_span(struct tbl_node *tbl)
    155 {
    156 	struct tbl_span	 *span;
    157 
    158 	span = tbl->current_span ? tbl->current_span->next
    159 				 : tbl->first_span;
    160 	if (span != NULL)
    161 		tbl->current_span = span;
    162 	return span;
    163 }
    164 
    165 int
    166 tbl_end(struct tbl_node *tbl, int still_open)
    167 {
    168 	struct tbl_span *sp;
    169 
    170 	if (still_open)
    171 		mandoc_msg(MANDOCERR_BLK_NOEND, tbl->line, tbl->pos, "TS");
    172 	else if (tbl->part == TBL_PART_CDATA)
    173 		mandoc_msg(MANDOCERR_TBLDATA_BLK, tbl->line, tbl->pos, "TE");
    174 
    175 	sp = tbl->first_span;
    176 	while (sp != NULL && sp->first == NULL)
    177 		sp = sp->next;
    178 	if (sp == NULL) {
    179 		mandoc_msg(MANDOCERR_TBLDATA_NONE, tbl->line, tbl->pos, NULL);
    180 		return 0;
    181 	}
    182 	return 1;
    183 }
    184