]> git.cameronkatri.com Git - mandoc.git/commitdiff
Rudimentary implementation of the .it request (input line trap).
authorIngo Schwarze <schwarze@openbsd.org>
Sat, 13 Jul 2013 12:52:07 +0000 (12:52 +0000)
committerIngo Schwarze <schwarze@openbsd.org>
Sat, 13 Jul 2013 12:52:07 +0000 (12:52 +0000)
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.

TODO
mandoc.h
read.c
roff.c

diff --git a/TODO b/TODO
index cdd061fb401dbed579ac37cefcfa6e679e9fdeb6..d1d1bd7cc082e1bb5bc93baac4390c9fd500bb61 100644 (file)
--- 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
 
index c86530c4f8f156f0638f33f6c772df3e55caf698..560bf62aa620ba7d641ec6590d23b46a160cc920 100644 (file)
--- 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 fce90924ff86b57b51a8894011bf0a148dfa8fb5..0ec58ecb29f396a97a0ad88cdaf327bf0085b784 100644 (file)
--- 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 303b0333597e0fd4ee55445908d2b9d05d67c97b..3ee8adfe6dab696e633264ca7114771ed3775d80 100644 (file)
--- 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);
 }
 
@@ -1295,6 +1317,31 @@ roff_rm(ROFF_ARGS)
        return(ROFF_IGN);
 }
 
+/* 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)