aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2011-05-15 00:03:43 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2011-05-15 14:00:57 +0300
commitfd64fa62bc68d8c2e0d693033e874fcc1f023544 (patch)
tree4e9f680539dc9ceb32ea6797c3f917586b2f757f /src
parentf83e3229ea5c917dfb1bd1a59b1768fdcb882f9a (diff)
downloadgrecs-fd64fa62bc68d8c2e0d693033e874fcc1f023544.tar.gz
grecs-fd64fa62bc68d8c2e0d693033e874fcc1f023544.tar.bz2
Improve wildcard matching.
* src/lookup.c (grecs_value_match): New function. (grecs_match_buf_free): Ignore NULL argument. (grecs_match): Implement single-occurrence wildcard (%). Match values using fnmatch globbing patterns. (grecs_match_first): Compress multiple contiguous *
Diffstat (limited to 'src')
-rw-r--r--src/lookup.c102
1 files changed, 98 insertions, 4 deletions
diff --git a/src/lookup.c b/src/lookup.c
index d30d348..a557845 100644
--- a/src/lookup.c
+++ b/src/lookup.c
@@ -22,6 +22,7 @@
22#include <ctype.h> 22#include <ctype.h>
23#include "grecs.h" 23#include "grecs.h"
24#include "wordsplit.h" 24#include "wordsplit.h"
25#include <fnmatch.h>
25 26
26static int 27static int
27_grecs_list_eq(struct grecs_value *a, struct grecs_value *b) 28_grecs_list_eq(struct grecs_value *a, struct grecs_value *b)
@@ -79,6 +80,73 @@ grecs_value_eq(struct grecs_value *a, struct grecs_value *b)
79 } 80 }
80 return 0; 81 return 0;
81} 82}
83
84static int
85_grecs_list_match(struct grecs_value *pat, struct grecs_value *b, int flags)
86{
87 struct grecs_list_entry *aent, *bent;
88 if (grecs_list_size(pat->v.list) != grecs_list_size(b->v.list))
89 return 0;
90
91 for (aent = pat->v.list->head, bent = b->v.list->head;;
92 aent = aent->next, bent = bent->next) {
93 if (!aent)
94 return bent == NULL;
95 if (!bent)
96 return 0;
97 if (!grecs_value_match(aent->data, bent->data, flags))
98 return 0;
99 }
100 /*notreached*/
101 return 1;
102}
103
104static int
105_grecs_array_match(struct grecs_value *pat, struct grecs_value *b, int flags)
106{
107 size_t i;
108
109 if (pat->v.arg.c > b->v.arg.c)
110 return 0;
111
112 for (i = 0; i < pat->v.arg.c; i++)
113 if (!grecs_value_match(pat->v.arg.v[i], b->v.arg.v[i], flags))
114 return 0;
115 return 1;
116}
117
118int
119grecs_value_match(struct grecs_value *pat, struct grecs_value *b, int flags)
120{
121 if (pat == 0 || b == 0)
122 return pat == b;
123 if (pat->type != b->type) {
124 if (pat->type != GRECS_TYPE_STRING)
125 return 0;
126 switch (b->type) {
127 case GRECS_TYPE_LIST:
128 b = grecs_list_index(b->v.list, 0);
129 break;
130
131 case GRECS_TYPE_ARRAY:
132 b = b->v.arg.v[0];
133 }
134 }
135
136 switch (pat->type) {
137 case GRECS_TYPE_STRING:
138 if (pat->v.string == NULL)
139 return b->v.string == NULL;
140 return fnmatch(pat->v.string, b->v.string, flags) == 0;
141
142 case GRECS_TYPE_LIST:
143 return _grecs_list_match(pat, b, flags);
144
145 case GRECS_TYPE_ARRAY:
146 return _grecs_array_match(pat, b, flags);
147 }
148 return 0;
149}
82 150
83 151
84struct grecs_match_buf { 152struct grecs_match_buf {
@@ -104,8 +172,10 @@ grecs_match_buf_free_contents(struct grecs_match_buf *buf)
104void 172void
105grecs_match_buf_free(struct grecs_match_buf *buf) 173grecs_match_buf_free(struct grecs_match_buf *buf)
106{ 174{
107 grecs_match_buf_free_contents(buf); 175 if (buf) {
108 free(buf); 176 grecs_match_buf_free_contents(buf);
177 free(buf);
178 }
109} 179}
110 180
111 181
@@ -333,10 +403,12 @@ grecs_match(struct grecs_match_buf *buf)
333 continue; 403 continue;
334 } 404 }
335 405
336 if (strcmp(buf->argv[buf->argi], node->ident) == 0 406 if ((ISWC(buf->argv[buf->argi], '%') ||
407 strcmp(buf->argv[buf->argi], node->ident) == 0)
337 /* FIXME: */ 408 /* FIXME: */
338 && (!buf->labelv[buf->argi] || 409 && (!buf->labelv[buf->argi] ||
339 grecs_value_eq(buf->labelv[buf->argi], node->v.value))) { 410 grecs_value_match(buf->labelv[buf->argi],
411 node->v.value, 0))) {
340 wcard = 0; 412 wcard = 0;
341 node = node->up; 413 node = node->up;
342 if (buf->argi-- == 0) 414 if (buf->argi-- == 0)
@@ -365,6 +437,7 @@ struct grecs_node *
365grecs_match_first(struct grecs_node *tree, const char *pattern, 437grecs_match_first(struct grecs_node *tree, const char *pattern,
366 struct grecs_match_buf **pbuf) 438 struct grecs_match_buf **pbuf)
367{ 439{
440 int i;
368 struct grecs_node *node; 441 struct grecs_node *node;
369 struct grecs_match_buf *buf; 442 struct grecs_match_buf *buf;
370 443
@@ -381,6 +454,27 @@ grecs_match_first(struct grecs_node *tree, const char *pattern,
381 } 454 }
382 /* FIXME: Compress argv/argc by replacing contiguous sequences of *'s 455 /* FIXME: Compress argv/argc by replacing contiguous sequences of *'s
383 with a single *. */ 456 with a single *. */
457 for (i = 0; i < buf->argc; i++) {
458 if (ISWC(buf->argv[i], '*')) {
459 int j;
460
461 for (j = i + 1;
462 j < buf->argc && ISWC(buf->argv[j], '*'); j++)
463 free(buf->argv[j]);
464 j -= i;
465 if (j > 1) {
466 memmove(&buf->argv[i+1], &buf->argv[i+j],
467 (buf->argc - (i + j)) *
468 sizeof(buf->argv[0]));
469 memmove(&buf->labelv[i+1], &buf->labelv[i+j],
470 (buf->argc - (i + j)) *
471 sizeof(buf->labelv[0]));
472 buf->argc -= j - 1;
473 }
474 }
475 }
476
477
384 buf->argi = 0; 478 buf->argi = 0;
385 buf->node = grecs_tree_first_node(tree); 479 buf->node = grecs_tree_first_node(tree);
386 *pbuf = buf; 480 *pbuf = buf;

Return to:

Send suggestions and report system problems to the System administrator.