[GRASS-SVN] r63744 - grass/trunk/lib/gis

svn_grass at osgeo.org svn_grass at osgeo.org
Thu Dec 25 03:51:51 PST 2014


Author: glynn
Date: 2014-12-25 03:51:51 -0800 (Thu, 25 Dec 2014)
New Revision: 63744

Modified:
   grass/trunk/lib/gis/parser.c
Log:
Change handling of ambiguous matches (issue #2409)


Modified: grass/trunk/lib/gis/parser.c
===================================================================
--- grass/trunk/lib/gis/parser.c	2014-12-25 11:34:18 UTC (rev 63743)
+++ grass/trunk/lib/gis/parser.c	2014-12-25 11:51:51 UTC (rev 63744)
@@ -94,6 +94,8 @@
 
 #define KEYLENGTH 64
 
+#define MAX_MATCHES 50
+
 /* initialize the global struct */
 struct state state;
 struct state *st = &state;
@@ -941,11 +943,11 @@
 {
     struct Option *at_opt = NULL;
     struct Option *opt = NULL;
-    int found;
-    int prefix;
     size_t key_len;
     char the_key[KEYLENGTH];
     char *ptr, *err;
+    struct Option *matches[MAX_MATCHES];
+    int found = 0;
 
     err = NULL;
 
@@ -955,37 +957,58 @@
     string++;
 
     /* Find option with best keyword match */
-    found = 0;
-    prefix = 0;
     key_len = strlen(the_key);
     for (at_opt = &st->first_option; at_opt; at_opt = at_opt->next_opt) {
 	if (!at_opt->key)
 	    continue;
 
         if (strcmp(the_key, at_opt->key) == 0) {
-	    opt = at_opt;
+	    matches[0] = at_opt;
 	    found = 1;
 	    break; 
 	}
 
-        if (strncmp(the_key, at_opt->key, key_len) == 0) {
-	    opt = at_opt;
-	    found++;
-	    prefix++;
+        if (strncmp(the_key, at_opt->key, key_len) == 0 ||
+	    match_option(the_key, at_opt->key)) {
+	    if (found >= MAX_MATCHES)
+		G_fatal_error("too many matches (limit %d)", MAX_MATCHES);
+	    matches[found++] = at_opt;
 	}
-	else if (match_option(the_key, at_opt->key)) {
-	    if (!found)
-		opt = at_opt;
-	    found++;
-	}
     }
 
-    if (found > 1 && prefix > 1) {
-	G_asprintf(&err, _("%s: Sorry, <%s=> is ambiguous"), G_program_name(), the_key);
-	append_error(err);
-	return;
+    if (found > 1) {
+	int shortest = 0;
+	int length = strlen(matches[0]->key);
+	int prefix = 1;
+	int i;
+	for (i = 1; i < found; i++) {
+	    int len = strlen(matches[i]->key);
+	    if (len < length) {
+		length = len;
+		shortest = i;
+	    }
+	}
+	for (i = 0; prefix && i < found; i++)
+	    if (strncmp(matches[i]->key, matches[shortest]->key, length) != 0)
+		prefix = 0;
+	if (prefix) {
+	    matches[0] = matches[shortest];
+	    found = 1;
+	}
+	else {
+	    G_asprintf(&err, _("%s: Sorry, <%s=> is ambiguous"), G_program_name(), the_key);
+	    append_error(err);
+	    for (i = 0; i < found; i++) {
+		G_asprintf(&err, _("Option <%s=> matches"), matches[i]->key);
+		append_error(err);
+	    }
+	    return;
+	}
     }
 
+    if (found)
+	opt = matches[0];
+
     /* First, check if key has been renamed in GRASS 7 */
     if (found == 0) {
         const char *renamed_key = NULL;
@@ -1214,7 +1237,7 @@
 {
     int len = strlen(ans);
     int found = 0;
-    int prefix = 0;
+    int matches[MAX_MATCHES];
     int i;
 
     if (!opts)
@@ -1223,26 +1246,41 @@
     for (i = 0; opts[i]; i++) {
 	if (strcmp(ans, opts[i]) == 0)
 	    return 0;
-	if (strncmp(ans, opts[i], len) == 0) {
-	    *result = i;
-	    found++;
-	    prefix++;
+	if (strncmp(ans, opts[i], len) == 0 || match_option(ans, opts[i])) {
+	    if (found >= MAX_MATCHES)
+		G_fatal_error("too many matches (limit %d)", MAX_MATCHES);
+	    matches[found++] = i;
 	}
-	else if (match_option(ans, opts[i])) {
-	    if (!found)
-		*result = i;
-	    found++;
+    }
+
+    if (found > 1) {
+	int shortest = 0;
+	int length = strlen(opts[matches[0]]);
+	int prefix = 1;
+	int i;
+	for (i = 1; i < found; i++) {
+	    int len = strlen(opts[matches[i]]);
+	    if (len < length) {
+		length = len;
+		shortest = i;
+	    }
 	}
+	for (i = 0; prefix && i < found; i++)
+	    if (strncmp(opts[matches[i]], opts[matches[shortest]], length) != 0)
+		prefix = 0;
+	if (prefix) {
+	    matches[0] = matches[shortest];
+	    found = 1;
+	}
     }
 
+    if (found == 1)
+	*result = matches[0];
+
     switch (found) {
     case 0: return OUT_OF_RANGE;
     case 1: return REPLACED;
-    default:
-	switch (prefix) {
-	case 1: return REPLACED;
-	default: return AMBIGUOUS;
-	}
+    default: return AMBIGUOUS;
     }
 }
 



More information about the grass-commit mailing list