source@mandoc.bsd.lv
 help / color / mirror / Atom feed
From: kristaps@mdocml.bsd.lv
To: source@mdocml.bsd.lv
Subject: mdocml: Give libroff an extremely simple table-lookup instead of
Date: Sat, 29 May 2010 15:41:47 -0400 (EDT)	[thread overview]
Message-ID: <201005291941.o4TJflxU029996@krisdoz.my.domain> (raw)

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

                 reply	other threads:[~2010-05-29 19:41 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=201005291941.o4TJflxU029996@krisdoz.my.domain \
    --to=kristaps@mdocml.bsd.lv \
    --cc=source@mdocml.bsd.lv \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).