[GRASS-SVN] r31881 - in grass-addons/general: . g.xlist g.xremove

svn_grass at osgeo.org svn_grass at osgeo.org
Sun Jun 29 07:44:57 EDT 2008


Author: hcho
Date: 2008-06-29 07:44:57 -0400 (Sun, 29 Jun 2008)
New Revision: 31881

Added:
   grass-addons/general/g.xlist/
   grass-addons/general/g.xlist/Makefile
   grass-addons/general/g.xlist/description.html
   grass-addons/general/g.xlist/gisdefs.h
   grass-addons/general/g.xlist/global.h
   grass-addons/general/g.xlist/join.c
   grass-addons/general/g.xlist/ls.c
   grass-addons/general/g.xlist/main.c
   grass-addons/general/g.xlist/read_list.c
   grass-addons/general/g.xlist/wc2regex.c
   grass-addons/general/g.xremove/
   grass-addons/general/g.xremove/Makefile
   grass-addons/general/g.xremove/check_reclass.c
   grass-addons/general/g.xremove/description.html
   grass-addons/general/g.xremove/do_remove.c
   grass-addons/general/g.xremove/gisdefs.h
   grass-addons/general/g.xremove/global.h
   grass-addons/general/g.xremove/join.c
   grass-addons/general/g.xremove/ls.c
   grass-addons/general/g.xremove/main.c
   grass-addons/general/g.xremove/read_list.c
   grass-addons/general/g.xremove/sighold.c
   grass-addons/general/g.xremove/wc2regex.c
Log:
Added g.xlist/g.xremove:
- C implementations of g.mlist/g.mremove
- No dependency on g.list/g.remove
- Requires POSIX regex(3) functions.
- Extended G__ls function.
- Added G_(set|get)_ls_filter and G_join_element functions.


Added: grass-addons/general/g.xlist/Makefile
===================================================================
--- grass-addons/general/g.xlist/Makefile	                        (rev 0)
+++ grass-addons/general/g.xlist/Makefile	2008-06-29 11:44:57 UTC (rev 31881)
@@ -0,0 +1,10 @@
+MODULE_TOPDIR = ../../../grass
+
+PGM = g.xlist
+
+LIBES = $(GISLIB)
+DEPENDENCIES = $(GISDEP)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd

Added: grass-addons/general/g.xlist/description.html
===================================================================
--- grass-addons/general/g.xlist/description.html	                        (rev 0)
+++ grass-addons/general/g.xlist/description.html	2008-06-29 11:44:57 UTC (rev 31881)
@@ -0,0 +1,65 @@
+<h2>DESCRIPTION</h2>
+
+<em>g.xlist</em> searches for data files matching a pattern given by wildcards or POSIX Extended Regular Expressions.
+
+<h2>EXAMPLES</h2>
+
+List all available GRASS data base files:
+<div class="code"><pre>
+  g.xlist type=all
+</pre></div>
+
+List all raster and vector maps:
+<div class="code"><pre>
+  g.xlist type=rast,vect
+</pre></div>
+
+<h3>Wildcards:</h3>
+
+List all vector maps starting with letter "r":
+<div class="code"><pre>
+  g.xlist type=vect pattern="r*"
+</pre></div>
+
+List certain raster maps with one variable character/number:
+<div class="code"><pre>
+  g.xlist type=rast pattern="N45E00?.meters"
+</pre></div>
+
+<h3>Regular expressions:</h3>
+
+Print out all soils map with "soils" in their name:
+<div class="code"><pre>
+  g.xlist -r type=rast pattern='^soils'
+</pre></div>
+
+Print out "tmp" if "tmp" raster map exists:
+<div class="code"><pre>
+  g.xlist -r pattern='^tmp$'
+</pre></div>
+
+Print out "tmp0" ..."tmp9" if corresponding vector map exists (each map name linewise):
+<div class="code"><pre>
+  g.xlist -r type=vect pattern='^tmp[0-9]$'
+</pre></div>
+
+Print out "tmp0" ..."tmp9" if corresponding vector map exists (each map name comma separated):
+<div class="code"><pre>
+  g.xlist -r type=vect separator=, pattern='^tmp[0-9]$'
+</pre></div>
+
+This may be useful for other programs' parameter input 
+(e.g. <em><a href="r.series.html">r.series</a></em>).
+
+<h2>SEE ALSO</h2>
+
+<em><a href="g.list.html">g.list</a></em>
+<p>
+<a href="http://en.wikipedia.org/wiki/Regular_expression">Regular expression</a> (from Wikipedia, the free encyclopedia)
+
+<h2>AUTHOR</h2>
+
+Huidae Cho<br>
+grass4u at gmail.com
+
+<p><i>Last changed: $Date: 2008-06-28 04:37:22 -0500 (Sat, 28 Jun 2008) $</i>

Added: grass-addons/general/g.xlist/gisdefs.h
===================================================================
--- grass-addons/general/g.xlist/gisdefs.h	                        (rev 0)
+++ grass-addons/general/g.xlist/gisdefs.h	2008-06-29 11:44:57 UTC (rev 31881)
@@ -0,0 +1,16 @@
+#ifndef GISDEFS_H
+#define GISDEFS_H
+
+#define G_JOIN_ELEMENT_TYPE 0x1
+#define G_JOIN_ELEMENT_MAPSET 0x2
+
+/* join.c */
+const char *G_join_element(const char *, const char *, const char *,
+			   const char *, int, int *);
+
+/* ls.c */
+void G_set_ls_filter(const char *);
+const char *G_get_ls_filter(void);
+const char **G__ls(const char *, int *);
+
+#endif

Added: grass-addons/general/g.xlist/global.h
===================================================================
--- grass-addons/general/g.xlist/global.h	                        (rev 0)
+++ grass-addons/general/g.xlist/global.h	2008-06-29 11:44:57 UTC (rev 31881)
@@ -0,0 +1,29 @@
+#include <grass/gis.h>
+#include <grass/glocale.h>
+
+struct list
+{
+    char **element;		/* list of related elements */
+    char *alias;		/* element alias */
+    char **desc;		/* description of elements */
+    char *text;			/* menu text */
+    int nelem;			/* number of elements */
+    char status;
+    char *mainelem;		/* main element */
+    char *maindesc;		/* main element description */
+};
+
+/* read_list.c */
+int read_list(int);
+
+/* wc2regex.c */
+char *wc2regex(const char *);
+
+#ifdef MAIN
+#	define GLOBAL
+#else
+#	define GLOBAL extern
+#endif
+
+GLOBAL int nlist;
+GLOBAL struct list *list;

