371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov/* $Id: tbl_data.c,v 1.41 2015/10/06 18:32:20 schwarze Exp $ */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore/*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * Copyright (c) 2011, 2015 Ingo Schwarze <schwarze@openbsd.org>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore *
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Permission to use, copy, modify, and distribute this software for any
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * purpose with or without fee is hereby granted, provided that the above
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * copyright notice and this permission notice appear in all copies.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore *
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include "config.h"
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov#include <sys/types.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include <assert.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include <ctype.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include <stdlib.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include <string.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include <time.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include "mandoc.h"
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov#include "mandoc_aux.h"
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include "libmandoc.h"
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include "libroff.h"
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovstatic void getdata(struct tbl_node *, struct tbl_span *,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore int, const char *, int *);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovstatic struct tbl_span *newspan(struct tbl_node *, int,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore struct tbl_row *);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovstatic void
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovgetdata(struct tbl_node *tbl, struct tbl_span *dp,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore int ln, const char *p, int *pos)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore struct tbl_dat *dat;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore struct tbl_cell *cp;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov int sv;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov /* Advance to the next layout cell, skipping spanners. */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov cp = dp->last == NULL ? dp->layout->first : dp->last->layout->next;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov while (cp != NULL && cp->pos == TBL_CELL_SPAN)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore cp = cp->next;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Stop processing when we reach the end of the available layout
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * cells. This means that we have extra input.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (cp == NULL) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mandoc_msg(MANDOCERR_TBLDATA_EXTRA, tbl->parse,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov ln, *pos, p + *pos);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* Skip to the end... */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore while (p[*pos])
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore (*pos)++;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov return;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov dat = mandoc_calloc(1, sizeof(*dat));
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore dat->layout = cp;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore dat->pos = TBL_DATA_NONE;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov dat->spans = 0;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov for (cp = cp->next; cp != NULL; cp = cp->next)
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (cp->pos == TBL_CELL_SPAN)
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov dat->spans++;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore else
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore break;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (dp->last == NULL)
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov dp->first = dat;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov else
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore dp->last->next = dat;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov dp->last = dat;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore sv = *pos;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore while (p[*pos] && p[*pos] != tbl->opts.tab)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore (*pos)++;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Check for a continued-data scope opening. This consists of a
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * trailing `T{' at the end of the line. Subsequent lines,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * until a standalone `T}', are included in our cell.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (*pos - sv == 2 && p[sv] == 'T' && p[sv + 1] == '{') {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore tbl->part = TBL_PART_CDATA;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov return;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov dat->string = mandoc_strndup(p + sv, *pos - sv);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (p[*pos])
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore (*pos)++;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if ( ! strcmp(dat->string, "_"))
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore dat->pos = TBL_DATA_HORIZ;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore else if ( ! strcmp(dat->string, "="))
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore dat->pos = TBL_DATA_DHORIZ;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore else if ( ! strcmp(dat->string, "\\_"))
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore dat->pos = TBL_DATA_NHORIZ;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore else if ( ! strcmp(dat->string, "\\="))
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore dat->pos = TBL_DATA_NDHORIZ;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore else
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore dat->pos = TBL_DATA_DATA;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if ((dat->layout->pos == TBL_CELL_HORIZ ||
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov dat->layout->pos == TBL_CELL_DHORIZ ||
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov dat->layout->pos == TBL_CELL_DOWN) &&
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov dat->pos == TBL_DATA_DATA && *dat->string != '\0')
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mandoc_msg(MANDOCERR_TBLDATA_SPAN,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov tbl->parse, ln, sv, dat->string);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoreint
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovtbl_cdata(struct tbl_node *tbl, int ln, const char *p, int pos)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore struct tbl_dat *dat;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov size_t sz;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore dat = tbl->last_span->last;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (p[pos] == 'T' && p[pos + 1] == '}') {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore pos += 2;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (p[pos] == tbl->opts.tab) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore tbl->part = TBL_PART_DATA;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore pos++;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov while (p[pos] != '\0')
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov getdata(tbl, tbl->last_span, ln, p, &pos);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return 1;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov } else if (p[pos] == '\0') {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore tbl->part = TBL_PART_DATA;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return 1;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* Fallthrough: T} is part of a word. */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore dat->pos = TBL_DATA_DATA;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (dat->string != NULL) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov sz = strlen(p + pos) + strlen(dat->string) + 2;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore dat->string = mandoc_realloc(dat->string, sz);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov (void)strlcat(dat->string, " ", sz);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov (void)strlcat(dat->string, p + pos, sz);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore } else
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov dat->string = mandoc_strdup(p + pos);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (dat->layout->pos == TBL_CELL_DOWN)
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mandoc_msg(MANDOCERR_TBLDATA_SPAN, tbl->parse,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov ln, pos, dat->string);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return 0;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorestatic struct tbl_span *
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorenewspan(struct tbl_node *tbl, int line, struct tbl_row *rp)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore struct tbl_span *dp;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov dp = mandoc_calloc(1, sizeof(*dp));
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore dp->line = line;
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore dp->opts = &tbl->opts;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore dp->layout = rp;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov dp->prev = tbl->last_span;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (dp->prev == NULL) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov tbl->first_span = dp;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore tbl->current_span = NULL;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov } else
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov dp->prev->next = dp;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov tbl->last_span = dp;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return dp;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovvoid
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovtbl_data(struct tbl_node *tbl, int ln, const char *p, int pos)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore struct tbl_span *dp;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore struct tbl_row *rp;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Choose a layout row: take the one following the last parsed
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * span's. If that doesn't exist, use the last parsed span's.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * If there's no last parsed span, use the first row. Lastly,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * if the last span was a horizontal line, use the same layout
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * (it doesn't "consume" the layout).
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (tbl->last_span != NULL) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (tbl->last_span->pos == TBL_SPAN_DATA) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore for (rp = tbl->last_span->layout->next;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov rp != NULL && rp->first != NULL;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov rp = rp->next) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore switch (rp->first->pos) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case TBL_CELL_HORIZ:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore dp = newspan(tbl, ln, rp);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore dp->pos = TBL_SPAN_HORIZ;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore continue;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case TBL_CELL_DHORIZ:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore dp = newspan(tbl, ln, rp);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore dp->pos = TBL_SPAN_DHORIZ;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore continue;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore default:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore break;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore break;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore } else
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore rp = tbl->last_span->layout;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (rp == NULL)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore rp = tbl->last_span->layout;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore } else
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore rp = tbl->first_row;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore assert(rp);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore dp = newspan(tbl, ln, rp);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if ( ! strcmp(p, "_")) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore dp->pos = TBL_SPAN_HORIZ;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov return;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore } else if ( ! strcmp(p, "=")) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore dp->pos = TBL_SPAN_DHORIZ;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov return;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore dp->pos = TBL_SPAN_DATA;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov while (p[pos] != '\0')
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov getdata(tbl, dp, ln, p, &pos);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}