Home | History | Annotate | Line # | Download | only in dist
tbl_data.c revision 1.1
      1 /*	$Vendor-Id: tbl_data.c,v 1.15 2011/01/09 23:14:41 kristaps Exp $ */
      2 /*
      3  * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps (at) bsd.lv>
      4  *
      5  * Permission to use, copy, modify, and distribute this software for any
      6  * purpose with or without fee is hereby granted, provided that the above
      7  * copyright notice and this permission notice appear in all copies.
      8  *
      9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     16  */
     17 #ifdef HAVE_CONFIG_H
     18 #include "config.h"
     19 #endif
     20 
     21 #include <assert.h>
     22 #include <ctype.h>
     23 #include <stdlib.h>
     24 #include <string.h>
     25 #include <time.h>
     26 
     27 #include "mandoc.h"
     28 #include "libmandoc.h"
     29 #include "libroff.h"
     30 
     31 static	int	data(struct tbl_node *, struct tbl_span *,
     32 			int, const char *, int *);
     33 
     34 static int
     35 data(struct tbl_node *tbl, struct tbl_span *dp,
     36 		int ln, const char *p, int *pos)
     37 {
     38 	struct tbl_dat	*dat;
     39 	struct tbl_cell	*cp;
     40 	int		 sv;
     41 
     42 	cp = NULL;
     43 	if (dp->last && dp->last->layout)
     44 		cp = dp->last->layout->next;
     45 	else if (NULL == dp->last)
     46 		cp = dp->layout->first;
     47 
     48 	/*
     49 	 * Skip over spanners and vertical lines to data formats, since
     50 	 * we want to match data with data layout cells in the header.
     51 	 */
     52 
     53 	while (cp && (TBL_CELL_VERT == cp->pos ||
     54 				TBL_CELL_DVERT == cp->pos ||
     55 				TBL_CELL_SPAN == cp->pos))
     56 		cp = cp->next;
     57 
     58 	dat = mandoc_calloc(1, sizeof(struct tbl_dat));
     59 	dat->layout = cp;
     60 	dat->pos = TBL_DATA_NONE;
     61 
     62 	if (NULL == dat->layout)
     63 		TBL_MSG(tbl, MANDOCERR_TBLEXTRADAT, ln, *pos);
     64 
     65 	if (dp->last) {
     66 		dp->last->next = dat;
     67 		dp->last = dat;
     68 	} else
     69 		dp->last = dp->first = dat;
     70 
     71 	sv = *pos;
     72 	while (p[*pos] && p[*pos] != tbl->opts.tab)
     73 		(*pos)++;
     74 
     75 	/*
     76 	 * Check for a continued-data scope opening.  This consists of a
     77 	 * trailing `T{' at the end of the line.  Subsequent lines,
     78 	 * until a standalone `T}', are included in our cell.
     79 	 */
     80 
     81 	if (*pos - sv == 2 && 'T' == p[sv] && '{' == p[sv + 1]) {
     82 		tbl->part = TBL_PART_CDATA;
     83 		return(0);
     84 	}
     85 
     86 	dat->string = mandoc_malloc(*pos - sv + 1);
     87 	memcpy(dat->string, &p[sv], *pos - sv);
     88 	dat->string[*pos - sv] = '\0';
     89 
     90 	if (p[*pos])
     91 		(*pos)++;
     92 
     93 	if ( ! strcmp(dat->string, "_"))
     94 		dat->pos = TBL_DATA_HORIZ;
     95 	else if ( ! strcmp(dat->string, "="))
     96 		dat->pos = TBL_DATA_DHORIZ;
     97 	else if ( ! strcmp(dat->string, "\\_"))
     98 		dat->pos = TBL_DATA_NHORIZ;
     99 	else if ( ! strcmp(dat->string, "\\="))
    100 		dat->pos = TBL_DATA_NDHORIZ;
    101 	else
    102 		dat->pos = TBL_DATA_DATA;
    103 
    104 	if (NULL == dat->layout)
    105 		return(1);
    106 
    107 	if (TBL_CELL_HORIZ == dat->layout->pos ||
    108 			TBL_CELL_DHORIZ == dat->layout->pos)
    109 		if (TBL_DATA_DATA == dat->pos && '\0' != *dat->string)
    110 			TBL_MSG(tbl, MANDOCERR_TBLIGNDATA, ln, sv);
    111 
    112 	return(1);
    113 }
    114 
    115 /* ARGSUSED */
    116 int
    117 tbl_cdata(struct tbl_node *tbl, int ln, const char *p)
    118 {
    119 	struct tbl_dat	*dat;
    120 	size_t	 	 sz;
    121 	int		 pos;
    122 
    123 	pos = 0;
    124 
    125 	dat = tbl->last_span->last;
    126 	dat->pos = TBL_DATA_DATA;
    127 
    128 	if (p[pos] == 'T' && p[pos + 1] == '}') {
    129 		pos += 2;
    130 		if (p[pos] == tbl->opts.tab) {
    131 			tbl->part = TBL_PART_DATA;
    132 			pos++;
    133 			return(data(tbl, tbl->last_span, ln, p, &pos));
    134 		} else if ('\0' == p[pos]) {
    135 			tbl->part = TBL_PART_DATA;
    136 			return(1);
    137 		}
    138 
    139 		/* Fallthrough: T} is part of a word. */
    140 	}
    141 
    142 	if (dat->string) {
    143 		sz = strlen(p) + strlen(dat->string) + 2;
    144 		dat->string = mandoc_realloc(dat->string, sz);
    145 		strlcat(dat->string, " ", sz);
    146 		strlcat(dat->string, p, sz);
    147 	} else
    148 		dat->string = mandoc_strdup(p);
    149 
    150 	return(0);
    151 }
    152 
    153 int
    154 tbl_data(struct tbl_node *tbl, int ln, const char *p)
    155 {
    156 	struct tbl_span	*dp;
    157 	struct tbl_row	*rp;
    158 	int		 pos;
    159 
    160 	pos = 0;
    161 
    162 	if ('\0' == p[pos]) {
    163 		TBL_MSG(tbl, MANDOCERR_TBL, ln, pos);
    164 		return(0);
    165 	}
    166 
    167 	/*
    168 	 * Choose a layout row: take the one following the last parsed
    169 	 * span's.  If that doesn't exist, use the last parsed span's.
    170 	 * If there's no last parsed span, use the first row.  Lastly,
    171 	 * if the last span was a horizontal line, use the same layout
    172 	 * (it doesn't "consume" the layout).
    173 	 *
    174 	 * In the end, this can be NULL!
    175 	 */
    176 
    177 	if (tbl->last_span) {
    178 		assert(tbl->last_span->layout);
    179 		if (tbl->last_span->pos == TBL_SPAN_DATA)
    180 			rp = tbl->last_span->layout->next;
    181 		else
    182 			rp = tbl->last_span->layout;
    183 		if (NULL == rp)
    184 			rp = tbl->last_span->layout;
    185 	} else
    186 		rp = tbl->first_row;
    187 
    188 	dp = mandoc_calloc(1, sizeof(struct tbl_span));
    189 	dp->tbl = &tbl->opts;
    190 	dp->layout = rp;
    191 	dp->head = tbl->first_head;
    192 
    193 	if (tbl->last_span) {
    194 		tbl->last_span->next = dp;
    195 		tbl->last_span = dp;
    196 	} else {
    197 		tbl->last_span = tbl->first_span = dp;
    198 		dp->flags |= TBL_SPAN_FIRST;
    199 	}
    200 
    201 	if ( ! strcmp(p, "_")) {
    202 		dp->pos = TBL_SPAN_HORIZ;
    203 		return(1);
    204 	} else if ( ! strcmp(p, "=")) {
    205 		dp->pos = TBL_SPAN_DHORIZ;
    206 		return(1);
    207 	}
    208 
    209 	dp->pos = TBL_SPAN_DATA;
    210 
    211 	/* This returns 0 when TBL_PART_CDATA is entered. */
    212 
    213 	while ('\0' != p[pos])
    214 		if ( ! data(tbl, dp, ln, p, &pos))
    215 			return(0);
    216 
    217 	return(1);
    218 }
    219