source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* mdocml: Give libroff an extremely simple table-lookup instead of
@ 2010-05-29 19:41 kristaps
  0 siblings, 0 replies; only message in thread
From: kristaps @ 2010-05-29 19:41 UTC (permalink / raw)
  To: source

Log Message:
-----------
Give libroff an extremely simple table-lookup instead of iterating over
each and every macro.  The table keys on the first character then walks
a chain.  Good enough for now.

Modified Files:
--------------
    mdocml:
        roff.c

Revision Data
-------------
Index: roff.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/roff.c,v
retrieving revision 1.84
retrieving revision 1.85
diff -Lroff.c -Lroff.c -u -p -r1.84 -r1.85
--- roff.c
+++ roff.c
@@ -19,6 +19,7 @@
 #endif
 
 #include <assert.h>
+#include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
@@ -91,6 +92,7 @@ struct	roffmac {
 	roffproc	 sub; /* process as child of macro */
 	int		 flags;
 #define	ROFFMAC_STRUCT	(1 << 0) /* always interpret */
+	struct roffmac	*next;
 };
 
 static	enum rofferr	 roff_block(ROFF_ARGS);
@@ -103,32 +105,65 @@ static	enum rofferr	 roff_cond_text(ROFF
 static	enum rofferr	 roff_cond_sub(ROFF_ARGS);
 static	enum rofferr	 roff_line(ROFF_ARGS);
 
-const	struct roffmac	 roffs[ROFF_MAX] = {
-	{ "am", roff_block, roff_block_text, roff_block_sub, 0 },
-	{ "ami", roff_block, roff_block_text, roff_block_sub, 0 },
-	{ "am1", roff_block, roff_block_text, roff_block_sub, 0 },
-	{ "de", roff_block, roff_block_text, roff_block_sub, 0 },
-	{ "dei", roff_block, roff_block_text, roff_block_sub, 0 },
-	{ "de1", roff_block, roff_block_text, roff_block_sub, 0 },
-	{ "ds", roff_line, NULL, NULL, 0 },
-	{ "el", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT },
-	{ "ie", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT },
-	{ "if", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT },
-	{ "ig", roff_block, roff_block_text, roff_block_sub, 0 },
-	{ "rm", roff_line, NULL, NULL, 0 },
-	{ "tr", roff_line, NULL, NULL, 0 },
-	{ ".", roff_cblock, NULL, NULL, 0 },
-	{ "\\}", roff_ccond, NULL, NULL, 0 },
+/* See roff_hash_find() */
+
+#define	ASCII_HI	 126
+#define	ASCII_LO	 33
+#define	HASHWIDTH	(ASCII_HI - ASCII_LO + 1)
+
+static	struct roffmac	*hash[HASHWIDTH];
+
+static	struct roffmac	 roffs[ROFF_MAX] = {
+	{ "am", roff_block, roff_block_text, roff_block_sub, 0, NULL },
+	{ "ami", roff_block, roff_block_text, roff_block_sub, 0, NULL },
+	{ "am1", roff_block, roff_block_text, roff_block_sub, 0, NULL },
+	{ "de", roff_block, roff_block_text, roff_block_sub, 0, NULL },
+	{ "dei", roff_block, roff_block_text, roff_block_sub, 0, NULL },
+	{ "de1", roff_block, roff_block_text, roff_block_sub, 0, NULL },
+	{ "ds", roff_line, NULL, NULL, 0, NULL },
+	{ "el", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL },
+	{ "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 },
+	{ "rm", roff_line, NULL, NULL, 0, NULL },
+	{ "tr", roff_line, NULL, NULL, 0, NULL },
+	{ ".", roff_cblock, NULL, NULL, 0, NULL },
+	{ "\\}", roff_ccond, NULL, NULL, 0, NULL },
 };
 
 static	void		 roff_free1(struct roff *);
 static	enum rofft	 roff_hash_find(const char *);
+static	void		 roff_hash_init(void);
 static	void		 roffnode_cleanscope(struct roff *);
 static	int		 roffnode_push(struct roff *, 
 				enum rofft, int, int);
 static	void		 roffnode_pop(struct roff *);
 static	enum rofft	 roff_parse(const char *, int *);
 
+/* See roff_hash_find() */
+#define	ROFF_HASH(p)	(p[0] - ASCII_LO)
+
+static void
+roff_hash_init(void)
+{
+	struct roffmac	 *n;
+	int		  buc, i;
+
+	for (i = 0; i < (int)ROFF_MAX; i++) {
+		assert(roffs[i].name[0] >= ASCII_LO);
+		assert(roffs[i].name[0] <= ASCII_HI);
+
+		buc = ROFF_HASH(roffs[i].name);
+
+		if (NULL != (n = hash[buc])) {
+			for ( ; n->next; n = n->next)
+				/* Do nothing. */ ;
+			n->next = &roffs[i];
+		} else
+			hash[buc] = &roffs[i];
+	}
+}
+
 
 /*
  * Look up a roff token by its name.  Returns ROFF_MAX if no macro by
@@ -137,13 +172,26 @@ static	enum rofft	 roff_parse(const char
 static enum rofft
 roff_hash_find(const char *p)
 {
-	int		 i;
-
-	/* FIXME: make this be fast and efficient. */
+	int		 buc;
+	struct roffmac	*n;
 
-	for (i = 0; i < (int)ROFF_MAX; i++)
-		if (0 == strcmp(roffs[i].name, p))
-			return((enum rofft)i);
+	/*
+	 * libroff has an extremely simple hashtable, for the time
+	 * being, which simply keys on the first character, which must
+	 * be printable, then walks a chain.  It works well enough until
+	 * optimised.
+	 */
+
+	if (p[0] < ASCII_LO || p[0] > ASCII_HI)
+		return(ROFF_MAX);
+
+	buc = ROFF_HASH(p);
+
+	if (NULL == (n = hash[buc]))
+		return(ROFF_MAX);
+	for ( ; n; n = n->next)
+		if (0 == strcmp(n->name, p))
+			return((enum rofft)(n - roffs));
 
 	return(ROFF_MAX);
 }
@@ -236,6 +284,8 @@ roff_alloc(const mandocmsg msg, void *da
 	r->msg = msg;
 	r->data = data;
 	r->rstackpos = -1;
+	
+	roff_hash_init();
 	return(r);
 }
 
--
 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:[~2010-05-29 19:41 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-05-29 19:41 mdocml: Give libroff an extremely simple table-lookup instead of kristaps

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).