Added: grass-addons/general/g.xlist/join.c
===================================================================
--- grass-addons/general/g.xlist/join.c	                        (rev 0)
+++ grass-addons/general/g.xlist/join.c	2008-06-29 11:44:57 UTC (rev 31881)
@@ -0,0 +1,158 @@
+
+/**
+   \file join.c
+
+   \brief Return a string that contains elements
+
+   \author Huidae Cho
+
+   (C) 2008 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
+   for details.
+*/
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+#include <grass/gis.h>
+#include <grass/glocale.h>
+
+#include "gisdefs.h"
+
+static int join_element(const char *, const char *, const char *,
+			const char *, int, const char **);
+
+/**
+   \brief General purpose join function.
+
+   Will collect file names from all mapsets
+   in the mapset list for a specified database element
+   and join them into a string.
+
+   Note: Use G_(set|get)_ls_filter functions to filter out unwanted file names.
+
+   \param element    Database element (eg, "cell", "cellhd", etc)
+   \param alias      Alias for element (if NULL, element is used)
+   \param mapset     Mapset to be listed "" to list all mapsets in mapset search list 
+   "." will list current mapset
+   \param separator  Map name separator
+   \param flags      G_JOIN_ELEMENT_TYPE   Include alias
+                     G_JOIN_ELEMENT_MAPSET Include mapset name
+   \param count      Return the number of elements (if NULL, ignored)
+
+   \return String pointer
+*/
+const char *G_join_element(const char *element,
+			   const char *alias,
+			   const char *mapset,
+			   const char *separator, int flags, int *count)
+{
+    int c, n;
+    const char *buf;
+
+    c = 0;
+    if (alias == 0 || *alias == 0)
+	alias = element;
+
+    /*
+     * if no specific mapset is requested, list the mapsets
+     * from the mapset search list
+     * otherwise just list the specified mapset
+     */
+    buf = G_strdup("");
+    if (mapset == 0 || *mapset == 0)
+	for (n = 0; (mapset = G__mapset_name(n)); n++)
+	    c += join_element(element, alias, mapset, separator, flags, &buf);
+    else
+	c = join_element(element, alias, mapset, separator, flags, &buf);
+
+    if (count)
+	*count = c;
+    return buf;
+}
+
+static int join_element(const char *element,
+			const char *alias,
+			const char *mapset,
+			const char *separator, int flags, const char **buf)
+{
+    char path[GPATH_MAX], *p;
+    int i, count = 0;
+    int buf_len, alias_len, list_len, sep_len = strlen(separator), mapset_len;
+    const char **list;
+
+    /*
+     * convert . to current mapset
+     */
+    if (strcmp(mapset, ".") == 0)
+	mapset = G_mapset();
+
+    mapset_len = strlen(mapset);
+
+    /*
+     * get the full name of the GIS directory within the mapset
+     * and list its contents (if it exists)
+     */
+    G__file_name(path, element, "", mapset);
+    if (access(path, 0) != 0)
+	return count;
+
+    list = G__ls(path, &count);
+
+    alias_len = strlen(alias);
+    for (i = 0; i < count; i++) {
+	buf_len = strlen(*buf);
+	list_len = strlen(list[i]);
+	*buf = (char *)G_realloc((char *)*buf,
+				 (buf_len ? buf_len + sep_len : 0) +
+				 (flags & G_JOIN_ELEMENT_TYPE ? alias_len +
+				  1 : 0) + list_len +
+				 (flags & G_JOIN_ELEMENT_MAPSET ? mapset_len +
+				  1 : 0) + 1);
+	p = (char *)*buf + buf_len;
+
+	/* looks dirty but fast! */
+	if (buf_len) {
+	    if (flags & G_JOIN_ELEMENT_TYPE) {
+		if (flags & G_JOIN_ELEMENT_MAPSET)
+		    sprintf(p, "%s%s/%s@%s", separator, alias, list[i],
+			    mapset);
+		else
+		    sprintf(p, "%s%s/%s", separator, alias, list[i]);
+	    }
+	    else {
+		if (flags & G_JOIN_ELEMENT_MAPSET)
+		    sprintf(p, "%s%s@%s", separator, list[i], mapset);
+		else
+		    sprintf(p, "%s%s", separator, list[i]);
+	    }
+	}
+	else {
+	    if (flags & G_JOIN_ELEMENT_TYPE) {
+		if (flags & G_JOIN_ELEMENT_MAPSET)
+		    sprintf(p, "%s/%s@%s", alias, list[i], mapset);
+		else
+		    sprintf(p, "%s/%s", alias, list[i]);
+	    }
+	    else {
+		if (flags & G_JOIN_ELEMENT_MAPSET)
+		    sprintf(p, "%s@%s", list[i], mapset);
+		else
+		    sprintf(p, "%s", list[i]);
+	    }
+	}
+    }
+
+    for (i = 0; i < count; i++)
+	G_free((char *)list[i]);
+    if (list)
+	G_free(list);
+
+    return count;
+}

Added: grass-addons/general/g.xlist/ls.c
===================================================================
--- grass-addons/general/g.xlist/ls.c	                        (rev 0)
+++ grass-addons/general/g.xlist/ls.c	2008-06-29 11:44:57 UTC (rev 31881)
@@ -0,0 +1,133 @@
+
+/**
+   \file ls.c
+
+   \brief Functions to list the files in a directory.
+
+   \author Paul Kelly, Huidae Cho
+   
+   (C) 2007, 2008 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
+   for details.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <regex.h>
+
+#include <grass/gis.h>
+#include <grass/config.h>
+#include <grass/glocale.h>
+
+#ifdef HAVE_SYS_IOCTL_H
+#  include <sys/ioctl.h>
+#endif
+
+
+#define LS_FILTER_FLAGS REG_EXTENDED|REG_NOSUB
+static char *ls_filter = NULL;
+
+static int cmp_names(const void *aa, const void *bb)
+{
+    char *const *a = (char *const *)aa;
+    char *const *b = (char *const *)bb;
+
+    return strcmp(*a, *b);
+}
+
+/**
+ * \brief Sets a filter for G__ls using POSIX Extended Regular Expressions.
+ * 
+ * Defines the pattern that allows G__ls to filter out unwanted file names.
+ * Call this function before G__ls.
+ *
+ * \param pattern   POSIX Extended Regular Expressions
+ * 		    (if NULL, no filter will be used)
+ **/
+void G_set_ls_filter(const char *pattern)
+{
+    regex_t reg;
+
+    if (ls_filter)
+	G_free(ls_filter);
+    if (pattern) {
+	ls_filter = G_strdup(pattern);
+	if (regcomp(&reg, ls_filter, LS_FILTER_FLAGS) != 0)
+	    G_fatal_error(_("Unable to compile regular expression %s"),
+			  ls_filter);
+	regfree(&reg);
+    }
+    else
+	ls_filter = NULL;
+
+    return;
+}
+
+/**
+ * \brief Gets a filter string for G__ls.
+ * 
+ * Returns the filter pattern defined by G_set_ls_filter.
+ *
+ * \return          Filter pattern
+ **/
+const char *G_get_ls_filter(void)
+{
+    return ls_filter;
+}
+
+/**
+ * \brief Stores a sorted directory listing in an array
+ * 
+ * The filenames in the specified directory are stored in an array of
+ * strings, then sorted alphabetically. Each filename has space allocated
+ * using G_store(), which can be freed using G_free() if necessary. The
+ * same goes for the array itself.
+ * 
+ * 
+ * \param dir       Directory to list
+ * \param num_files Pointer to an integer in which the total number of
+ *                  files listed will be stored
+ * 
+ * \return          Pointer to array of strings containing the listing
+ **/
+
+const char **G__ls(const char *dir, int *num_files)
+{
+    struct dirent *dp;
+    DIR *dfd;
+    const char **dir_listing = NULL;
+    int n = 0;
+    regex_t reg;
+
+    if ((dfd = opendir(dir)) == NULL)
+	G_fatal_error(_("Unable to open directory %s"), dir);
+
+    if (ls_filter && regcomp(&reg, ls_filter, LS_FILTER_FLAGS) != 0)
+	G_fatal_error(_("Unable to compile regular expression %s"),
+		      ls_filter);
+
+    while ((dp = readdir(dfd)) != NULL) {
+	if (dp->d_name[0] != '.' &&	/* Don't list hidden files */
+	    (ls_filter == NULL || regexec(&reg, dp->d_name, 0, NULL, 0) == 0)) {
+	    dir_listing = (const char **)G_realloc(dir_listing,
+						   (1 + n) * sizeof(char *));
+	    dir_listing[n] = G_store(dp->d_name);
+	    n++;
+	}
+    }
+
+    if (ls_filter)
+	regfree(&reg);
+
+    /* Sort list of filenames alphabetically */
+    qsort(dir_listing, n, sizeof(char *), cmp_names);
+
+    *num_files = n;
+    return dir_listing;
+}

