source@mandoc.bsd.lv
 help / color / mirror / Atom feed
From: kristaps@mdocml.bsd.lv
To: source@mdocml.bsd.lv
Subject: mdocml: Make apropos's lookup use a find(1)-like expression.
Date: Wed, 9 Nov 2011 17:05:56 -0500 (EST)	[thread overview]
Message-ID: <201111092205.pA9M5uL6016395@krisdoz.my.domain> (raw)

Log Message:
-----------
Make apropos's lookup use a find(1)-like expression.  I'll write more on
this when it completes; this is to keep it in-tree.

Right now this uses prefix notation.  Ignore it.  I'll make this into
infix notation real soon.

The goal of this (exprcomp and exprexec) is to have arbitrary logical
expressions.

Modified Files:
--------------
    mdocml:
        apropos.c
        apropos.h
        cgi.c
        db.c

Revision Data
-------------
Index: cgi.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/cgi.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -Lcgi.c -Lcgi.c -u -p -r1.1 -r1.2
--- cgi.c
+++ cgi.c
@@ -47,13 +47,17 @@ struct	req {
 	enum page	 page;
 };
 
+#if 0
 static	void		 html_printtext(const char *);
+#endif
 static	int 		 kval_decode(char *);
 static	void		 kval_parse(struct kval **, size_t *, char *);
 static	void		 kval_free(struct kval *, size_t);
 static	void		 pg_index(const struct req *, char *);
 static	void		 pg_search(const struct req *, char *);
+#if 0
 static	void		 pg_searchres(struct rec *, size_t, void *);
+#endif
 
 static	const char * const pages[PAGE__MAX] = {
 	"index", /* PAGE_INDEX */ 
@@ -64,6 +68,7 @@ static	const char * const medias[MEDIA__
 	"html", /* MEDIA_HTML */
 };
 
+#if 0
 static void
 html_printtext(const char *p)
 {
@@ -88,6 +93,7 @@ html_printtext(const char *p)
 			break;
 		}
 }
+#endif
 
 static void
 kval_free(struct kval *p, size_t sz)
@@ -205,6 +211,7 @@ pg_index(const struct req *req, char *pa
 
 }
 
+#if 0
 static void
 pg_searchres(struct rec *recs, size_t sz, void *arg)
 {
@@ -223,6 +230,7 @@ pg_searchres(struct rec *recs, size_t sz
 		puts(")</A>");
 	}
 }
+#endif
 
 static void
 pg_search(const struct req *req, char *path)
@@ -238,8 +246,8 @@ pg_search(const struct req *req, char *p
 		return;
 
 	memset(&opt, 0, sizeof(struct opts));
-	opt.types = TYPE_NAME | TYPE_DESC;
-	apropos_search(&opt, req->fields[i].val, NULL, pg_searchres);
+	/*opt.types = TYPE_NAME | TYPE_DESC;
+	apropos_search(&opt, req->fields[i].val, NULL, pg_searchres);*/
 }
 
 int
