-/* $Id: roff.c,v 1.111 2010/12/29 01:16:57 kristaps Exp $ */
+/* $Id: roff.c,v 1.120 2011/01/03 23:24:16 schwarze Exp $ */
/*
- * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
ROFF_tr,
ROFF_TS,
ROFF_TE,
+ ROFF_T_,
ROFF_cblock,
ROFF_ccond, /* FIXME: remove this. */
ROFF_USERDEF,
struct regset *regs; /* read/writable registers */
struct roffstr *first_string; /* user-defined strings & macros */
const char *current_string; /* value of last called user macro */
- struct tbl *tbl;
+ struct tbl_node *first_tbl; /* first table parsed */
+ struct tbl_node *last_tbl; /* last table parsed */
+ struct tbl_node *tbl; /* current table being parsed */
};
struct roffnode {
static enum rofferr roff_so(ROFF_ARGS);
static enum rofferr roff_TE(ROFF_ARGS);
static enum rofferr roff_TS(ROFF_ARGS);
+static enum rofferr roff_T_(ROFF_ARGS);
static enum rofferr roff_userdef(ROFF_ARGS);
/* See roff_hash_find() */
{ "tr", roff_line_ignore, NULL, NULL, 0, NULL },
{ "TS", roff_TS, NULL, NULL, 0, NULL },
{ "TE", roff_TE, NULL, NULL, 0, NULL },
+ { "T&", roff_T_, NULL, NULL, 0, NULL },
{ ".", roff_cblock, NULL, NULL, 0, NULL },
{ "\\}", roff_ccond, NULL, NULL, 0, NULL },
{ NULL, roff_userdef, NULL, NULL, 0, NULL },
static void
roff_free1(struct roff *r)
{
+ struct tbl_node *t;
- if (r->tbl) {
- tbl_free(r->tbl);
- r->tbl = NULL;
+ while (r->first_tbl) {
+ t = r->first_tbl;
+ r->first_tbl = t->next;
+ tbl_free(t);
}
+ r->first_tbl = r->last_tbl = r->tbl = NULL;
+
while (r->last)
roffnode_pop(r);
}
-int
+void
roff_endparse(struct roff *r)
{
- /* FIXME: if r->tbl */
if (r->last)
(*r->msg)(MANDOCERR_SCOPEEXIT, r->data,
r->last->line, r->last->col, NULL);
- return(1);
+
+ if (r->tbl) {
+ (*r->msg)(MANDOCERR_SCOPEEXIT, r->data,
+ r->tbl->line, r->tbl->pos, NULL);
+ tbl_end(r->tbl);
+ r->tbl = NULL;
+ }
}
if (NULL == r->tbl)
(*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL);
else
- tbl_free(r->tbl);
+ tbl_end(r->tbl);
r->tbl = NULL;
return(ROFF_IGN);
}
+/* ARGSUSED */
+static enum rofferr
+roff_T_(ROFF_ARGS)
+{
+
+ if (NULL == r->tbl)
+ (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL);
+ else
+ tbl_restart(ppos, ln, r->tbl);
+
+ return(ROFF_IGN);
+}
+
/* ARGSUSED */
static enum rofferr
roff_TS(ROFF_ARGS)
{
+ struct tbl_node *t;
if (r->tbl) {
(*r->msg)(MANDOCERR_SCOPEBROKEN, r->data, ln, ppos, NULL);
- tbl_reset(r->tbl);
- } else
- r->tbl = tbl_alloc(r->data, r->msg);
+ tbl_end(r->tbl);
+ }
+
+ t = tbl_alloc(ppos, ln, r->data, r->msg);
+ if (r->last_tbl)
+ r->last_tbl->next = t;
+ else
+ r->first_tbl = r->last_tbl = t;
+
+ r->tbl = r->last_tbl = t;
return(ROFF_IGN);
}
{
const char *arg[9];
char *cp, *n1, *n2;
- int i, quoted, pairs;
+ int i;
/*
* Collect pointers to macro argument strings
* and null-terminate them.
*/
cp = *bufp + pos;
- for (i = 0; i < 9; i++) {
- /* Quoting can only start with a new word. */
- if ('"' == *cp) {
- quoted = 1;
- cp++;
- } else
- quoted = 0;
- arg[i] = cp;
- for (pairs = 0; '\0' != *cp; cp++) {
- /* Unquoted arguments end at blanks. */
- if (0 == quoted) {
- if (' ' == *cp)
- break;
- continue;
- }
- /* After pairs of quotes, move left. */
- if (pairs)
- cp[-pairs] = cp[0];
- /* Pairs of quotes do not end words, ... */
- if ('"' == cp[0] && '"' == cp[1]) {
- pairs++;
- cp++;
- continue;
- }
- /* ... but solitary quotes do. */
- if ('"' != *cp)
- continue;
- if (pairs)
- cp[-pairs] = '\0';
- *cp = ' ';
- break;
- }
- /* Last argument; the remaining ones are empty strings. */
- if ('\0' == *cp)
- continue;
- /* Null-terminate argument and move to the next one. */
- *cp++ = '\0';
- while (' ' == *cp)
- cp++;
- }
+ for (i = 0; i < 9; i++)
+ arg[i] = '\0' == *cp ? "" :
+ mandoc_getarg(&cp, r->msg, r->data, ln, &pos);
/*
* Expand macro arguments.
r->first_string = NULL;
}
+
+const struct tbl_span *
+roff_span(const struct roff *r)
+{
+
+ return(r->tbl ? tbl_span(r->tbl) : NULL);
+}