Added: grass-addons/general/g.xlist/main.c
===================================================================
--- grass-addons/general/g.xlist/main.c	                        (rev 0)
+++ grass-addons/general/g.xlist/main.c	2008-06-29 11:44:57 UTC (rev 31881)
@@ -0,0 +1,247 @@
+
+/****************************************************************************
+ *
+ * MODULE:       g.xlist
+ *
+ * AUTHOR(S):    Huidae Cho
+ * 		 Based on general/manage/cmd/list.c by Michael Shapiro.
+ *
+ * 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
+ *
+ *               This program is free software under the GNU General Public
+ *               License (>=v2). Read the file COPYING that comes with GRASS
+ *               for details.
+ *
+ *****************************************************************************/
+
+#define MAIN
+#include <stdlib.h>
+#include <string.h>
+#include <grass/spawn.h>
+#include "gisdefs.h"
+#include "global.h"
+
+static int parse(const char *);
+static int do_list(int, const char *, const char *, int, const char *, int);
+
+int main(int argc, char *argv[])
+{
+    struct GModule *module;
+    struct
+    {
+	struct Option *type;
+	struct Option *pattern;
+	struct Option *separator;
+	struct Option *mapset;
+    } opt;
+    struct
+    {
+	struct Flag *regex;
+	struct Flag *type;
+	struct Flag *mapset;
+	struct Flag *pretty;
+	struct Flag *full;
+    } flag;
+    int i, n, all, num_types, any, flags = 0;
+    char **types, *pattern = NULL, separator[2];
+
+    G_gisinit(argv[0]);
+
+    module = G_define_module();
+    module->keywords = _("general, map management");
+    module->description =
+	_("Lists available GRASS data base files "
+	  "of the user-specified data type to standard output.");
+
+    read_list(0);
+
+    opt.type = G_define_option();
+    opt.type->key = "type";
+    opt.type->key_desc = "datatype";
+    opt.type->type = TYPE_STRING;
+    opt.type->required = YES;
+    opt.type->multiple = YES;
+    opt.type->answer = "rast";
+    opt.type->description = "Data type";
+    for (i = 0, n = 0; n < nlist; n++)
+	i += strlen(list[n].alias) + 1;
+    opt.type->options = G_malloc(i + 4);
+
+    opt.type->options[0] = 0;
+    for (n = 0; n < nlist; n++) {
+	G_strcat(opt.type->options, list[n].alias);
+	G_strcat(opt.type->options, ",");
+    }
+    G_strcat(opt.type->options, "all");
+#define TYPES opt.type->answers
+
+    opt.pattern = G_define_option();
+    opt.pattern->key = "pattern";
+    opt.pattern->type = TYPE_STRING;
+    opt.pattern->required = NO;
+    opt.pattern->multiple = NO;
+    opt.pattern->answer = "*";
+    opt.pattern->description = _("Map name search pattern (default: all)");
+#define PATTERN opt.pattern->answer
+
+    opt.separator = G_define_option();
+    opt.separator->key = "separator";
+    opt.separator->type = TYPE_STRING;
+    opt.separator->required = NO;
+    opt.separator->multiple = NO;
+    opt.separator->answer = "newline";
+    opt.separator->description =
+	_("One-character output separator, newline, space, or tab");
+#define SEPARATOR opt.separator->answer
+
+    opt.mapset = G_define_option();
+    opt.mapset->key = "mapset";
+    opt.mapset->type = TYPE_STRING;
+    opt.mapset->required = NO;
+    opt.mapset->multiple = NO;
+    opt.mapset->description =
+	_("Mapset to list (default: current search path)");
+#define MAPSET opt.mapset->answer
+
+    flag.regex = G_define_flag();
+    flag.regex->key = 'r';
+    flag.regex->description =
+	_("Use extended regular expressions instead of wildcards");
+#define FREGEX flag.regex->answer
+
+    flag.type = G_define_flag();
+    flag.type->key = 't';
+    flag.type->description = _("Print data types");
+#define FTYPE flag.type->answer
+
+    flag.mapset = G_define_flag();
+    flag.mapset->key = 'm';
+    flag.mapset->description = _("Print mapset names");
+#define FMAPSET flag.mapset->answer
+
+    flag.pretty = G_define_flag();
+    flag.pretty->key = 'p';
+    flag.pretty->description = _("Pretty printing in human readable format");
+#define FPRETTY flag.pretty->answer
+
+    flag.full = G_define_flag();
+    flag.full->key = 'f';
+    flag.full->description = _("Verbose listing (also list map titles)");
+#define FFULL flag.full->answer
+
+    if (G_parser(argc, argv))
+	exit(EXIT_FAILURE);
+
+    if (!FREGEX) {
+	pattern = wc2regex(PATTERN);
+	G_free(PATTERN);
+	PATTERN = pattern;
+    }
+
+    G_set_ls_filter(PATTERN);
+#if 0
+    fprintf(stderr, "%s\n", G_get_ls_filter());
+#endif
+
+    if (strcmp(SEPARATOR, "newline") == 0)
+	separator[0] = '\n';
+    else if (strcmp(SEPARATOR, "space") == 0)
+	separator[0] = ' ';
+    else if (strcmp(SEPARATOR, "tab") == 0)
+	separator[0] = '\t';
+    else
+	separator[0] = SEPARATOR[0];
+    separator[1] = 0;
+
+    if (MAPSET == NULL)
+	MAPSET = "";
+
+    if (G_strcasecmp(MAPSET, ".") == 0)
+	MAPSET = G_mapset();
+
+    for (i = 0; TYPES[i]; i++) {
+	if (strcmp(TYPES[i], "all") == 0)
+	    break;
+    }
+    if (TYPES[i]) {
+	all = 1;
+	num_types = nlist;
+    }
+    else {
+	all = 0;
+	num_types = i;
+    }
+
+    if (FTYPE)
+	flags |= G_JOIN_ELEMENT_TYPE;
+    if (FMAPSET)
+	flags |= G_JOIN_ELEMENT_MAPSET;
+
+    for (i = 0; i < num_types; i++) {
+	n = all ? i : parse(TYPES[i]);
+
+	if (FFULL) {
+	    char lister[300];
+
+	    sprintf(lister, "%s/etc/lister/%s", G_gisbase(),
+		    list[n].element[0]);
+	    G_debug(3, "lister CMD: %s", lister);
+	    if (access(lister, 1) == 0)	/* execute permission? */
+		G_spawn(lister, lister, MAPSET, NULL);
+	    else
+		any = do_list(n, PATTERN, MAPSET, FPRETTY, separator, flags);
+	}
+	else
+	    any = do_list(n, PATTERN, MAPSET, FPRETTY, separator, flags);
+    }
+    if (!FPRETTY && any)
+	fprintf(stdout, "\n");
+
+    if (pattern)
+	G_free(pattern);
+
+    exit(EXIT_SUCCESS);
+}
+
+static int parse(const char *data_type)
+{
+    int n;
+
+    for (n = 0; n < nlist; n++) {
+	if (G_strcasecmp(list[n].alias, data_type) == 0)
+	    break;
+    }
+
+    return n;
+}
+
+static int do_list(int n, const char *pattern, const char *mapset,
+		   int pretty, const char *separator, int flags)
+{
+    static int any = 0;
+    const char *buf;
+    int len;
+
+    if (pretty) {
+	G_list_element(list[n].element[0], list[n].alias, mapset,
+		       (int (*)())0);
+	return 1;
+    }
+
+    buf =
+	G_join_element(list[n].element[0], list[n].alias, mapset, separator,
+		       flags, NULL);
+    len = strlen(buf);
+    if (any && len)
+	fprintf(stdout, "%s", separator);
+    if (len)
+	fprintf(stdout, "%s", buf);
+    G_free((char *)buf);
+
+    any += len > 0;
+
+    return any;
+}

