summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--main.c7
-rw-r--r--mdoc.h1
-rw-r--r--regs.h39
-rw-r--r--roff.31
-rw-r--r--roff.734
-rw-r--r--roff.c87
-rw-r--r--roff.h4
8 files changed, 162 insertions, 13 deletions
diff --git a/Makefile b/Makefile
index 134d4a93..9a85b103 100644
--- a/Makefile
+++ b/Makefile
@@ -98,7 +98,7 @@ DATAS = arch.in att.in lib.in msec.in st.in \
HEADS = mdoc.h libmdoc.h man.h libman.h term.h \
libmandoc.h html.h chars.h out.h main.h roff.h \
- mandoc.h
+ mandoc.h regs.h
GSGMLS = mandoc.1.sgml mdoc.3.sgml mdoc.7.sgml \
mandoc_char.7.sgml man.7.sgml man.3.sgml roff.7.sgml \
diff --git a/main.c b/main.c
index 0d63a334..a29c3633 100644
--- a/main.c
+++ b/main.c
@@ -30,10 +30,11 @@
#include <unistd.h>
#include "mandoc.h"
+#include "regs.h"
+#include "main.h"
#include "mdoc.h"
#include "man.h"
#include "roff.h"
-#include "main.h"
#define UNCONST(a) ((void *)(uintptr_t)(const void *)(a))
@@ -450,11 +451,13 @@ fdesc(struct curparse *curp)
struct man *man;
struct mdoc *mdoc;
struct roff *roff;
+ struct regset regs;
man = NULL;
mdoc = NULL;
roff = NULL;
memset(&ln, 0, sizeof(struct buf));
+ memset(&regs, 0, sizeof(struct regset));
/*
* Two buffers: ln and buf. buf is the input file and may be
@@ -537,7 +540,7 @@ fdesc(struct curparse *curp)
of = 0;
do {
- re = roff_parseln(roff, lnn_start,
+ re = roff_parseln(roff, &regs, lnn_start,
&ln.buf, &ln.sz, of, &of);
} while (ROFF_RERUN == re);
diff --git a/mdoc.h b/mdoc.h
index 10767d4f..7fc5b3e4 100644
--- a/mdoc.h
+++ b/mdoc.h
@@ -155,6 +155,7 @@ enum mdoct {
/* What follows is a list of ALL possible macro arguments. */
+/* FIXME: make this into an enum. */
#define MDOC_Split 0
#define MDOC_Nosplit 1
#define MDOC_Ragged 2
diff --git a/regs.h b/regs.h
new file mode 100644
index 00000000..9f176d6d
--- /dev/null
+++ b/regs.h
@@ -0,0 +1,39 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef REGS_H
+#define REGS_H
+
+__BEGIN_DECLS
+
+enum regs {
+ REG_nS = 0, /* nS */
+ REG__MAX
+};
+
+/*
+ * Registers are passed into libmdoc and libman. They refer to some
+ * sort of external state.
+ */
+struct regset {
+ union {
+ int i; /* integer value */
+ } regs[REG__MAX];
+};
+
+__END_DECLS
+
+#endif /*!REGS_H*/
diff --git a/roff.3 b/roff.3
index 18b48ad3..30b8aa2b 100644
--- a/roff.3
+++ b/roff.3
@@ -27,6 +27,7 @@
.Nd roff macro compiler library
.Sh SYNOPSIS
.In mandoc.h
+.In regs.h
.In roff.h
.Ft "struct roff *"
.Fn roff_alloc "mandocmsg msgs" "void *data"
diff --git a/roff.7 b/roff.7
index 58fb4d19..e35f37d4 100644
--- a/roff.7
+++ b/roff.7
@@ -268,6 +268,34 @@ This macro is intended to have one argument,
the name of the request, macro or string to be undefined.
Currently, it is ignored including its arguments,
and the number of arguments is not checked.
+.Ss \&nr
+Define a register.
+A register is an arbitrary string value that defines some sort of state,
+which influences parsing and/or formatting.
+Its syntax is as follows:
+.Pp
+.D1 Pf \. Sx \&nr Cm name value
+.Pp
+The
+.Cm value
+may, at the moment, only be an integer.
+The
+.Cm name
+is defined up to the next whitespace.
+The following register
+.Cm name
+requests are recognised:
+.Bl -tag -width Ds
+.It Cm nS
+If set to a positive integer value, certain
+.Xr mdoc 7
+macros will behave as if they are defined in the
+.Em SYNOPSIS
+section to a manual.
+Otherwise, this behaviour is unset (even if called within the
+.Em SYNOPSIS
+section itself).
+.El
.Ss \&tr
Output character translation.
This macro is intended to have one argument,
@@ -287,6 +315,12 @@ file re-write
.Pp
.Bl -dash -compact
.It
+The
+.Cm nS
+request to
+.Sx \&nr
+is only compatible with OpenBSD's groff.
+.It
Historic groff did not accept white-space buffering the custom END tag
for the
.Sx \&ig
diff --git a/roff.c b/roff.c
index f0c23664..2fbff8b7 100644
--- a/roff.c
+++ b/roff.c
@@ -19,12 +19,15 @@
#endif
#include <assert.h>
+#include <errno.h>
#include <ctype.h>
+#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "mandoc.h"
+#include "regs.h"
#include "roff.h"
#define RSTACK_MAX 128
@@ -56,6 +59,7 @@ enum rofft {
ROFF_tr,
ROFF_cblock,
ROFF_ccond,
+ ROFF_nr,
ROFF_MAX
};
@@ -83,6 +87,7 @@ struct roffnode {
};
#define ROFF_ARGS struct roff *r, /* parse ctx */ \
+ struct regset *regs, /* registers */ \
enum rofft tok, /* tok of macro */ \
char **bufp, /* input buffer */ \
size_t *szp, /* size of input buffer */ \
@@ -111,8 +116,9 @@ static enum rofferr roff_ccond(ROFF_ARGS);
static enum rofferr roff_cond(ROFF_ARGS);
static enum rofferr roff_cond_text(ROFF_ARGS);
static enum rofferr roff_cond_sub(ROFF_ARGS);
-static enum roffrule roff_evalcond(const char *, int *);
static enum rofferr roff_line(ROFF_ARGS);
+static enum rofferr roff_nr(ROFF_ARGS);
+static enum roffrule roff_evalcond(const char *, int *);
/* See roff_hash_find() */
@@ -138,6 +144,7 @@ static struct roffmac roffs[ROFF_MAX] = {
{ "tr", roff_line, NULL, NULL, 0, NULL },
{ ".", roff_cblock, NULL, NULL, 0, NULL },
{ "\\}", roff_ccond, NULL, NULL, 0, NULL },
+ { "nr", roff_nr, NULL, NULL, 0, NULL },
};
static void roff_free1(struct roff *);
@@ -148,6 +155,7 @@ static int roffnode_push(struct roff *,
enum rofft, int, int);
static void roffnode_pop(struct roff *);
static enum rofft roff_parse(const char *, int *);
+static int roff_parse_nat(const char *, int *);
/* See roff_hash_find() */
#define ROFF_HASH(p) (p[0] - ASCII_LO)
@@ -300,7 +308,7 @@ roff_alloc(const mandocmsg msg, void *data)
enum rofferr
-roff_parseln(struct roff *r, int ln,
+roff_parseln(struct roff *r, struct regset *regs, int ln,
char **bufp, size_t *szp, int pos, int *offs)
{
enum rofft t;
@@ -318,7 +326,8 @@ roff_parseln(struct roff *r, int ln,
ROFF_DEBUG("roff: intercept scoped text: %s, [%s]\n",
roffs[t].name, &(*bufp)[pos]);
return((*roffs[t].text)
- (r, t, bufp, szp, ln, pos, pos, offs));
+ (r, regs, t, bufp,
+ szp, ln, pos, pos, offs));
} else if ( ! ROFF_CTL((*bufp)[pos])) {
ROFF_DEBUG("roff: pass non-scoped text: [%s]\n",
&(*bufp)[pos]);
@@ -336,7 +345,8 @@ roff_parseln(struct roff *r, int ln,
ROFF_DEBUG("roff: intercept scoped context: %s\n",
roffs[t].name);
return((*roffs[t].sub)
- (r, t, bufp, szp, ln, pos, pos, offs));
+ (r, regs, t, bufp,
+ szp, ln, pos, pos, offs));
}
/*
@@ -356,7 +366,8 @@ roff_parseln(struct roff *r, int ln,
roffs[t].name, &(*bufp)[pos]);
assert(roffs[t].proc);
return((*roffs[t].proc)
- (r, t, bufp, szp, ln, ppos, pos, offs));
+ (r, regs, t, bufp,
+ szp, ln, ppos, pos, offs));
}
@@ -412,6 +423,26 @@ roff_parse(const char *buf, int *pos)
}
+static int
+roff_parse_nat(const char *buf, int *res)
+{
+ char *ep;
+ long lval;
+
+ errno = 0;
+ lval = strtol(buf, &ep, 10);
+ if (buf[0] == '\0' || *ep != '\0')
+ return(0);
+ if ((errno == ERANGE &&
+ (lval == LONG_MAX || lval == LONG_MIN)) ||
+ (lval > INT_MAX || lval <= 0))
+ return(0);
+
+ *res = (int)lval;
+ return(1);
+}
+
+
/* ARGSUSED */
static enum rofferr
roff_cblock(ROFF_ARGS)
@@ -622,7 +653,7 @@ roff_block_sub(ROFF_ARGS)
return(ROFF_IGN);
assert(roffs[t].proc);
- return((*roffs[t].proc)(r, t, bufp,
+ return((*roffs[t].proc)(r, regs, t, bufp,
szp, ln, ppos, pos, offs));
}
@@ -673,7 +704,7 @@ roff_cond_sub(ROFF_ARGS)
assert(roffs[t].proc);
return((*roffs[t].proc)
- (r, t, bufp, szp, ln, ppos, pos, offs));
+ (r, regs, t, bufp, szp, ln, ppos, pos, offs));
}
@@ -732,6 +763,15 @@ roff_evalcond(const char *v, int *pos)
/* ARGSUSED */
static enum rofferr
+roff_line(ROFF_ARGS)
+{
+
+ return(ROFF_IGN);
+}
+
+
+/* ARGSUSED */
+static enum rofferr
roff_cond(ROFF_ARGS)
{
int sv;
@@ -838,8 +878,39 @@ roff_cond(ROFF_ARGS)
/* ARGSUSED */
static enum rofferr
-roff_line(ROFF_ARGS)
+roff_nr(ROFF_ARGS)
{
+ const char *key, *val;
+
+ key = &(*bufp)[pos];
+
+ /* Parse register request. */
+ while ((*bufp)[pos] && ' ' != (*bufp)[pos])
+ pos++;
+
+ /*
+ * Set our nil terminator. Because this line is going to be
+ * ignored anyway, we can munge it as we please.
+ */
+ if ((*bufp)[pos])
+ (*bufp)[pos++] = '\0';
+
+ /* Skip whitespace to register token. */
+ while ((*bufp)[pos] && ' ' == (*bufp)[pos])
+ pos++;
+
+ val = &(*bufp)[pos];
+
+ /* Process register token. */
+
+ if (0 == strcmp(key, "nS")) {
+ if ( ! roff_parse_nat(val, &regs->regs[(int)REG_nS].i))
+ regs->regs[(int)REG_nS].i = 0;
+
+ ROFF_DEBUG("roff: register nS: %d\n",
+ regs->regs[(int)REG_nS].i);
+ } else
+ ROFF_DEBUG("roff: ignoring register: %s\n", key);
return(ROFF_IGN);
}
diff --git a/roff.h b/roff.h
index bc2b50c1..9185f912 100644
--- a/roff.h
+++ b/roff.h
@@ -31,8 +31,8 @@ struct roff;
void roff_free(struct roff *);
struct roff *roff_alloc(mandocmsg, void *);
void roff_reset(struct roff *);
-enum rofferr roff_parseln(struct roff *, int,
- char **, size_t *, int, int *);
+enum rofferr roff_parseln(struct roff *, struct regset *,
+ int, char **, size_t *, int, int *);
int roff_endparse(struct roff *);
__END_DECLS