-/* $Id: roff.c,v 1.365 2019/04/21 23:51:21 schwarze Exp $ */
+/* $Id: roff.c,v 1.371 2020/02/27 21:43:44 schwarze Exp $ */
/*
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010-2015, 2017-2019 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010-2015, 2017-2020 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
"Lk", "Mt", "Brq", "Bro",
"Brc", "%C", "Es", "En",
"Dx", "%Q", "%U", "Ta",
- NULL,
+ "Tg", NULL,
"TH", "SH", "SS", "TP",
"TQ",
"LP", "PP", "P", "IP",
roff_reset(struct roff *r)
{
roff_free1(r);
+ r->options |= MPARSE_COMMENT;
r->format = r->options & (MPARSE_MDOC | MPARSE_MAN);
r->control = '\0';
r->escape = '\\';
void
roff_free(struct roff *r)
{
- int i;
+ int i;
roff_free1(r);
for (i = 0; i < r->mstacksz; i++)
r = mandoc_calloc(1, sizeof(struct roff));
r->reqtab = roffhash_alloc(0, ROFF_RENAMED);
- r->options = options;
+ r->options = options | MPARSE_COMMENT;
r->format = options & (MPARSE_MDOC | MPARSE_MAN);
r->mstackpos = -1;
r->rstackpos = -1;
roff_node_free(n);
}
+int
+roff_node_transparent(struct roff_node *n)
+{
+ if (n == NULL)
+ return 0;
+ if (n->type == ROFFT_COMMENT || n->flags & NODE_NOPRT)
+ return 1;
+ switch (n->tok) {
+ case ROFF_ft:
+ case ROFF_ll:
+ case ROFF_mc:
+ case ROFF_po:
+ case ROFF_ta:
+ case MDOC_Db:
+ case MDOC_Es:
+ case MDOC_Sm:
+ case MDOC_Tg:
+ case MAN_DT:
+ case MAN_UC:
+ case MAN_PD:
+ case MAN_AT:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+struct roff_node *
+roff_node_child(struct roff_node *n)
+{
+ for (n = n->child; roff_node_transparent(n); n = n->next)
+ continue;
+ return n;
+}
+
+struct roff_node *
+roff_node_prev(struct roff_node *n)
+{
+ do {
+ n = n->prev;
+ } while (roff_node_transparent(n));
+ return n;
+}
+
+struct roff_node *
+roff_node_next(struct roff_node *n)
+{
+ do {
+ n = n->next;
+ } while (roff_node_transparent(n));
+ return n;
+}
+
void
deroff(char **dest, const struct roff_node *n)
{
char *cp;
size_t sz;
- if (n->type != ROFFT_TEXT) {
+ if (n->string == NULL) {
for (n = n->child; n != NULL; n = n->next)
deroff(dest, n);
return;
* in the syntax tree.
*/
- if (newesc != ASCII_ESC && r->format == 0) {
+ if (newesc != ASCII_ESC && r->options & MPARSE_COMMENT) {
while (*ep == ' ' || *ep == '\t')
ep--;
ep[1] = '\0';
roff_getarg(struct roff *r, char **cpp, int ln, int *pos)
{
struct buf buf;
- char *cp, *start;
+ char *cp, *start;
int newesc, pairs, quoted, white;
/* Quoting can only start with a new word. */
roff_addtbl(r->man, ln, r->tbl);
return e;
}
- if ( ! ctl)
+ if ( ! ctl) {
+ r->options &= ~MPARSE_COMMENT;
return roff_parsetext(r, buf, pos, offs) | e;
+ }
/* Skip empty request lines. */
/* No scope is open. This is a new request or macro. */
+ r->options &= ~MPARSE_COMMENT;
spos = pos;
t = roff_parse(r, buf->buf, &pos, ln, ppos);
}
}
+ t = roff_parse(r, buf->buf, &pos, ln, ppos);
+
+ /* For now, let high level macros abort .ce mode. */
+
+ if (roffce_node != NULL &&
+ (t == TOKEN_NONE || t == ROFF_Dd || t == ROFF_EQ ||
+ t == ROFF_TH || t == ROFF_TS)) {
+ r->man->last = roffce_node;
+ r->man->next = ROFF_NEXT_SIBLING;
+ roffce_lines = 0;
+ roffce_node = NULL;
+ }
+
/*
* Fully handle known macros when they are structurally
* required or when the conditional evaluated to true.
*/
- t = roff_parse(r, buf->buf, &pos, ln, ppos);
if (t == ROFF_break) {
if (irc & ROFF_LOOPMASK)
irc = ROFF_IGN | ROFF_LOOPEXIT;