Annotation of src/usr.bin/mandoc/tbl_data.c, Revision 1.6
1.6 ! schwarze 1: /* $Id: tbl_data.c,v 1.5 2011/01/09 14:30:48 schwarze Exp $ */
1.1 schwarze 2: /*
1.4 schwarze 3: * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
1.1 schwarze 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: #include <assert.h>
18: #include <ctype.h>
19: #include <stdlib.h>
20: #include <string.h>
1.4 schwarze 21: #include <time.h>
1.1 schwarze 22:
1.4 schwarze 23: #include "mandoc.h"
24: #include "libmandoc.h"
25: #include "libroff.h"
26:
27: static int data(struct tbl_node *, struct tbl_span *,
28: int, const char *, int *);
29:
30: static int
31: data(struct tbl_node *tbl, struct tbl_span *dp,
32: int ln, const char *p, int *pos)
1.1 schwarze 33: {
1.4 schwarze 34: struct tbl_dat *dat;
35: struct tbl_cell *cp;
1.6 ! schwarze 36: int sv, spans;
1.4 schwarze 37:
38: cp = NULL;
39: if (dp->last && dp->last->layout)
40: cp = dp->last->layout->next;
41: else if (NULL == dp->last)
42: cp = dp->layout->first;
43:
1.5 schwarze 44: /*
45: * Skip over spanners and vertical lines to data formats, since
46: * we want to match data with data layout cells in the header.
47: */
1.4 schwarze 48:
49: while (cp && (TBL_CELL_VERT == cp->pos ||
1.5 schwarze 50: TBL_CELL_DVERT == cp->pos ||
51: TBL_CELL_SPAN == cp->pos))
1.4 schwarze 52: cp = cp->next;
53:
1.6 ! schwarze 54: /*
! 55: * Stop processing when we reach the end of the available layout
! 56: * cells. This means that we have extra input.
! 57: */
! 58:
! 59: if (NULL == cp) {
! 60: TBL_MSG(tbl, MANDOCERR_TBLEXTRADAT, ln, *pos);
! 61: /* Skip to the end... */
! 62: while (p[*pos])
! 63: (*pos)++;
! 64: return(1);
! 65: }
! 66:
1.4 schwarze 67: dat = mandoc_calloc(1, sizeof(struct tbl_dat));
68: dat->layout = cp;
69: dat->pos = TBL_DATA_NONE;
70:
1.6 ! schwarze 71: assert(TBL_CELL_SPAN != cp->pos);
! 72:
! 73: for (spans = 0, cp = cp->next; cp; cp = cp->next)
! 74: if (TBL_CELL_SPAN == cp->pos)
! 75: spans++;
! 76: else
! 77: break;
! 78:
! 79: dat->spans = spans;
1.4 schwarze 80:
81: if (dp->last) {
82: dp->last->next = dat;
83: dp->last = dat;
84: } else
85: dp->last = dp->first = dat;
86:
87: sv = *pos;
88: while (p[*pos] && p[*pos] != tbl->opts.tab)
89: (*pos)++;
90:
91: /*
92: * Check for a continued-data scope opening. This consists of a
93: * trailing `T{' at the end of the line. Subsequent lines,
94: * until a standalone `T}', are included in our cell.
95: */
1.1 schwarze 96:
1.4 schwarze 97: if (*pos - sv == 2 && 'T' == p[sv] && '{' == p[sv + 1]) {
98: tbl->part = TBL_PART_CDATA;
1.1 schwarze 99: return(0);
1.4 schwarze 100: }
1.1 schwarze 101:
1.4 schwarze 102: dat->string = mandoc_malloc(*pos - sv + 1);
103: memcpy(dat->string, &p[sv], *pos - sv);
104: dat->string[*pos - sv] = '\0';
1.1 schwarze 105:
1.4 schwarze 106: if (p[*pos])
107: (*pos)++;
1.1 schwarze 108:
109: if ( ! strcmp(dat->string, "_"))
1.4 schwarze 110: dat->pos = TBL_DATA_HORIZ;
1.1 schwarze 111: else if ( ! strcmp(dat->string, "="))
1.4 schwarze 112: dat->pos = TBL_DATA_DHORIZ;
1.1 schwarze 113: else if ( ! strcmp(dat->string, "\\_"))
1.4 schwarze 114: dat->pos = TBL_DATA_NHORIZ;
1.1 schwarze 115: else if ( ! strcmp(dat->string, "\\="))
1.4 schwarze 116: dat->pos = TBL_DATA_NDHORIZ;
1.1 schwarze 117: else
1.4 schwarze 118: dat->pos = TBL_DATA_DATA;
119:
120: if (TBL_CELL_HORIZ == dat->layout->pos ||
1.6 ! schwarze 121: TBL_CELL_DHORIZ == dat->layout->pos ||
! 122: TBL_CELL_DOWN == dat->layout->pos)
1.4 schwarze 123: if (TBL_DATA_DATA == dat->pos && '\0' != *dat->string)
124: TBL_MSG(tbl, MANDOCERR_TBLIGNDATA, ln, sv);
125:
1.1 schwarze 126: return(1);
127: }
128:
1.5 schwarze 129: /* ARGSUSED */
1.4 schwarze 130: int
131: tbl_cdata(struct tbl_node *tbl, int ln, const char *p)
132: {
133: struct tbl_dat *dat;
134: size_t sz;
1.5 schwarze 135: int pos;
1.4 schwarze 136:
1.5 schwarze 137: pos = 0;
1.4 schwarze 138:
139: dat = tbl->last_span->last;
1.5 schwarze 140:
141: if (p[pos] == 'T' && p[pos + 1] == '}') {
142: pos += 2;
143: if (p[pos] == tbl->opts.tab) {
144: tbl->part = TBL_PART_DATA;
145: pos++;
146: return(data(tbl, tbl->last_span, ln, p, &pos));
147: } else if ('\0' == p[pos]) {
148: tbl->part = TBL_PART_DATA;
149: return(1);
150: }
151:
152: /* Fallthrough: T} is part of a word. */
153: }
1.4 schwarze 154:
1.6 ! schwarze 155: dat->pos = TBL_DATA_DATA;
! 156:
1.4 schwarze 157: if (dat->string) {
158: sz = strlen(p) + strlen(dat->string) + 2;
159: dat->string = mandoc_realloc(dat->string, sz);
160: strlcat(dat->string, " ", sz);
161: strlcat(dat->string, p, sz);
162: } else
163: dat->string = mandoc_strdup(p);
164:
1.6 ! schwarze 165: if (TBL_CELL_DOWN == dat->layout->pos)
! 166: TBL_MSG(tbl, MANDOCERR_TBLIGNDATA, ln, pos);
! 167:
1.4 schwarze 168: return(0);
169: }
1.1 schwarze 170:
171: int
1.4 schwarze 172: tbl_data(struct tbl_node *tbl, int ln, const char *p)
1.1 schwarze 173: {
174: struct tbl_span *dp;
1.4 schwarze 175: struct tbl_row *rp;
176: int pos;
177:
178: pos = 0;
1.1 schwarze 179:
1.4 schwarze 180: if ('\0' == p[pos]) {
181: TBL_MSG(tbl, MANDOCERR_TBL, ln, pos);
182: return(0);
1.1 schwarze 183: }
184:
1.4 schwarze 185: /*
186: * Choose a layout row: take the one following the last parsed
187: * span's. If that doesn't exist, use the last parsed span's.
1.6 ! schwarze 188: * If there's no last parsed span, use the first row. Lastly,
! 189: * if the last span was a horizontal line, use the same layout
! 190: * (it doesn't "consume" the layout).
1.4 schwarze 191: */
192:
193: if (tbl->last_span) {
194: assert(tbl->last_span->layout);
1.6 ! schwarze 195: if (tbl->last_span->pos == TBL_SPAN_DATA)
! 196: rp = tbl->last_span->layout->next;
! 197: else
! 198: rp = tbl->last_span->layout;
! 199:
1.4 schwarze 200: if (NULL == rp)
201: rp = tbl->last_span->layout;
202: } else
203: rp = tbl->first_row;
1.6 ! schwarze 204:
! 205: assert(rp);
1.4 schwarze 206:
207: dp = mandoc_calloc(1, sizeof(struct tbl_span));
208: dp->tbl = &tbl->opts;
209: dp->layout = rp;
210: dp->head = tbl->first_head;
211:
212: if (tbl->last_span) {
213: tbl->last_span->next = dp;
214: tbl->last_span = dp;
215: } else {
216: tbl->last_span = tbl->first_span = dp;
217: dp->flags |= TBL_SPAN_FIRST;
218: }
1.1 schwarze 219:
220: if ( ! strcmp(p, "_")) {
1.4 schwarze 221: dp->pos = TBL_SPAN_HORIZ;
1.1 schwarze 222: return(1);
223: } else if ( ! strcmp(p, "=")) {
1.4 schwarze 224: dp->pos = TBL_SPAN_DHORIZ;
1.1 schwarze 225: return(1);
226: }
227:
1.4 schwarze 228: dp->pos = TBL_SPAN_DATA;
1.1 schwarze 229:
1.4 schwarze 230: /* This returns 0 when TBL_PART_CDATA is entered. */
1.1 schwarze 231:
1.4 schwarze 232: while ('\0' != p[pos])
233: if ( ! data(tbl, dp, ln, p, &pos))
234: return(0);
1.1 schwarze 235:
236: return(1);
237: }