Index: apropos.h
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/apropos.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -Lapropos.h -Lapropos.h -u -p -r1.1 -r1.2
--- apropos.h
+++ apropos.h
@@ -53,15 +53,18 @@ struct	rec {
 struct	opts {
 	const char	*arch; /* restrict to architecture */
 	const char	*cat; /* restrict to manual section */
-	int		 types; /* only types in bitmask */
-	int		 flags;
-#define	OPTS_INSENS	(0x01) /* case-insensitive match */
 };
 
 __BEGIN_DECLS
 
-void	 apropos_search(const struct opts *, const char *, 
-		void *, void (*)(struct rec *, size_t, void *));
+struct	expr;
+
+void	 	 apropos_search(const struct opts *, 
+			const struct expr *, void *, 
+			void (*)(struct rec *, size_t, void *));
+
+struct	expr	*exprcomp(int, char *[], int);
+void		 exprfree(struct expr *);
 
 __END_DECLS
 
Index: apropos.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/apropos.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -Lapropos.c -Lapropos.c -u -p -r1.9 -r1.10
--- apropos.c
+++ apropos.c
@@ -24,29 +24,6 @@
 #include "apropos.h"
 #include "mandoc.h"
 
-struct	type {
-	int		 mask;
-	const char	*name; /* command-line type name */
-};
-
-static	const struct type types[] = {
-	{ TYPE_NAME, "name" },
-	{ TYPE_FUNCTION, "func" },
-	{ TYPE_UTILITY, "utility" },
-	{ TYPE_INCLUDES, "incl" },
-	{ TYPE_VARIABLE, "var" },
-	{ TYPE_STANDARD, "stand" },
-	{ TYPE_AUTHOR, "auth" },
-	{ TYPE_CONFIG, "conf" },
-	{ TYPE_DESC, "desc" },
-	{ TYPE_XREF, "xref" },
-	{ TYPE_PATH, "path" },
-	{ TYPE_ENV, "env" },
-	{ TYPE_ERR, "err" },
-	{ INT_MAX, "all" },
-	{ 0, NULL }
-};
-
 static	int	 cmp(const void *, const void *);
 static	void	 list(struct rec *, size_t, void *);
 static	void	 usage(void);
@@ -56,23 +33,23 @@ static	char	*progname;
 int
 main(int argc, char *argv[])
 {
-	int		 ch, i;
-	char		*q, *v;
+	int		 ch, cs;
 	struct opts	 opts;
+	struct expr	*e;
 	extern int	 optind;
 	extern char	*optarg;
 
 	memset(&opts, 0, sizeof(struct opts));
 
-	q = NULL;
-
 	progname = strrchr(argv[0], '/');
 	if (progname == NULL)
 		progname = argv[0];
 	else
 		++progname;
 
-	while (-1 != (ch = getopt(argc, argv, "S:s:It:"))) 
+	cs = 0;
+
+	while (-1 != (ch = getopt(argc, argv, "S:s:I"))) 
 		switch (ch) {
 		case ('S'):
 			opts.arch = optarg;
@@ -81,26 +58,8 @@ main(int argc, char *argv[])
 			opts.cat = optarg;
 			break;
 		case ('I'):
-			opts.flags |= OPTS_INSENS;
+			cs = 1;
 			break;
-		case ('t'):
-			while (NULL != (v = strsep(&optarg, ","))) {
-				if ('\0' == *v)
-					continue;
-				for (i = 0; types[i].mask; i++) {
-					if (strcmp(types[i].name, v))
-						continue;
-					break;
-				}
-				if (0 == types[i].mask)
-					break;
-				opts.types |= types[i].mask;
-			}
-			if (NULL == v)
-				break;
-			
-			fprintf(stderr, "%s: Bad type\n", v);
-			return(EXIT_FAILURE);
 		default:
 			usage();
 			return(EXIT_FAILURE);
@@ -109,14 +68,13 @@ main(int argc, char *argv[])
 	argc -= optind;
 	argv += optind;
 
-	if (0 == argc || '\0' == **argv) {
-		usage();
+	if (0 == argc) 
 		return(EXIT_SUCCESS);
-	} else
-		q = *argv;
 
-	if (0 == opts.types)
-		opts.types = TYPE_NAME | TYPE_DESC;
+	if (NULL == (e = exprcomp(cs, argv, argc))) {
+		fprintf(stderr, "Bad expression\n");
+		return(EXIT_FAILURE);
+	}
 
 	/*
 	 * Configure databases.
@@ -125,7 +83,8 @@ main(int argc, char *argv[])
 	 * The index database is a recno.
 	 */
 
-	apropos_search(&opts, q, NULL, list);
+	apropos_search(&opts, e, NULL, list);
+	exprfree(e);
 	return(EXIT_SUCCESS);
 }
 
@@ -161,6 +120,6 @@ usage(void)
 			"[-I] "
 			"[-S arch] "
 			"[-s section] "
-			"[-t type[,...]] "
-			"key\n", progname);
+			"EXPR\n", 
+			progname);
 }
Index: db.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/db.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -Ldb.c -Ldb.c -u -p -r1.1 -r1.2
--- db.c
+++ db.c
@@ -30,8 +30,46 @@
 #include "apropos.h"
 #include "mandoc.h"
 
+enum	match {
+	MATCH_REGEX,
+	MATCH_REGEXCASE,
+	MATCH_STR,
+	MATCH_STRCASE
+};
+
+struct	expr {
+	enum match	 match;
+	int	 	 mask;
+	char		*v;
+	regex_t	 	 re;
+};
+
+struct	type {
+	int		 mask;
+	const char	*name;
+};
+
+static	const struct type types[] = {
+	{ TYPE_NAME, "name" },
+	{ TYPE_FUNCTION, "func" },
+	{ TYPE_UTILITY, "utility" },
+	{ TYPE_INCLUDES, "incl" },
+	{ TYPE_VARIABLE, "var" },
+	{ TYPE_STANDARD, "stand" },
+	{ TYPE_AUTHOR, "auth" },
+	{ TYPE_CONFIG, "conf" },
+	{ TYPE_DESC, "desc" },
+	{ TYPE_XREF, "xref" },
+	{ TYPE_PATH, "path" },
+	{ TYPE_ENV, "env" },
+	{ TYPE_ERR, "err" },
+	{ INT_MAX, "all" },
+	{ 0, NULL }
+};
+
 static	DB	*btree_open(void);
 static	int	 btree_read(const DBT *, const struct mchars *, char **);
