source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* mdocml: Rewrite the expression parser for a more concise syntax:
@ 2011-11-13 11:10 schwarze
  0 siblings, 0 replies; only message in thread
From: schwarze @ 2011-11-13 11:10 UTC (permalink / raw)
  To: source

Log Message:
-----------
Rewrite the expression parser for a more concise syntax:

 apropos [search_type[,...]=]substring
 apropos search_type[,...][,i]~regex

... and expression evaluation must take the search type into account.

This allows to:
* drop the global -I option and
* drop the enum match, just using a boolean int.

"go ahead" kristaps@

Modified Files:
--------------
    mdocml:
        apropos.c
        apropos_db.c
        apropos_db.h

Revision Data
-------------
Index: apropos_db.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/apropos_db.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -Lapropos_db.c -Lapropos_db.c -u -p -r1.2 -r1.3
--- apropos_db.c
+++ apropos_db.c
@@ -1,6 +1,7 @@
 /*	$Id$ */
 /*
  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2011 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
@@ -31,15 +32,8 @@
 #include "apropos_db.h"
 #include "mandoc.h"
 
-enum	match {
-	MATCH_REGEX,
-	MATCH_REGEXCASE,
-	MATCH_STR,
-	MATCH_STRCASE
-};
-
 struct	expr {
-	enum match	 match;
+	int		 regex;
 	int	 	 mask;
 	char		*v;
 	regex_t	 	 re;
@@ -71,7 +65,7 @@ static	const struct type types[] = {
 
 static	DB	*btree_open(void);
 static	int	 btree_read(const DBT *, const struct mchars *, char **);
-static	int	 exprexec(const struct expr *, char *);
+static	int	 exprexec(const struct expr *, char *, int);
 static	DB	*index_open(void);
 static	int	 index_read(const DBT *, const DBT *, 
 			const struct mchars *, struct rec *);
@@ -368,7 +362,7 @@ apropos_search(const struct opts *opts, 
 		if ( ! btree_read(&key, mc, &buf))
 			break;
 
-		if ( ! exprexec(expr, buf))
+		if ( ! exprexec(expr, buf, *(int *)val.data))
 			continue;
 
 		memcpy(&rec, val.data + 4, sizeof(recno_t));
@@ -460,55 +454,55 @@ out:
 }
 
 struct expr *
-exprcomp(int cs, char *argv[], int argc)
+exprcomp(int argc, char *argv[])
 {
 	struct expr	*p;
 	struct expr	 e;
-	int		 i, pos, ch;
-
-	pos = 0;
-
-	if (pos > argc)
-		return(NULL);
-
-	for (i = 0; 0 != types[i].mask; i++)
-		if (0 == strcmp(types[i].name, argv[pos]))
-			break;
-
-	if (0 == (e.mask = types[i].mask))
-		return(NULL);
+	char		*key;
+	int		 i, icase;
 
-	if (++pos > argc--)
+	if (0 >= argc)
 		return(NULL);
 
-	if ('-' != *argv[pos]) 
-		e.match = cs ? MATCH_STRCASE : MATCH_STR;
-	else if (0 == strcmp("-eq", argv[pos]))
-		e.match = cs ? MATCH_STRCASE : MATCH_STR;
-	else if (0 == strcmp("-ieq", argv[pos]))
-		e.match = MATCH_STRCASE;
-	else if (0 == strcmp("-re", argv[pos]))
-		e.match = cs ? MATCH_REGEXCASE : MATCH_REGEX;
-	else if (0 == strcmp("-ire", argv[pos]))
-		e.match = MATCH_REGEXCASE;
-	else
-		return(NULL);
+	/*
+	 * Choose regex or substring match.
+	 */
+
+	if (NULL == (e.v = strpbrk(*argv, "=~"))) {
+		e.regex = 0;
+		e.v = *argv;
+	} else {
+		e.regex = '~' == *e.v;
+		*e.v++ = '\0';
+	}
 
