aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2013-07-13 12:52:07 +0000
committerIngo Schwarze <schwarze@openbsd.org>2013-07-13 12:52:07 +0000
commitc347c2cd27346df69977ccd8c718bb4c1ec91a88 (patch)
tree52d97933e647f641f1461a44387af918ac68deb9
parent9ef07094816176da1ae6b38a6391f4b1481bc5be (diff)
downloadmandoc-c347c2cd27346df69977ccd8c718bb4c1ec91a88.tar.gz
mandoc-c347c2cd27346df69977ccd8c718bb4c1ec91a88.tar.zst
mandoc-c347c2cd27346df69977ccd8c718bb4c1ec91a88.zip
Rudimentary implementation of the .it request (input line trap).
As with any low-level roff request involving subtle interactions with macro internals, this implementation is not exact, but it does handle the simplest cases. This request occurs in man(7) code generated from DocBook, for example mysql(1) and yasm_arch(7). Thanks to brad@ for reporting the issue back in January 2011.
-rw-r--r--TODO6
-rw-r--r--mandoc.h5
-rw-r--r--read.c3
-rw-r--r--roff.c69
4 files changed, 64 insertions, 19 deletions
diff --git a/TODO b/TODO
index cdd061fb..d1d1bd7c 100644
--- a/TODO
+++ b/TODO
@@ -1,6 +1,6 @@
************************************************************************
* Official mandoc TODO.
-* $Id: TODO,v 1.151 2013/07/02 12:22:31 schwarze Exp $
+* $Id: TODO,v 1.152 2013/07/13 12:52:07 schwarze Exp $
************************************************************************
************************************************************************
@@ -37,10 +37,6 @@ None known right now.
- .fc (field control)
found by naddy@ in xloadimage(1)
-- .it (line traps) occur in mysql(1), yasm_arch(7)
- generated by DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
- reported by brad@ Sat, 15 Jan 2011 15:48:18 -0500
-
- .ns (no-space mode) occurs in xine-config(1)
reported by brad@ Sat, 15 Jan 2011 15:45:23 -0500
diff --git a/mandoc.h b/mandoc.h
index c86530c4..560bf62a 100644
--- a/mandoc.h
+++ b/mandoc.h
@@ -1,7 +1,7 @@
-/* $Id: mandoc.h,v 1.107 2013/05/31 21:37:17 schwarze Exp $ */
+/* $Id: mandoc.h,v 1.108 2013/07/13 12:52:07 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2012 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2012, 2013 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
@@ -145,6 +145,7 @@ enum mandocerr {
MANDOCERR_NOARGS, /* macro requires line argument(s) */
MANDOCERR_NOBODY, /* macro requires body argument(s) */
MANDOCERR_NOARGV, /* macro requires argument(s) */
+ MANDOCERR_NUMERIC, /* request requires a numeric argument */
MANDOCERR_LISTTYPE, /* missing list type */
MANDOCERR_ARGSLOST, /* line argument(s) will be lost */
MANDOCERR_BODYLOST, /* body argument(s) will be lost */
diff --git a/read.c b/read.c
index fce90924..0ec58ecb 100644
--- a/read.c
+++ b/read.c
@@ -1,4 +1,4 @@
-/* $Id: read.c,v 1.37 2013/06/02 03:52:21 schwarze Exp $ */
+/* $Id: read.c,v 1.38 2013/07/13 12:52:07 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
@@ -185,6 +185,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
"macro requires line argument(s)",
"macro requires body argument(s)",
"macro requires argument(s)",
+ "request requires a numeric argument",
"missing list type",
"line argument(s) will be lost",
"body argument(s) will be lost",
diff --git a/roff.c b/roff.c
index 303b0333..3ee8adfe 100644
--- a/roff.c
+++ b/roff.c
@@ -1,4 +1,4 @@
-/* $Id: roff.c,v 1.177 2013/06/27 09:49:47 schwarze Exp $ */
+/* $Id: roff.c,v 1.178 2013/07/13 12:52:07 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
@@ -21,6 +21,7 @@
#include <assert.h>
#include <ctype.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -186,12 +187,13 @@ static void roff_freestr(struct roffkv *);
static char *roff_getname(struct roff *, char **, int, int);
static const char *roff_getstrn(const struct roff *,
const char *, size_t);
+static enum rofferr roff_it(ROFF_ARGS);
static enum rofferr roff_line_ignore(ROFF_ARGS);
static enum rofferr roff_nr(ROFF_ARGS);
static void roff_openeqn(struct roff *, const char *,
int, int, const char *);
static enum rofft roff_parse(struct roff *, const char *, int *);
-static enum rofferr roff_parsetext(char *);
+static enum rofferr roff_parsetext(char **, size_t *, int, int *);
static enum rofferr roff_res(struct roff *,
char **, size_t *, int, int);
static enum rofferr roff_rm(ROFF_ARGS);
@@ -233,7 +235,7 @@ static struct roffmac roffs[ROFF_MAX] = {
{ "ie", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL },
{ "if", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL },
{ "ig", roff_block, roff_block_text, roff_block_sub, 0, NULL },
- { "it", roff_line_ignore, NULL, NULL, 0, NULL },
+ { "it", roff_it, NULL, NULL, 0, NULL },
{ "ne", roff_line_ignore, NULL, NULL, 0, NULL },
{ "nh", roff_line_ignore, NULL, NULL, 0, NULL },
{ "nr", roff_nr, NULL, NULL, 0, NULL },
@@ -295,6 +297,9 @@ static const struct predef predefs[PREDEFS_MAX] = {
/* See roffhash_find() */
#define ROFF_HASH(p) (p[0] - ASCII_LO)
+static int roffit_lines; /* number of lines to delay */
+static char *roffit_macro; /* nil-terminated macro line */
+
static void
roffhash_init(void)
{
@@ -596,16 +601,20 @@ again:
}
/*
- * Process text streams: convert all breakable hyphens into ASCII_HYPH.
+ * Process text streams:
+ * Convert all breakable hyphens into ASCII_HYPH.
+ * Decrement and spring input line trap.
*/
static enum rofferr
-roff_parsetext(char *p)
+roff_parsetext(char **bufp, size_t *szp, int pos, int *offs)
{
size_t sz;
const char *start;
+ char *p;
+ int isz;
enum mandoc_esc esc;
- start = p;
+ start = p = *bufp + pos;
while ('\0' != *p) {
sz = strcspn(p, "-\\");
@@ -633,6 +642,22 @@ roff_parsetext(char *p)
p++;
}
+ /* Spring the input line trap. */
+ if (1 == roffit_lines) {
+ isz = asprintf(&p, "%s\n.%s", *bufp, roffit_macro);
+ if (-1 == isz) {
+ perror(NULL);
+ exit((int)MANDOCLEVEL_SYSERR);
+ }
+ free(*bufp);
+ *bufp = p;
+ *szp = isz + 1;
+ *offs = 0;
+ free(roffit_macro);
+ roffit_lines = 0;
+ return(ROFF_REPARSE);
+ } else if (1 < roffit_lines)
+ --roffit_lines;
return(ROFF_CONT);
}
@@ -677,13 +702,13 @@ roff_parseln(struct roff *r, int ln, char **bufp,
return(eqn_read(&r->eqn, ln, *bufp, pos, offs));
if (r->tbl)
return(tbl_read(r->tbl, ln, *bufp, pos));
- return(roff_parsetext(*bufp + pos));
+ return(roff_parsetext(bufp, szp, pos, offs));
} else if ( ! ctl) {
if (r->eqn)
return(eqn_read(&r->eqn, ln, *bufp, pos, offs));
if (r->tbl)
return(tbl_read(r->tbl, ln, *bufp, pos));
- return(roff_parsetext(*bufp + pos));
+ return(roff_parsetext(bufp, szp, pos, offs));
} else if (r->eqn)
return(eqn_read(&r->eqn, ln, *bufp, ppos, offs));
@@ -1120,9 +1145,6 @@ static enum rofferr
roff_line_ignore(ROFF_ARGS)
{
- if (ROFF_it == tok)
- mandoc_msg(MANDOCERR_REQUEST, r->parse, ln, ppos, "it");
-
return(ROFF_IGN);
}
@@ -1297,6 +1319,31 @@ roff_rm(ROFF_ARGS)
/* ARGSUSED */
static enum rofferr
+roff_it(ROFF_ARGS)
+{
+ char *cp;
+ size_t len;
+ int iv;
+
+ /* Parse the number of lines. */
+ cp = *bufp + pos;
+ len = strcspn(cp, " \t");
+ cp[len] = '\0';
+ if ((iv = mandoc_strntoi(cp, len, 10)) <= 0) {
+ mandoc_msg(MANDOCERR_NUMERIC, r->parse,
+ ln, ppos, *bufp + 1);
+ return(ROFF_IGN);
+ }
+ cp += len + 1;
+
+ /* Arm the input line trap. */
+ roffit_lines = iv;
+ roffit_macro = mandoc_strdup(cp);
+ return(ROFF_IGN);
+}
+
+/* ARGSUSED */
+static enum rofferr
roff_Dd(ROFF_ARGS)
{
const char *const *cp;