Added: grass-addons/general/g.xlist/read_list.c
===================================================================
--- grass-addons/general/g.xlist/read_list.c	                        (rev 0)
+++ grass-addons/general/g.xlist/read_list.c	2008-06-29 11:44:57 UTC (rev 31881)
@@ -0,0 +1,148 @@
+/* Copied from general/manage */
+
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dirent.h>
+#include "global.h"
+
+/*******************************************************************
+read the element list file
+
+   format is:
+
+   # ... comments
+   main element:alias:description:menu text
+      sub element:description
+      sub element:description
+	  .
+	  .
+	  .
+******************************************************************/
+
+static int add_element(const char *, const char *);
+static int empty(const char *);
+static int format_error(const char *, int, const char *);
+
+int read_list(int check_if_empty)
+{
+    FILE *fd;
+    char element_list[600], buf[1024], elem[100], alias[100], desc[100],
+	text[100], *env;
+    int any, line;
+
+    nlist = 0;
+    list = 0;
+    any = 0;
+
+    if ((env = G__getenv("ELEMENT_LIST")))
+	G_strcpy(element_list, env);
+    else
+	sprintf(element_list, "%s/etc/element_list", G_gisbase());
+    fd = fopen(element_list, "r");
+
+    if (!fd)
+	G_fatal_error("can't open database element list <%s>", element_list);
+
+    line = 0;
+    while (G_getl(buf, sizeof(buf), fd)) {
+	line++;
+	if (*buf == '#')
+	    continue;
+	if (*buf == ' ' || *buf == '\t') {	/* support element */
+	    *desc = 0;
+	    if (sscanf(buf, "%[^:]:%[^\n]", elem, desc) < 1)
+		continue;
+	    if (*elem == '#')
+		continue;
+	    if (nlist == 0)
+		format_error(element_list, line, buf);
+
+	    G_strip(elem);
+	    G_strip(desc);
+	    add_element(elem, desc);
+	}
+	else {			/* main element */
+
+	    if (sscanf
+		(buf, "%[^:]:%[^:]:%[^:]:%[^\n]", elem, alias, desc,
+		 text) != 4)
+		format_error(element_list, line, buf);
+
+	    G_strip(elem);
+	    G_strip(alias);
+	    G_strip(desc);
+	    G_strip(text);
+
+	    list =
+		(struct list *)G_realloc(list, (nlist + 1) * sizeof(*list));
+	    list[nlist].mainelem = G_store(elem);
+	    list[nlist].alias = G_store(alias);
+	    list[nlist].maindesc = G_store(desc);
+	    list[nlist].text = G_store(text);
+	    list[nlist].nelem = 0;
+	    list[nlist].element = 0;
+	    list[nlist].desc = 0;
+	    list[nlist].status = 0;
+	    if (!check_if_empty || !empty(elem)) {
+		list[nlist].status = 1;
+		any = 1;
+	    }
+	    nlist++;
+	    add_element(elem, desc);
+	}
+    }
+
+    fclose(fd);
+
+    return any;
+}
+
+static int add_element(const char *elem, const char *desc)
+{
+    int n;
+    int nelem;
+
+    if (*desc == 0)
+	desc = elem;
+
+    n = nlist - 1;
+    nelem = list[n].nelem++;
+    list[n].element =
+	(char **)G_realloc(list[n].element, (nelem + 1) * sizeof(char *));
+    list[n].element[nelem] = G_store(elem);
+    list[n].desc =
+	(char **)G_realloc(list[n].desc, (nelem + 1) * sizeof(char *));
+    list[n].desc[nelem] = G_store(desc);
+
+    return 0;
+}
+
+static int empty(const char *elem)
+{
+    DIR *dirp;
+    struct dirent *dp;
+    char dir[1024];
+    int any;
+
+    G__file_name(dir, elem, "", G_mapset());
+
+    any = 0;
+    if ((dirp = opendir(dir)) != NULL) {
+	while (!any && (dp = readdir(dirp)) != NULL) {
+	    if (dp->d_name[0] != '.')
+		any = 1;
+	}
+	closedir(dirp);
+    }
+
+    return any == 0;
+}
+
+static int format_error(const char *element_list, int line, const char *buf)
+{
+    G_fatal_error(_("Format error: <%s>\nLine: %d\n%s"), element_list, line,
+		  buf);
+
+    return 1;
+}

Added: grass-addons/general/g.xlist/wc2regex.c
===================================================================
--- grass-addons/general/g.xlist/wc2regex.c	                        (rev 0)
+++ grass-addons/general/g.xlist/wc2regex.c	2008-06-29 11:44:57 UTC (rev 31881)
@@ -0,0 +1,46 @@
+#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;
+}

