浏览代码

Move regex/glob G__ls() filters into lib/gis
More accurate emulation of glob patterns


git-svn-id: https://svn.osgeo.org/grass/grass/trunk@40706 15284696-431f-4ddb-bdfa-cd5b030d7da7

Glynn Clements 15 年之前
父节点
当前提交
af2133adf1

+ 1 - 2
general/g.mlist/Makefile

@@ -2,8 +2,7 @@ MODULE_TOPDIR = ../..
 
 PGM = g.mlist
 
-EXTRA_INC = $(REGEXINCPATH)
-LIBES = $(MANAGELIB) $(GISLIB) $(REGEXLIBPATH) $(REGEXLIB)
+LIBES = $(MANAGELIB) $(GISLIB)
 DEPENDENCIES = $(MANAGEDEP) $(GISDEP)
 
 include $(MODULE_TOPDIR)/include/Make/Module.make

+ 0 - 7
general/g.mlist/global.h

@@ -1,7 +0,0 @@
-#include <grass/gis.h>
-#include <grass/glocale.h>
-#include <grass/list.h>
-
-/* wc2regex.c */
-char *wc2regex(const char *);
-

+ 13 - 32
general/g.mlist/main.c

@@ -9,7 +9,7 @@
  * PURPOSE:      Lists available GRASS data base files of the
  *               user-specified data type to standard output
  *
- * COPYRIGHT:    (C) 1999-2008 by the GRASS Development Team
+ * COPYRIGHT:    (C) 1999-2010 by the GRASS Development Team
  *
  *               This program is free software under the GNU General Public
  *               License (>=v2). Read the file COPYING that comes with GRASS
@@ -20,10 +20,10 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
-#include <regex.h>
-#include <grass/spawn.h>
+#include <grass/gis.h>
 #include <grass/list.h>
-#include "global.h"
+#include <grass/glocale.h>
+#include <grass/spawn.h>
 
 static int any = 0;
 
@@ -31,7 +31,6 @@ static void make_list(const struct list *,
 		      const char *, const char *,
 		      int, int, int);
 static int parse(const char *);
-static int ls_filter(const char *, void *);
 
 int main(int argc, char *argv[])
 {
@@ -54,10 +53,9 @@ int main(int argc, char *argv[])
 	struct Flag *full;
     } flag;
     int i, n, all, num_types;
-    char *pattern = NULL, *exclude = NULL;
+    void *filter = NULL, *exclude = NULL;
     const char *mapset;
     char separator[2], *buf;
-    regex_t regex, regex_ex;
 
     G_gisinit(argv[0]);
 
@@ -157,24 +155,16 @@ int main(int argc, char *argv[])
 
     if (opt.pattern->answer) {
 	if (flag.regex->answer || flag.extended->answer)
-	    pattern = G_store(opt.pattern->answer);
+	    filter = G_ls_regex_filter(opt.pattern->answer, 0, (int) flag.extended->answer);
 	else
-	    pattern = wc2regex(opt.pattern->answer);
-
-	if (regcomp(&regex, pattern, (flag.regex->answer ? 0 : REG_EXTENDED) | REG_NOSUB))
-	    G_fatal_error(_("Unable to compile regular expression %s"), pattern);
-	G_set_ls_filter(ls_filter, &regex);
+	    filter = G_ls_glob_filter(opt.pattern->answer, 0);
     }
 
     if (opt.exclude->answer) {
 	if (flag.regex->answer || flag.extended->answer)
-	    exclude = G_store(opt.exclude->answer);
+	    exclude = G_ls_regex_filter(opt.pattern->answer, 1, (int) flag.extended->answer);
 	else
-	    exclude = wc2regex(opt.exclude->answer);
-
-	if (regcomp(&regex_ex, exclude, (flag.regex->answer ? 0 : REG_EXTENDED) | REG_NOSUB))
-	    G_fatal_error(_("Unable to compile regular expression %s"), exclude);
-	G_set_ls_exclude_filter(ls_filter, &regex_ex);
+	    exclude = G_ls_glob_filter(opt.pattern->answer, 1);
     }
 
     if (strcmp(opt.separator->answer, "newline") == 0)
@@ -235,15 +225,11 @@ int main(int argc, char *argv[])
     if (!flag.pretty->answer && any)
 	fprintf(stdout, "\n");
 
-    if (pattern) {
-	G_free(pattern);
-	regfree(&regex);
-    }
+    if (filter)
+	G_free_ls_filter(filter);
 
