source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* mdocml: Support setting arbitrary roff(7) number registers, preserving
@ 2013-10-05 22:08 schwarze
  0 siblings, 0 replies; only message in thread
From: schwarze @ 2013-10-05 22:08 UTC (permalink / raw)
  To: source

Log Message:
-----------
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.

Modified Files:
--------------
    mdocml:
        libmandoc.h
        mdoc.c
        mdoc_validate.c
        roff.c

Revision Data
-------------
Index: mdoc_validate.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/mdoc_validate.c,v
retrieving revision 1.193
retrieving revision 1.194
diff -Lmdoc_validate.c -Lmdoc_validate.c -u -p -r1.193 -r1.194
--- mdoc_validate.c
+++ mdoc_validate.c
@@ -1,7 +1,7 @@
 /*	$Id$ */
 /*
  * 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. */
 
Index: mdoc.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/mdoc.c,v
retrieving revision 1.203
retrieving revision 1.204
diff -Lmdoc.c -Lmdoc.c -u -p -r1.203 -r1.204
--- mdoc.c
+++ mdoc.c
@@ -295,12 +295,10 @@ mdoc_parseln(struct mdoc *mdoc, int ln, 
 	 * 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) :
Index: roff.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/roff.c,v
retrieving revision 1.179
retrieving revision 1.180
diff -Lroff.c -Lroff.c -u -p -r1.179 -r1.180
--- roff.c
+++ roff.c
@@ -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_
 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);
 }
Index: libmandoc.h
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/libmandoc.h,v
retrieving revision 1.32
retrieving revision 1.33
diff -Llibmandoc.h -Llibmandoc.h -u -p -r1.32 -r1.33
--- libmandoc.h
+++ libmandoc.h
@@ -1,6 +1,7 @@
 /*	$Id$ */
 /*
  * 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 *);
--
 To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2013-10-05 22:08 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-10-05 22:08 mdocml: Support setting arbitrary roff(7) number registers, preserving schwarze

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).