Added: grass-addons/general/g.xremove/Makefile
===================================================================
--- grass-addons/general/g.xremove/Makefile	                        (rev 0)
+++ grass-addons/general/g.xremove/Makefile	2008-06-29 11:44:57 UTC (rev 31881)
@@ -0,0 +1,10 @@
+MODULE_TOPDIR = ../../../grass
+
+PGM = g.xremove
+
+LIBES = $(GISLIB) $(VECTLIB) $(G3DLIB)
+DEPENDENCIES = $(GISDEP) $(VECTDEP) $(G3DDEP)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd

Added: grass-addons/general/g.xremove/check_reclass.c
===================================================================
--- grass-addons/general/g.xremove/check_reclass.c	                        (rev 0)
+++ grass-addons/general/g.xremove/check_reclass.c	2008-06-29 11:44:57 UTC (rev 31881)
@@ -0,0 +1,62 @@
+#include <string.h>
+#include "global.h"
+
+int check_reclass(const char *name, const char *mapset, int force)
+{
+    char rname[GNAME_MAX], rmapset[GMAPSET_MAX];
+    char **rmaps;
+    int nrmaps;
+
+    if (G_is_reclassed_to(name, mapset, &nrmaps, &rmaps) > 0) {
+	for (; *rmaps; rmaps++) {
+	    /* force remove */
+	    if (force)
+		G_warning(_("[%s@%s] is a base map for [%s]. Remove forced."),
+			  name, mapset, *rmaps);
+	    else
+		G_warning(_
+			  ("[%s@%s] is a base map. Remove reclassed map first: %s"),
+			  name, mapset, *rmaps);
+	}
+
+	if (!force)
+	    return 1;
+    }
+
+    if (G_is_reclass(name, mapset, rname, rmapset) > 0 &&
+	G_is_reclassed_to(rname, rmapset, &nrmaps, &rmaps) > 0) {
+	char path[GPATH_MAX];
+	char *p = strchr(rname, '@');
+	char *qname = G_fully_qualified_name(name, mapset);
+
+	if (p)
+	    *p = '\0';
+
+	G__file_name_misc(path, "cell_misc", "reclassed_to", rname, rmapset);
+
+	if (nrmaps == 1 && !G_strcasecmp(rmaps[0], qname)) {
+
+	    if (remove(path) < 0)
+		G_warning(_
+			  ("Removing information about reclassed map from [%s@%s] failed"),
+			  rname, rmapset);
+	}
+	else {
+	    FILE *fp = fopen(path, "w");
+
+	    if (fp) {
+		for (; *rmaps; rmaps++)
+		    if (G_strcasecmp(*rmaps, qname))
+			fprintf(fp, "%s\n", *rmaps);
+		fclose(fp);
+	    }
+	    else
+		G_warning(_
+			  ("Removing information about reclassed map from [%s@%s] failed"),
+			  rname, rmapset);
+
+	}
+    }
+
+    return 0;
+}

Added: grass-addons/general/g.xremove/description.html
===================================================================
--- grass-addons/general/g.xremove/description.html	                        (rev 0)
+++ grass-addons/general/g.xremove/description.html	2008-06-29 11:44:57 UTC (rev 31881)
@@ -0,0 +1,26 @@
+<h2>DESCRIPTION</h2>
+
+<em>g.xremove</em> removes data files matching a pattern given by wildcards or POSIX Extended Regular Expressions.
+If the <b>-f</b> force flag is not given then nothing is removed, instead
+the list of selected file names is printed to <tt>stdout</tt>
+as a preview of the files to be deleted.
+
+<h2>EXAMPLE</h2>
+
+Delete all raster maps starting with "<tt>tmp_</tt>" in the current mapset:
+<div class="code"><pre>
+  g.xremove -f "tmp_*"
+</pre></div>
+
+<h2>SEE ALSO</h2>
+
+<em><a HREF="g.remove.html">g.remove</a></em>
+<p>
+<a href="http://en.wikipedia.org/wiki/Regular_expression">Regular expression</a> (from Wikipedia, the free encyclopedia)
+
+<h2>AUTHOR</h2>
+
+Huidae Cho<br>
+grass4u at gmail.com
+
+<p><i>Last changed: $Date: 2008-06-28 03:23:07 -0500 (Sat, 28 Jun 2008) $</i>

Added: grass-addons/general/g.xremove/do_remove.c
===================================================================
--- grass-addons/general/g.xremove/do_remove.c	                        (rev 0)
+++ grass-addons/general/g.xremove/do_remove.c	2008-06-29 11:44:57 UTC (rev 31881)
@@ -0,0 +1,106 @@
+#include <string.h>
+#include <grass/Vect.h>
+#include <grass/G3d.h>
+#include "global.h"
+
+/* 
+ *  returns 0 - success
+ *          1 - error
+ */
+int do_remove(int n, char *old)
+{
+    int i, ret;
+
+    /* int len; */
+    char *mapset;
+    int result = 0;
+    int removed = 0;
+    char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
+
+    G_message(_("Removing %s <%s>"), list[n].maindesc, old);
+
+    /* len = get_description_len(n); */
+
+    hold_signals(1);
+
+    if (G__name_is_fully_qualified(old, xname, xmapset)) {
+	if (strcmp(xmapset, G_mapset()) != 0)
+	    G_fatal_error("%s is not in the current mapset (%s)", old,
+			  G_mapset());
+	old = xname;
+    }
+
+    if (G_strcasecmp(list[n].alias, "vect") == 0) {
+	if ((mapset = G_find_vector2(old, "")) == NULL) {
+	    G_warning(_("Vector map <%s> not found"), old);
+	}
+	else {
+	    ret = Vect_delete(old);
+	    if (ret != -1) {
+		removed = 1;
+	    }
+	    else {
+		G_warning(_("couldn't be removed"));
+		result = 1;
+	    }
+	}
+    }
+    else {
+	if (G_strcasecmp(list[n].alias, "rast") == 0) {
+	    if ((mapset = G_find_cell2(old, "")) == NULL)
+		G_warning(_("Raster map <%s> not found"), old);
+	}
+
+	if (G_strcasecmp(list[n].alias, "rast3d") == 0) {
+	    if ((mapset = G_find_grid3(old, "")) == NULL)
+		G_warning(_("3D raster map <%s> not found"), old);
+	}
+
+	for (i = 0; i < list[n].nelem; i++) {
+
+	    switch (G_remove(list[n].element[i], old)) {
+	    case -1:
+		G_warning(_("%s: couldn't be removed"), list[n].desc[i]);
+		result = 1;
+		break;
+	    case 0:
+		if (G_verbose() == G_verbose_max())
+		    G_message(_("%s: missing"), list[n].desc[i]);
+		break;
+	    case 1:
+		if (G_verbose() == G_verbose_max())
+		    G_message(_("%s: removed"), list[n].desc[i]);
+		removed = 1;
+		break;
+	    }
+	}
+    }
+
+    if (G_strcasecmp(list[n].element[0], "cell") == 0) {
+	char colr2[50];
+
+	sprintf(colr2, "colr2/%s", G_mapset());
+	switch (G_remove(colr2, old)) {
+	case -1:
+	    G_warning("%s: %s", colr2, _("couldn't be removed"));
+	    result = 1;
+	    break;
+	case 0:
+	    if (G_verbose() == G_verbose_max())
+		G_message(_("%s: missing"), colr2);
+	    break;
+	case 1:
+	    if (G_verbose() == G_verbose_max())
+		G_message(_("%s: removed"), colr2);
+	    removed = 1;
+	    break;
+	}
+    }
+
+    hold_signals(0);
+
+    if (!removed)
+	G_warning(_("<%s> nothing removed"), old);
+
+    return result;
+}