-    if (exclude) {
-	G_free(exclude);
-	regfree(&regex_ex);
-    }
+    if (exclude)
+	G_free_ls_filter(exclude);
 
     exit(EXIT_SUCCESS);
 }
@@ -315,8 +301,3 @@ static int parse(const char *data_type)
     return n;
 }
 
-static int ls_filter(const char *filename, void *closure)
-{
-    return filename[0] != '.' &&
-	regexec((regex_t *) closure, filename, 0, NULL, 0) == 0;
-}

+ 0 - 46
general/g.mlist/wc2regex.c

@@ -1,46 +0,0 @@
-#include <grass/gis.h>
-
-char *wc2regex(const char *wc)
-{
-    int i, j;
-    char *regex;
-
-    for (i = 0, j = 2; wc[i]; i++, j++) {
-	switch (wc[i]) {
-	case '.':
-	case '*':
-	    j++;
-	    break;
-	}
-    }
-    regex = (char *)G_malloc(j + 1);
-    j = 0;
-    regex[j++] = '^';
-    for (i = 0; wc[i]; i++) {
-	switch (wc[i]) {
-	case '.':
-	    regex[j++] = '\\';
-	    break;
-	case '*':
-	    regex[j++] = '.';
-	    break;
-	case '?':
-	    regex[j++] = '.';
-	    continue;
-	case '{':
-	    regex[j++] = '(';
-	    continue;
-	case '}':
-	    regex[j++] = ')';
-	    continue;
-	case ',':
-	    regex[j++] = '|';
-	    continue;
-	}
-	regex[j++] = wc[i];
-    }
-    regex[j++] = '$';
-    regex[j] = 0;
-
-    return regex;
-}

+ 2 - 2
general/g.mremove/Makefile

@@ -2,9 +2,9 @@ MODULE_TOPDIR = ../..
 
 PGM = g.mremove
 
-LIBES = $(MANAGELIB) $(RASTERLIB) $(GISLIB) $(REGEXLIBPATH) $(REGEXLIB)
+LIBES = $(MANAGELIB) $(RASTERLIB) $(GISLIB)
 DEPENDENCIES = $(MANAGEDEP) $(RASTERDEP) $(GISDEP)
-EXTRA_INC = $(VECT_INC) $(REGEXINCPATH)
+EXTRA_INC = $(VECT_INC)
 EXTRA_CFLAGS = $(VECT_CFLAGS)
 
 include $(MODULE_TOPDIR)/include/Make/Module.make

+ 3 - 2
general/g.mremove/check_reclass.c

@@ -1,8 +1,9 @@
 #include <string.h>
 
+#include <grass/gis.h>
+#include <grass/list.h>
 #include <grass/raster.h>