-	if ('-' == *argv[pos])
-		pos++;
+	/*
+	 * Determine the record types to search for.
+	 */
+
+	icase = 0;
+	e.mask = 0;
+	if (*argv < e.v) {
+		while (NULL != (key = strsep(argv, ","))) {
+			if ('i' == key[0] && '\0' == key[1]) {
+				icase = REG_ICASE;
+				continue;
+			}
+			i = 0;
+			while (types[i].mask &&
+			    strcmp(types[i].name, key))
+				i++;
+			e.mask |= types[i].mask;
+		}
+	}
+	if (0 == e.mask)
+		e.mask = TYPE_Nm | TYPE_Nd;
 
-	if (pos > argc--)
+	if (e.regex &&
+	    regcomp(&e.re, e.v, REG_EXTENDED | REG_NOSUB | icase))
 		return(NULL);
 
-	e.v = mandoc_strdup(argv[pos]);
-
-	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);
-	}
+	e.v = mandoc_strdup(e.v);
 
 	p = mandoc_calloc(1, sizeof(struct expr));
 	memcpy(p, &e, sizeof(struct expr));
@@ -522,7 +516,7 @@ exprfree(struct expr *p)
 	if (NULL == p)
 		return;
 
-	if (MATCH_REGEX == p->match)
+	if (p->regex)
 		regfree(&p->re);
 
 	free(p->v);
@@ -530,14 +524,14 @@ exprfree(struct expr *p)
 }
 
 static int
-exprexec(const struct expr *p, char *cp)
+exprexec(const struct expr *p, char *cp, int mask)
 {
 
-	if (MATCH_STR == p->match)
-		return(0 == strcmp(p->v, cp));
-	else if (MATCH_STRCASE == p->match)
-		return(0 == strcasecmp(p->v, cp));
+	if ( ! (mask & p->mask))
+		return(0);
 
-	assert(MATCH_REGEX == p->match);
-	return(0 == regexec(&p->re, cp, 0, NULL, 0));
+	if (p->regex)
+		return(0 == regexec(&p->re, cp, 0, NULL, 0));
+	else
+		return(NULL != strcasestr(cp, p->v));
 }
Index: apropos_db.h
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/apropos_db.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -Lapropos_db.h -Lapropos_db.h -u -p -r1.2 -r1.3
--- apropos_db.h
+++ apropos_db.h
@@ -49,7 +49,7 @@ void	 	 apropos_search(const struct opts
 			const struct expr *, void *, 
 			void (*)(struct rec *, size_t, void *));
 
-struct	expr	*exprcomp(int, char *[], int);
+struct	expr	*exprcomp(int, char *[]);
 void		 exprfree(struct expr *);
 
 __END_DECLS
Index: apropos.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/apropos.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -Lapropos.c -Lapropos.c -u -p -r1.11 -r1.12
--- apropos.c
+++ apropos.c
@@ -33,7 +33,7 @@ static	char	*progname;
 int
 main(int argc, char *argv[])
 {
-	int		 ch, cs;
+	int		 ch;
 	struct opts	 opts;
 	struct expr	*e;
 	extern int	 optind;
@@ -47,9 +47,7 @@ main(int argc, char *argv[])
 	else
 		++progname;
 
-	cs = 0;
-
-	while (-1 != (ch = getopt(argc, argv, "S:s:I"))) 
+	while (-1 != (ch = getopt(argc, argv, "S:s:"))) 
 		switch (ch) {
 		case ('S'):
 			opts.arch = optarg;
@@ -57,9 +55,6 @@ main(int argc, char *argv[])
 		case ('s'):
 			opts.cat = optarg;
 			break;
-		case ('I'):
-			cs = 1;
-			break;
 		default:
 			usage();
 			return(EXIT_FAILURE);
@@ -71,7 +66,7 @@ main(int argc, char *argv[])
 	if (0 == argc) 
 		return(EXIT_SUCCESS);
 
-	if (NULL == (e = exprcomp(cs, argv, argc))) {
+	if (NULL == (e = exprcomp(argc, argv))) {
 		fprintf(stderr, "Bad expression\n");
 		return(EXIT_FAILURE);
 	}
--
 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:[~2011-11-13 11:10 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-11-13 11:10 mdocml: Rewrite the expression parser for a more concise syntax: 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).