Added: grass-addons/general/g.xremove/gisdefs.h
===================================================================
--- grass-addons/general/g.xremove/gisdefs.h	                        (rev 0)
+++ grass-addons/general/g.xremove/gisdefs.h	2008-06-29 11:44:57 UTC (rev 31881)
@@ -0,0 +1,16 @@
+#ifndef GISDEFS_H
+#define GISDEFS_H
+
+#define G_JOIN_ELEMENT_TYPE 0x1
+#define G_JOIN_ELEMENT_MAPSET 0x2
+
+/* join.c */
+const char *G_join_element(const char *, const char *, const char *,
+			   const char *, int, int *);
+
+/* ls.c */
+void G_set_ls_filter(const char *);
+const char *G_get_ls_filter(void);
+const char **G__ls(const char *, int *);
+
+#endif

Added: grass-addons/general/g.xremove/global.h
===================================================================
--- grass-addons/general/g.xremove/global.h	                        (rev 0)
+++ grass-addons/general/g.xremove/global.h	2008-06-29 11:44:57 UTC (rev 31881)
@@ -0,0 +1,38 @@
+#include <grass/gis.h>
+#include <grass/glocale.h>
+
+struct list
+{
+    char **element;		/* list of related elements */
+    char *alias;		/* element alias */
+    char **desc;		/* description of elements */
+    char *text;			/* menu text */
+    int nelem;			/* number of elements */
+    char status;
+    char *mainelem;		/* main element */
+    char *maindesc;		/* main element description */
+};
+
+/* read_list.c */
+int read_list(int);
+
+/* wc2regex.c */
+char *wc2regex(const char *);
+
+/* check_reclass.c */
+int check_reclass(const char *, const char *, int);
+
+/* sighold.c */
+int hold_signals(int);
+
+/* do_remove.c */
+int do_remove(int, char *);
+
+#ifdef MAIN
+#	define GLOBAL
+#else
+#	define GLOBAL extern
+#endif
+
+GLOBAL int nlist;
+GLOBAL struct list *list;

Added: grass-addons/general/g.xremove/join.c
===================================================================
--- grass-addons/general/g.xremove/join.c	                        (rev 0)
+++ grass-addons/general/g.xremove/join.c	2008-06-29 11:44:57 UTC (rev 31881)
@@ -0,0 +1,158 @@
+
+/**
+   \file join.c
+
+   \brief Return a string that contains elements
+
+   \author Huidae Cho
+
+   (C) 2008 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
+   for details.
+*/
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+#include <grass/gis.h>
+#include <grass/glocale.h>
+
+#include "gisdefs.h"
+
+static int join_element(const char *, const char *, const char *,
+			const char *, int, const char **);
+
+/**
+   \brief General purpose join function.
+
+   Will collect file names from all mapsets
+   in the mapset list for a specified database element
+   and join them into a string.
+
+   Note: Use G_(set|get)_ls_filter functions to filter out unwanted file names.
+
+   \param element    Database element (eg, "cell", "cellhd", etc)
+   \param alias      Alias for element (if NULL, element is used)
+   \param mapset     Mapset to be listed "" to list all mapsets in mapset search list 
+   "." will list current mapset
+   \param separator  Map name separator
+   \param flags      G_JOIN_ELEMENT_TYPE   Include alias
+                     G_JOIN_ELEMENT_MAPSET Include mapset name
+   \param count      Return the number of elements (if NULL, ignored)
+
+   \return String pointer
+*/
+const char *G_join_element(const char *element,
+			   const char *alias,
+			   const char *mapset,
+			   const char *separator, int flags, int *count)
+{
+    int c, n;
+    const char *buf;
+
+    c = 0;
+    if (alias == 0 || *alias == 0)
+	alias = element;
+
+    /*
+     * if no specific mapset is requested, list the mapsets
+     * from the mapset search list
+     * otherwise just list the specified mapset
+     */
+    buf = G_strdup("");
+    if (mapset == 0 || *mapset == 0)
+	for (n = 0; (mapset = G__mapset_name(n)); n++)
+	    c += join_element(element, alias, mapset, separator, flags, &buf);
+    else
+	c = join_element(element, alias, mapset, separator, flags, &buf);
+
+    if (count)
+	*count = c;
+    return buf;
+}
+
+static int join_element(const char *element,
+			const char *alias,
+			const char *mapset,
+			const char *separator, int flags, const char **buf)
+{
+    char path[GPATH_MAX], *p;
+    int i, count = 0;
+    int buf_len, alias_len, list_len, sep_len = strlen(separator), mapset_len;
+    const char **list;
+
+    /*
+     * convert . to current mapset
+     */
+    if (strcmp(mapset, ".") == 0)
+	mapset = G_mapset();
+
+    mapset_len = strlen(mapset);
+
+    /*
+     * get the full name of the GIS directory within the mapset
+     * and list its contents (if it exists)
+     */
+    G__file_name(path, element, "", mapset);
+    if (access(path, 0) != 0)
+	return count;
+
+    list = G__ls(path, &count);
+
+    alias_len = strlen(alias);
+    for (i = 0; i < count; i++) {
+	buf_len = strlen(*buf);
+	list_len = strlen(list[i]);
+	*buf = (char *)G_realloc((char *)*buf,
+				 (buf_len ? buf_len + sep_len : 0) +
+				 (flags & G_JOIN_ELEMENT_TYPE ? alias_len +
+				  1 : 0) + list_len +
+				 (flags & G_JOIN_ELEMENT_MAPSET ? mapset_len +
+				  1 : 0) + 1);
+	p = (char *)*buf + buf_len;
+
+	/* looks dirty but fast! */
+	if (buf_len) {
+	    if (flags & G_JOIN_ELEMENT_TYPE) {
+		if (flags & G_JOIN_ELEMENT_MAPSET)
+		    sprintf(p, "%s%s/%s@%s", separator, alias, list[i],
+			    mapset);
+		else
+		    sprintf(p, "%s%s/%s", separator, alias, list[i]);
+	    }
+	    else {
+		if (flags & G_JOIN_ELEMENT_MAPSET)
+		    sprintf(p, "%s%s@%s", separator, list[i], mapset);
+		else
+		    sprintf(p, "%s%s", separator, list[i]);
+	    }
+	}
+	else {
+	    if (flags & G_JOIN_ELEMENT_TYPE) {
+		if (flags & G_JOIN_ELEMENT_MAPSET)
+		    sprintf(p, "%s/%s@%s", alias, list[i], mapset);
+		else
+		    sprintf(p, "%s/%s", alias, list[i]);
+	    }
+	    else {
+		if (flags & G_JOIN_ELEMENT_MAPSET)
+		    sprintf(p, "%s@%s", list[i], mapset);
+		else
+		    sprintf(p, "%s", list[i]);
+	    }
+	}
+    }
+
+    for (i = 0; i < count; i++)
+	G_free((char *)list[i]);
+    if (list)
+	G_free(list);
+
+    return count;
+}