-
-#include "global.h"
+#include <grass/glocale.h>
 
 int check_reclass(const char *name, const char *mapset, int force)
 {

+ 0 - 9
general/g.mremove/global.h

@@ -1,9 +0,0 @@
-#include <grass/gis.h>
-#include <grass/glocale.h>
-#include <grass/list.h>
-
-/* wc2regex.c */
-char *wc2regex(const char *);
-
-/* check_reclass.c */
-int check_reclass(const char *, const char *, int);

+ 16 - 19
general/g.mremove/main.c

@@ -17,7 +17,7 @@
  *
  * PURPOSE:      lets users remove GRASS database files
  *
- * COPYRIGHT:    (C) 1999-2008 by the GRASS Development Team
+ * COPYRIGHT:    (C) 1999-2010 by the GRASS Development Team
  *
  *               This program is free software under the GNU General Public
  *               License (>=v2). Read the file COPYING that comes with GRASS
@@ -27,10 +27,13 @@
 
 #include <stdlib.h>
 #include <unistd.h>
-#include <regex.h>
-#include "global.h"
 
-static int ls_filter(const char *, void *);
+#include <grass/gis.h>
+#include <grass/list.h>
+#include <grass/glocale.h>
+
+/* check_reclass.c */
+int check_reclass(const char *, const char *, int);
 
 int main(int argc, char *argv[])
 {
@@ -48,7 +51,7 @@ int main(int argc, char *argv[])
     char *buf, *buf2;
     int num_files, rast, result = EXIT_SUCCESS;
     int i, j, n;
-    regex_t regex;
+    void *filter;
 
     G_gisinit(argv[0]);
 
@@ -122,18 +125,17 @@ int main(int argc, char *argv[])
 	    rast = !G_strcasecmp(list[n].alias, "rast");
 	    for (i = 0; (name = opt[n]->answers[i]); i++) {
 		if (!flag.regex->answer && !flag.extended->answer)
-		    name = wc2regex(name);
-		if (regcomp(&regex, name,
-			    (flag.regex->answer ? 0 : REG_EXTENDED) | REG_NOSUB))
-		    G_fatal_error(
-				  _("Unable to compile regular expression %s"),
+		    filter = G_ls_glob_filter(name, 0);
+		else
+		    filter = G_ls_regex_filter(name, 0,
+					       (int) flag.extended->answer);
+		if (!filter)
+		    G_fatal_error(_("Unable to compile pattern <%s>"),
 				  name);
-		if (!flag.regex->answer && !flag.extended->answer)
-		    G_free(name);
 
-		G_set_ls_filter(ls_filter, &regex);
 		files = G__ls(path, &num_files);
-		regfree(&regex);
+
+		G_free_ls_filter(filter);
 
 		for (j = 0; j < num_files; j++) {
 		    if (!flag.force->answer) {
@@ -160,8 +162,3 @@ int main(int argc, char *argv[])
     exit(result);
 }
 
-static int ls_filter(const char *filename, void *closure)
-{
-    return filename[0] != '.' &&
-	regexec((regex_t *) closure, filename, 0, NULL, 0) == 0;
-}

+ 0 - 46
general/g.mremove/wc2regex.c

@@ -1,46 +0,0 @@
-#include <grass/gis.h>
-
-char *wc2regex(const char *wc)
-{
-    int i, j;
-    char *regex;
-
-    for (i = 0, j = 2; wc[i]; i++, j++) {
-	switch (wc[i]) {
-	case '.':
-	case '*':
-	    j++;
-	    break;
-	}
-    }
-    regex = (char *)G_malloc(j + 1);
-    j = 0;
-    regex[j++] = '^';
-    for (i = 0; wc[i]; i++) {
-	switch (wc[i]) {
-	case '.':
-	    regex[j++] = '\\';
-	    break;
-	case '*':
-	    regex[j++] = '.';
-	    break;
-	case '?':
-	    regex[j++] = '.';
-	    continue;
-	case '{':
-	    regex[j++] = '(';
-	    continue;
-	case '}':
-	    regex[j++] = ')';
-	    continue;
-	case ',':
-	    regex[j++] = '|';
-	    continue;
-	}
-	regex[j++] = wc[i];
-    }
-    regex[j++] = '$';
-    regex[j] = 0;
-
-    return regex;
-}

+ 1 - 1
include/Make/Grass.make

@@ -190,7 +190,7 @@ DRIVERDEPS       = $(GISLIB) $(FTLIB) $(ICONVLIB) $(MATHLIB)
 DSPFDEPS         = $(GISLIB)
 FORMDEPS         = $(DBMILIB) $(GISLIB)
 G3DDEPS          = $(RASTERLIB) $(GISLIB) $(XDRLIB)
-GISDEPS          = $(DATETIMELIB) $(ZLIBLIBPATH) $(ZLIB) $(INTLLIB) $(PTHREADLIBPATH) $(PTHREADLIB) $(MATHLIB)
+GISDEPS          = $(DATETIMELIB) $(ZLIBLIBPATH) $(ZLIB) $(INTLLIB) $(REGEXLIBPATH) $(REGEXLIB) $(PTHREADLIBPATH) $(PTHREADLIB) $(MATHLIB)
 GMATHDEPS        = $(GISLIB) $(FFTWLIB) $(LAPACKLIB) $(BLASLIB) $(CCMATHLIB)
 GPDEDEPS         = $(G3DLIB) $(RASTERLIB) $(GISLIB) $(GMATHLIB) $(MATHLIB)
 GPROJDEPS        = $(GISLIB) $(GDALLIBS) $(PROJLIB) $(MATHLIB)

+ 7 - 0
include/gisdefs.h

@@ -366,6 +366,13 @@ char **G__ls(const char *, int *);
 void G_ls(const char *, FILE *);
 void G_ls_format(char **, int, int, FILE *);
 
+/* ls_filter.c */
+#ifdef HAVE_REGEX_H
+void *G_ls_regex_filter(const char *, int, int);
+void *G_ls_glob_filter(const char *, int);
+void G_free_ls_filter(void *);
+#endif
+
 /* mach_name.c */
 const char *G__machine_name(void);
 

+ 1 - 1
lib/gis/Makefile

@@ -2,7 +2,7 @@ MODULE_TOPDIR = ../..
 
 LIB = GIS
 
-EXTRA_INC = $(ZLIBINCPATH) $(PTHREADINCPATH)
+EXTRA_INC = $(ZLIBINCPATH) $(PTHREADINCPATH) $(REGEXINCPATH)
 
 DATASRC = ellipse.table datum.table datumtransform.table FIPS.code state27 state83 projections
 

+ 195 - 0
lib/gis/ls_filter.c

@@ -0,0 +1,195 @@
+/*!
+ * \file gis/ls_filter.c
+ *
+ * \brief GIS Library - Filename filter functions
+ *
+ * (C) 2010 by Glynn Clements and the GRASS Development Team
+ *
+ * This program is free software under the GNU General Public License
+ * (>=v2). Read the file COPYING that comes with GRASS for details.
+ *
+ * \author Original author Glynn Clements
+ */
+
+#include <grass/config.h>
+#include <grass/gis.h>
+
+#ifdef HAVE_REGEX_H
+
+#include <regex.h>
+
+struct buffer
+{
+    char *buf;
+    size_t len;
+    size_t alloc;
+};
+
+static void init(struct buffer *buf)
+{
+    buf->buf = NULL;
+    buf->len = 0;
+    buf->alloc = 0;
+}
+
+static void add(struct buffer *buf, char c)
+{
+    if (buf->len >= buf->alloc) {
+	buf->alloc += 50;
+	buf->buf = G_realloc(buf->buf, buf->alloc);
+    }
+
+    buf->buf[buf->len++] = c;
+}
+
+static void fini(struct buffer *buf)
+{
+    G_free(buf->buf);
+}
+
+static const char *do_set(struct buffer *buf, const char *p)
+{
+    add(buf, '[');
+
+    if (*p == '!') {
+	add(buf, '^');
+	p++;
+    }
+
+    if (*p == ']') {
+	add(buf, ']');
+	p++;
+    }
+
+    for (; *p && *p != ']'; p++)
+	add(buf, *p);
+
+    if (!*p)
+	return NULL;
+
+    add(buf, ']');
+
+    return p;
+}
+
+static int wc2regex(struct buffer *buf, const char *pat)
+{
+    const char *p;
+    int in_brace = 0;
+
+    init(buf);
+
+    add(buf, '^');
+
+    for (p = pat; p && *p; p++) {
+	switch (*p) {
+	case '\\':
+	case '.':
+	case '|':
+	case '(':
+	case ')':
+	case '+':
+	    add(buf, '\\');
+	    add(buf, *p);
+	    break;
+	case '*':
+	    add(buf, '.');
+	    add(buf, '*');
+	    break;
+	case '?':
+	    add(buf, '.');
+	    break;
+	case '{':
+	    if (in_brace)
+		return 0;
+	    in_brace = 1;
+	    add(buf, '(');
+	    break;
+	case '}':
+	    if (!in_brace)
+		return 0;
+	    in_brace = 0;
+	    add(buf, ')');
+	    break;
+	case ',':
+	    if (in_brace)
+		add(buf, '|');
+	    else
+		add(buf, ',');
+	    break;
+	case '[':
+	    p = do_set(buf, p);
+	    break;
+	default:
+	    add(buf, *p);
+	    break;
+	}
+    }
+
+    if (!p)
+	return 0;
+
+    if (in_brace)
+	return 0;
+
+    add(buf, '$');
+    add(buf, '\0');
+
+    return 1;
+}
+
+static int re_filter(const char *filename, void *closure)
+{
+    regex_t *regex = closure;
+
+    return filename[0] != '.' &&
+	regexec(regex, filename, 0, NULL, 0) == 0;
+}
+
+void *G_ls_regex_filter(const char *pat, int exclude, int extended)
+{
+    regex_t *regex = G_malloc(sizeof(regex_t));
+
+    if (regcomp(regex, pat, (extended ? REG_EXTENDED : 0) | REG_NOSUB) != 0) {
+	G_free(regex);
+	return NULL;
+    }
+
+    if (exclude)
+	G_set_ls_exclude_filter(re_filter, regex);
+    else
+	G_set_ls_filter(re_filter, regex);
+
+    return regex;
+}
+
+void *G_ls_glob_filter(const char *pat, int exclude)
+{
+    struct buffer buf;
+    regex_t *regex;
+
+    init(&buf);
+
+    if (!wc2regex(&buf, pat)) {
+	fini(&buf);
+	return NULL;
+    }
+
+    regex = G_ls_regex_filter(buf.buf, exclude, 1);
+
+    fini(&buf);
+
+    return regex;
+}
+
+void G_free_ls_filter(void *regex)
+{
+    if (!regex)
+	return;
+
+    regfree(regex);
+    G_free(regex);
+}
+
+#endif
+