+static	int	 exprexec(const struct expr *, char *);
 static	DB	*index_open(void);
 static	int	 index_read(const DBT *, const DBT *, 
 			const struct mchars *, struct rec *);
@@ -277,16 +315,15 @@ index_read(const DBT *key, const DBT *va
 }
 
 /*
- * Search the mandocdb database for the regular expression "q".
+ * Search the mandocdb database for the expression "expr".
  * Filter out by "opts".
  * Call "res" with the results, which may be zero.
  */
 void
-apropos_search(const struct opts *opts, const char *q, void *arg, 
-		void (*res)(struct rec *, size_t, void *))
+apropos_search(const struct opts *opts, const struct expr *expr,
+		void *arg, void (*res)(struct rec *, size_t, void *))
 {
 	int		 i, len, root, leaf;
-	regex_t		 reg;
 	DBT		 key, val;
 	DB		*btree, *idx;
 	struct mchars	*mc;
@@ -307,19 +344,8 @@ apropos_search(const struct opts *opts, 
 
 	memset(&srec, 0, sizeof(struct rec));
 
-	if (NULL != q && '\0' == *q)
-		q = NULL;
-
-	ch = REG_EXTENDED | REG_NOSUB | 
-		(OPTS_INSENS & opts->flags ? REG_ICASE : 0);
-
 	/* XXX: error out with bad regexp? */
 
-	if (NULL == q || regcomp(&reg, q, ch)) {
-		(*res)(NULL, 0, arg);
-		return;
-	}
-
 	mc = mchars_alloc();
 
 	/* XXX: return fact that we've errored? */
@@ -337,13 +363,10 @@ apropos_search(const struct opts *opts, 
 		 */
 		if (key.size < 2 || 8 != val.size) 
 			break;
-
-		if ( ! (*(int32_t *)val.data & opts->types))
-			continue;
-
 		if ( ! btree_read(&key, mc, &buf))
 			break;
-		if (regexec(&reg, buf, 0, NULL, 0))
+
+		if ( ! exprexec(expr, buf))
 			continue;
 
 		memcpy(&rec, val.data + 4, sizeof(recno_t));
@@ -432,5 +455,74 @@ out:
 
 	free(buf);
 	free(recs);
-	regfree(&reg);
+}
+
+struct expr *
+exprcomp(int cs, char *argv[], int argc)
+{
+	struct expr	*p;
+	struct expr	 e;
+	int		 i, ch;
+
+	if (3 != argc)
+		return(NULL);
+
+	if (0 == strcmp("-eq", argv[0]))
+		e.match = cs ? MATCH_STRCASE : MATCH_STR;
+	else if (0 == strcmp("-ieq", argv[0]))
+		e.match = MATCH_STRCASE;
+	else if (0 == strcmp("-re", argv[0]))
+		e.match = cs ? MATCH_REGEXCASE : MATCH_REGEX;
+	else if (0 == strcmp("-ire", argv[0]))
+		e.match = MATCH_REGEXCASE;
+	else
+		return(NULL);
+
+	for (i = 0; 0 != types[i].mask; i++)
+		if (0 == strcmp(types[i].name, argv[1]))
+			break;
+
+	if (0 == (e.mask = types[i].mask))
+		return(NULL);
+
+	e.v = mandoc_strdup(argv[2]);
+
+	if (MATCH_REGEX == e.match || MATCH_REGEXCASE == e.match) {
+		ch = REG_EXTENDED | REG_NOSUB;
+		if (MATCH_REGEXCASE == e.match)
+			ch |= REG_ICASE;
+		if (regcomp(&e.re, e.v, ch))
+			return(NULL);
+	}
+
+	p = mandoc_calloc(1, sizeof(struct expr));
+	memcpy(p, &e, sizeof(struct expr));
+	return(p);
+}
+
+void
+exprfree(struct expr *p)
+{
+
+	if (NULL == p)
+		return;
+
+	if (MATCH_REGEX == p->match)
+		regfree(&p->re);
+
+	free(p->v);
+	free(p);
+}
+
+static int
+exprexec(const struct expr *p, char *cp)
+{
+
+	if (MATCH_STR == p->match)
+		return(0 == strcmp(p->v, cp));
+	else if (MATCH_STRCASE == p->match)
+		return(0 == strcasecmp(p->v, cp));
+
+	assert(MATCH_REGEX == p->match);
+	return(0 == regexec(&p->re, cp, 0, NULL, 0));
 }
--
 To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv

                 reply	other threads:[~2011-11-09 22:05 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=201111092205.pA9M5uL6016395@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).