Added: grass-addons/general/g.xremove/ls.c
===================================================================
--- grass-addons/general/g.xremove/ls.c	                        (rev 0)
+++ grass-addons/general/g.xremove/ls.c	2008-06-29 11:44:57 UTC (rev 31881)
@@ -0,0 +1,133 @@
+
+/**
+   \file ls.c
+
+   \brief Functions to list the files in a directory.
+
+   \author Paul Kelly, Huidae Cho
+   
+   (C) 2007, 2008 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
+   for details.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <regex.h>
+
+#include <grass/gis.h>
+#include <grass/config.h>
+#include <grass/glocale.h>
+
+#ifdef HAVE_SYS_IOCTL_H
+#  include <sys/ioctl.h>
+#endif
+
+
+#define LS_FILTER_FLAGS REG_EXTENDED|REG_NOSUB
+static char *ls_filter = NULL;
+
+static int cmp_names(const void *aa, const void *bb)
+{
+    char *const *a = (char *const *)aa;
+    char *const *b = (char *const *)bb;
+
+    return strcmp(*a, *b);
+}
+
+/**
+ * \brief Sets a filter for G__ls using POSIX Extended Regular Expressions.
+ * 
+ * Defines the pattern that allows G__ls to filter out unwanted file names.
+ * Call this function before G__ls.
+ *
+ * \param pattern   POSIX Extended Regular Expressions
+ * 		    (if NULL, no filter will be used)
+ **/
+void G_set_ls_filter(const char *pattern)
+{
+    regex_t reg;
+
+    if (ls_filter)
+	G_free(ls_filter);
+    if (pattern) {
+	ls_filter = G_strdup(pattern);
+	if (regcomp(&reg, ls_filter, LS_FILTER_FLAGS) != 0)
+	    G_fatal_error(_("Unable to compile regular expression %s"),
+			  ls_filter);
+	regfree(&reg);
+    }
+    else
+	ls_filter = NULL;
+
+    return;
+}
+
+/**
+ * \brief Gets a filter string for G__ls.
+ * 
+ * Returns the filter pattern defined by G_set_ls_filter.
+ *
+ * \return          Filter pattern
+ **/
+const char *G_get_ls_filter(void)
+{
+    return ls_filter;
+}
+
+/**
+ * \brief Stores a sorted directory listing in an array
+ * 
+ * The filenames in the specified directory are stored in an array of
+ * strings, then sorted alphabetically. Each filename has space allocated
+ * using G_store(), which can be freed using G_free() if necessary. The
+ * same goes for the array itself.
+ * 
+ * 
+ * \param dir       Directory to list
+ * \param num_files Pointer to an integer in which the total number of
+ *                  files listed will be stored
+ * 
+ * \return          Pointer to array of strings containing the listing
+ **/
+
+const char **G__ls(const char *dir, int *num_files)
+{
+    struct dirent *dp;
+    DIR *dfd;
+    const char **dir_listing = NULL;
+    int n = 0;
+    regex_t reg;
+
+    if ((dfd = opendir(dir)) == NULL)
+	G_fatal_error(_("Unable to open directory %s"), dir);
+
+    if (ls_filter && regcomp(&reg, ls_filter, LS_FILTER_FLAGS) != 0)
+	G_fatal_error(_("Unable to compile regular expression %s"),
+		      ls_filter);
+
+    while ((dp = readdir(dfd)) != NULL) {
+	if (dp->d_name[0] != '.' &&	/* Don't list hidden files */
+	    (ls_filter == NULL || regexec(&reg, dp->d_name, 0, NULL, 0) == 0)) {
+	    dir_listing = (const char **)G_realloc(dir_listing,
+						   (1 + n) * sizeof(char *));
+	    dir_listing[n] = G_store(dp->d_name);
+	    n++;
+	}
+    }
+
+    if (ls_filter)
+	regfree(&reg);
+
+    /* Sort list of filenames alphabetically */
+    qsort(dir_listing, n, sizeof(char *), cmp_names);
+
+    *num_files = n;
+    return dir_listing;
+}

Added: grass-addons/general/g.xremove/main.c
===================================================================
--- grass-addons/general/g.xremove/main.c	                        (rev 0)
+++ grass-addons/general/g.xremove/main.c	2008-06-29 11:44:57 UTC (rev 31881)
@@ -0,0 +1,128 @@
+
+/****************************************************************************
+ *
+ * MODULE:       g.xremove
+ *
+ * AUTHOR(S):    Huidae Cho <grass4u gmail.com>
+ *
+ * 		 Based on general/manage/cmd/remove.c by
+ *               CERL (original contributor)
+ *               Radim Blazek <radim.blazek gmail.com>, 
+ *               Cedric Shock <cedricgrass shockfamily.net>, 
+ *               Huidae Cho <grass4u gmail.com>,
+ *               Glynn Clements <glynn gclements.plus.com>, 
+ *               Jachym Cepicky <jachym les-ejk.cz>, 
+ *               Markus Neteler <neteler itc.it>, 
+ *               Martin Landa <landa.martin gmail.com>
+ *
+ * PURPOSE:      lets users remove GRASS database files
+ *
+ * COPYRIGHT:    (C) 1999-2008 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
+ *               for details.
+ *
+ *****************************************************************************/
+
+#define MAIN
+#include <stdlib.h>
+#include "global.h"
+
+int main(int argc, char *argv[])
+{
+    struct GModule *module;
+    struct Option **opt, *o;
+    struct
+    {
+	struct Flag *regex;
+	struct Flag *force;
+	struct Flag *basemap;
+    } flag;
+    char *name, *mapset, *location_path, path[GPATH_MAX];
+    const char **files;
+    int num_files, rast, result = EXIT_SUCCESS;
+    int i, j, n;
+
+    G_gisinit(argv[0]);
+
+    module = G_define_module();
+    module->keywords = _("general, map management");
+    module->description =
+	_("Removes data base element files from "
+	  "the user's current mapset.");
+
+    flag.regex = G_define_flag();
+    flag.regex->key = 'r';
+    flag.regex->description =
+	_("Use extended regular expressions instead of wildcards");
+#define FREGEX flag.regex->answer
+
+    flag.force = G_define_flag();
+    flag.force->key = 'f';
+    flag.force->description =
+	_("Force removal (required for actual deletion of files)");
+#define FFORCE flag.force->answer
+
+    flag.basemap = G_define_flag();
+    flag.basemap->key = 'b';
+    flag.basemap->description = _("Remove base maps");
+#define FBASEMAP flag.basemap->answer
+
+    read_list(0);
+
+    opt = (struct Option **)G_calloc(nlist, sizeof(struct Option *));
+
+    for (n = 0; n < nlist; n++) {
+	o = opt[n] = G_define_option();
+	o->key = list[n].alias;
+	o->type = TYPE_STRING;
+	o->required = NO;
+	o->multiple = YES;
+	o->gisprompt = G_malloc(64);
+	sprintf(o->gisprompt, "old,%s,%s", list[n].mainelem,
+		list[n].maindesc);
+	o->description = G_malloc(64);
+	sprintf(o->description, _("%s file(s) to be removed"), list[n].alias);
+    }
+
+    if (G_parser(argc, argv))
+	exit(EXIT_FAILURE);
+
+    location_path = G_location_path();
+    mapset = G_mapset();
+
+    for (n = 0; n < nlist; n++) {
+	if (opt[n]->answers) {
+	    G__file_name(path, list[n].element[0], "", mapset);
+	    if (access(path, 0) != 0)
+		continue;
+	    rast = !G_strcasecmp(list[n].alias, "rast");
+	    for (i = 0; (name = opt[n]->answers[i]); i++) {
+		if (!FREGEX)
+		    name = wc2regex(name);
+		G_set_ls_filter(name);
+
+		files = G__ls(path, &num_files);
+
+		if (!FREGEX)
+		    G_free(name);
+
+		for (j = 0; j < num_files; j++) {
+		    if (!FFORCE) {
+			fprintf(stdout, "%s/%s@%s\n", list[n].alias, files[j],
+				mapset);
+			continue;
+		    }
+		    if (rast && check_reclass(files[j], mapset, FBASEMAP))
+			continue;
+
+		    if (do_remove(n, (char *)files[j]) == 1)
+			result = EXIT_FAILURE;
+		}
+	    }
+	}
+    }
+
+    exit(result);
+}

