aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2013-10-05 22:08:12 +0000
committerIngo Schwarze <schwarze@openbsd.org>2013-10-05 22:08:12 +0000
commita572afd89f35bf2a05cba26f422436714a0de4de (patch)
treed357d349c277f8b918065cab513078e2e229d0a6
parenta8f58a55c9e1fd8a3804c52ca3873c8291135319 (diff)
downloadmandoc-a572afd89f35bf2a05cba26f422436714a0de4de.tar.gz
mandoc-a572afd89f35bf2a05cba26f422436714a0de4de.tar.zst
mandoc-a572afd89f35bf2a05cba26f422436714a0de4de.zip
Support setting arbitrary roff(7) number registers,
preserving read support for the ".nr nS" SYNOPSIS state register. Inspired by NetBSD roff.c rev. 1.18 (Christos Zoulas, March 21, 2013), but implemented differently. I don't want to have yet another different implementation of a hash table in mandoc - it would be the second one in roff.c alone and the fifth one in mandoc grand total. Instead, i designed and implemented roff_setreg() and roff_getreg() to be similar to roff_setstrn() and roff_getstrn(). Once we feel the need to optimize, we can introduce one common hash table implementation for everything in mandoc.
-rw-r--r--libmandoc.h13
-rw-r--r--mdoc.c12
-rw-r--r--mdoc_validate.c13
-rw-r--r--roff.c85
4 files changed, 73 insertions, 50 deletions
diff --git a/libmandoc.h b/libmandoc.h
index 9b3ffee1..df2c8fc6 100644
--- a/libmandoc.h
+++ b/libmandoc.h
@@ -1,6 +1,7 @@
-/* $Id: libmandoc.h,v 1.32 2012/11/19 17:57:23 schwarze Exp $ */
+/* $Id: libmandoc.h,v 1.33 2013/10/05 22:08:12 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 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
@@ -29,11 +30,6 @@ enum rofferr {
ROFF_ERR /* badness: puke and stop */
};
-enum regs {
- REG_nS = 0, /* nS register */
- REG__MAX
-};
-
__BEGIN_DECLS
struct roff;
@@ -72,9 +68,8 @@ void roff_reset(struct roff *);
enum rofferr roff_parseln(struct roff *, int,
char **, size_t *, int, int *);
void roff_endparse(struct roff *);
-int roff_regisset(const struct roff *, enum regs);
-unsigned int roff_regget(const struct roff *, enum regs);
-void roff_regunset(struct roff *, enum regs);
+void roff_setreg(struct roff *, const char *, unsigned int);
+unsigned int roff_getreg(const struct roff *, const char *);
char *roff_strdup(const struct roff *, const char *);
int roff_getcontrol(const struct roff *,
const char *, int *);
diff --git a/mdoc.c b/mdoc.c
index df68229c..c5cfef3c 100644
--- a/mdoc.c
+++ b/mdoc.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc.c,v 1.203 2012/11/17 00:26:33 schwarze Exp $ */
+/* $Id: mdoc.c,v 1.204 2013/10/05 22:08:12 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2012 Ingo Schwarze <schwarze@openbsd.org>
@@ -295,12 +295,10 @@ mdoc_parseln(struct mdoc *mdoc, int ln, char *buf, int offs)
* whether this mode is on or off.
* Note that this mode is also switched by the Sh macro.
*/
- if (roff_regisset(mdoc->roff, REG_nS)) {
- if (roff_regget(mdoc->roff, REG_nS))
- mdoc->flags |= MDOC_SYNOPSIS;
- else
- mdoc->flags &= ~MDOC_SYNOPSIS;
- }
+ if (roff_getreg(mdoc->roff, "nS"))
+ mdoc->flags |= MDOC_SYNOPSIS;
+ else
+ mdoc->flags &= ~MDOC_SYNOPSIS;
return(roff_getcontrol(mdoc->roff, buf, &offs) ?
mdoc_pmacro(mdoc, ln, buf, offs) :
diff --git a/mdoc_validate.c b/mdoc_validate.c
index 8ffc3937..b4d60315 100644
--- a/mdoc_validate.c
+++ b/mdoc_validate.c
@@ -1,7 +1,7 @@
-/* $Id: mdoc_validate.c,v 1.193 2013/09/16 00:25:07 schwarze Exp $ */
+/* $Id: mdoc_validate.c,v 1.194 2013/10/05 22:08:12 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010, 2011, 2012 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2011, 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
@@ -888,8 +888,6 @@ pre_sh(PRE_ARGS)
if (MDOC_BLOCK != n->type)
return(1);
-
- roff_regunset(mdoc->roff, REG_nS);
return(check_parent(mdoc, n, MDOC_MAX, MDOC_ROOT));
}
@@ -1905,10 +1903,13 @@ post_sh_head(POST_ARGS)
/* The SYNOPSIS gets special attention in other areas. */
- if (SEC_SYNOPSIS == sec)
+ if (SEC_SYNOPSIS == sec) {
+ roff_setreg(mdoc->roff, "nS", 1);
mdoc->flags |= MDOC_SYNOPSIS;
- else
+ } else {
+ roff_setreg(mdoc->roff, "nS", 0);
mdoc->flags &= ~MDOC_SYNOPSIS;
+ }
/* Mark our last section. */
diff --git a/roff.c b/roff.c
index 062758ce..eb9d495e 100644
--- a/roff.c
+++ b/roff.c
@@ -1,4 +1,4 @@
-/* $Id: roff.c,v 1.179 2013/10/05 20:30:05 schwarze Exp $ */
+/* $Id: roff.c,v 1.180 2013/10/05 22:08:12 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
@@ -79,16 +79,6 @@ enum roffrule {
};
/*
- * A single register entity. If "set" is zero, the value of the
- * register should be the default one, which is per-register.
- * Registers are assumed to be unsigned ints for now.
- */
-struct reg {
- int set; /* whether set or not */
- unsigned int u; /* unsigned integer */
-};
-
-/*
* An incredibly-simple string buffer.
*/
struct roffstr {
@@ -105,6 +95,16 @@ struct roffkv {
struct roffkv *next; /* next in list */
};
+/*
+ * A single number register as part of a singly-linked list.
+ * Registers are assumed to be unsigned ints for now.
+ */
+struct roffreg {
+ struct roffstr key;
+ unsigned int u;
+ struct roffreg *next;
+};
+
struct roff {
enum mparset parsetype; /* requested parse type */
struct mparse *parse; /* parse point */
@@ -112,7 +112,7 @@ struct roff {
enum roffrule rstack[RSTACK_MAX]; /* stack of !`ie' rules */
char control; /* control character */
int rstackpos; /* position in rstack */
- struct reg regs[REG__MAX];
+ struct roffreg *regtab; /* number registers */
struct roffkv *strtab; /* user-defined strings & macros */
struct roffkv *xmbtab; /* multi-byte trans table (`tr') */
struct roffstr *xtab; /* single-byte trans table (`tr') */
@@ -183,6 +183,7 @@ static enum rofferr roff_cond_sub(ROFF_ARGS);
static enum rofferr roff_ds(ROFF_ARGS);
static enum roffrule roff_evalcond(const char *, int *);
static void roff_free1(struct roff *);
+static void roff_freereg(struct roffreg *);
static void roff_freestr(struct roffkv *);
static char *roff_getname(struct roff *, char **, int, int);
static const char *roff_getstrn(const struct roff *,
@@ -424,6 +425,10 @@ roff_free1(struct roff *r)
r->strtab = r->xmbtab = NULL;
+ roff_freereg(r->regtab);
+
+ r->regtab = NULL;
+
if (r->xtab)
for (i = 0; i < 128; i++)
free(r->xtab[i].p);
@@ -440,7 +445,6 @@ roff_reset(struct roff *r)
roff_free1(r);
r->control = 0;
- memset(&r->regs, 0, sizeof(struct reg) * REG__MAX);
for (i = 0; i < PREDEFS_MAX; i++)
roff_setstr(r, predefs[i].name, predefs[i].str, 0);
@@ -1258,25 +1262,52 @@ roff_ds(ROFF_ARGS)
return(ROFF_IGN);
}
-int
-roff_regisset(const struct roff *r, enum regs reg)
+void
+roff_setreg(struct roff *r, const char *name, unsigned int val)
{
+ struct roffreg *reg;
+
+ /* Search for an existing register with the same name. */
+ reg = r->regtab;
+
+ while (reg && strcmp(name, reg->key.p))
+ reg = reg->next;
- return(r->regs[(int)reg].set);
+ if (NULL == reg) {
+ /* Create a new register. */
+ reg = mandoc_malloc(sizeof(struct roffreg));
+ reg->key.p = mandoc_strdup(name);
+ reg->key.sz = strlen(name);
+ reg->next = r->regtab;
+ r->regtab = reg;
+ }
+
+ reg->u = val;
}
unsigned int
-roff_regget(const struct roff *r, enum regs reg)
+roff_getreg(const struct roff *r, const char *name)
{
+ struct roffreg *reg;
+
+ for (reg = r->regtab; reg; reg = reg->next)
+ if (0 == strcmp(name, reg->key.p))
+ return(reg->u);
- return(r->regs[(int)reg].u);
+ return(0);
}
-void
-roff_regunset(struct roff *r, enum regs reg)
+static void
+roff_freereg(struct roffreg *reg)
{
+ struct roffreg *old_reg;
- r->regs[(int)reg].set = 0;
+ while (NULL != reg) {
+ free(reg->key.p);
+ old_reg = reg;
+ reg = reg->next;
+ free(old_reg);
+ }
}
/* ARGSUSED */
@@ -1290,13 +1321,11 @@ roff_nr(ROFF_ARGS)
val = *bufp + pos;
key = roff_getname(r, &val, ln, pos);
- if (0 == strcmp(key, "nS")) {
- r->regs[(int)REG_nS].set = 1;
- if ((iv = mandoc_strntoi(val, strlen(val), 10)) >= 0)
- r->regs[(int)REG_nS].u = (unsigned)iv;
- else
- r->regs[(int)REG_nS].u = 0u;
- }
+ iv = mandoc_strntoi(val, strlen(val), 10);
+ if (0 > iv)
+ iv = 0;
+
+ roff_setreg(r, key, (unsigned)iv);
return(ROFF_IGN);
}