Added: grass-addons/general/g.xremove/read_list.c
===================================================================
--- grass-addons/general/g.xremove/read_list.c	                        (rev 0)
+++ grass-addons/general/g.xremove/read_list.c	2008-06-29 11:44:57 UTC (rev 31881)
@@ -0,0 +1,148 @@
+/* Copied from general/manage */
+
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dirent.h>
+#include "global.h"
+
+/*******************************************************************
+read the element list file
+
+   format is:
+
+   # ... comments
+   main element:alias:description:menu text
+      sub element:description
+      sub element:description
+	  .
+	  .
+	  .
+******************************************************************/
+
+static int add_element(const char *, const char *);
+static int empty(const char *);
+static int format_error(const char *, int, const char *);
+
+int read_list(int check_if_empty)
+{
+    FILE *fd;
+    char element_list[600], buf[1024], elem[100], alias[100], desc[100],
+	text[100], *env;
+    int any, line;
+
+    nlist = 0;
+    list = 0;
+    any = 0;
+
+    if ((env = G__getenv("ELEMENT_LIST")))
+	G_strcpy(element_list, env);
+    else
+	sprintf(element_list, "%s/etc/element_list", G_gisbase());
+    fd = fopen(element_list, "r");
+
+    if (!fd)
+	G_fatal_error("can't open database element list <%s>", element_list);
+
+    line = 0;
+    while (G_getl(buf, sizeof(buf), fd)) {
+	line++;
+	if (*buf == '#')
+	    continue;
+	if (*buf == ' ' || *buf == '\t') {	/* support element */
+	    *desc = 0;
+	    if (sscanf(buf, "%[^:]:%[^\n]", elem, desc) < 1)
+		continue;
+	    if (*elem == '#')
+		continue;
+	    if (nlist == 0)
+		format_error(element_list, line, buf);
+
+	    G_strip(elem);
+	    G_strip(desc);
+	    add_element(elem, desc);
+	}
+	else {			/* main element */
+
+	    if (sscanf
+		(buf, "%[^:]:%[^:]:%[^:]:%[^\n]", elem, alias, desc,
+		 text) != 4)
+		format_error(element_list, line, buf);
+
+	    G_strip(elem);
+	    G_strip(alias);
+	    G_strip(desc);
+	    G_strip(text);
+
+	    list =
+		(struct list *)G_realloc(list, (nlist + 1) * sizeof(*list));
+	    list[nlist].mainelem = G_store(elem);
+	    list[nlist].alias = G_store(alias);
+	    list[nlist].maindesc = G_store(desc);
+	    list[nlist].text = G_store(text);
+	    list[nlist].nelem = 0;
+	    list[nlist].element = 0;
+	    list[nlist].desc = 0;
+	    list[nlist].status = 0;
+	    if (!check_if_empty || !empty(elem)) {
+		list[nlist].status = 1;
+		any = 1;
+	    }
+	    nlist++;
+	    add_element(elem, desc);
+	}
+    }
+
+    fclose(fd);
+
+    return any;
+}
+
+static int add_element(const char *elem, const char *desc)
+{
+    int n;
+    int nelem;
+
+    if (*desc == 0)
+	desc = elem;
+
+    n = nlist - 1;
+    nelem = list[n].nelem++;
+    list[n].element =
+	(char **)G_realloc(list[n].element, (nelem + 1) * sizeof(char *));
+    list[n].element[nelem] = G_store(elem);
+    list[n].desc =
+	(char **)G_realloc(list[n].desc, (nelem + 1) * sizeof(char *));
+    list[n].desc[nelem] = G_store(desc);
+
+    return 0;
+}
+
+static int empty(const char *elem)
+{
+    DIR *dirp;
+    struct dirent *dp;
+    char dir[1024];
+    int any;
+
+    G__file_name(dir, elem, "", G_mapset());
+
+    any = 0;
+    if ((dirp = opendir(dir)) != NULL) {
+	while (!any && (dp = readdir(dirp)) != NULL) {
+	    if (dp->d_name[0] != '.')
+		any = 1;
+	}
+	closedir(dirp);
+    }
+
+    return any == 0;
+}
+
+static int format_error(const char *element_list, int line, const char *buf)
+{
+    G_fatal_error(_("Format error: <%s>\nLine: %d\n%s"), element_list, line,
+		  buf);
+
+    return 1;
+}

Added: grass-addons/general/g.xremove/sighold.c
===================================================================
--- grass-addons/general/g.xremove/sighold.c	                        (rev 0)
+++ grass-addons/general/g.xremove/sighold.c	2008-06-29 11:44:57 UTC (rev 31881)
@@ -0,0 +1,21 @@
+#include <signal.h>
+
+void (*sig) ();
+
+int hold_signals(int hold)
+{
+
+    sig = hold ? SIG_IGN : SIG_DFL;
+
+    signal(SIGINT, sig);
+
+#ifndef __MINGW32__
+    signal(SIGQUIT, sig);
+#endif
+
+#ifdef SIGTSTP
+    signal(SIGTSTP, sig);
+#endif
+
+    return 0;
+}

Added: grass-addons/general/g.xremove/wc2regex.c
===================================================================
--- grass-addons/general/g.xremove/wc2regex.c	                        (rev 0)
+++ grass-addons/general/g.xremove/wc2regex.c	2008-06-29 11:44:57 UTC (rev 31881)
@@ -0,0 +1,46 @@
+#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;
+}



More information about the grass-commit mailing list