aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2009-02-18 00:04:51 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2009-02-18 00:04:51 +0200
commit8c4ab07dbf003ba07bec6e77fd803b9c54b91e52 (patch)
tree9f4e1b0dcd3f10e78c815d6c5baecc8da8ad1c47
parent317095181674a01651602ddf6817e888d0ad5280 (diff)
downloadwydawca-8c4ab07dbf003ba07bec6e77fd803b9c54b91e52.tar.gz
wydawca-8c4ab07dbf003ba07bec6e77fd803b9c54b91e52.tar.bz2
Various fixes
-rw-r--r--gconf/gnulib.modules13
-rw-r--r--gnulib.modules1
-rw-r--r--src/builtin.c224
-rw-r--r--src/builtin.h3
-rw-r--r--src/method.c5
5 files changed, 231 insertions, 15 deletions
diff --git a/gconf/gnulib.modules b/gconf/gnulib.modules
index c211bcd..5ba9e5f 100644
--- a/gconf/gnulib.modules
+++ b/gconf/gnulib.modules
@@ -1,13 +1,14 @@
-hash
-xalloc
-linked-list
+# getdtablesize ??
+c-ctype
getline
+hash
inttostr
inttypes
+linked-list
obstack
+regex
+stdbool
strtoimax
strtoumax
vasprintf
-# getdtablesize ??
-c-ctype
-stdbool \ No newline at end of file
+xalloc
diff --git a/gnulib.modules b/gnulib.modules
index 7480221..1c56638 100644
--- a/gnulib.modules
+++ b/gnulib.modules
@@ -1,5 +1,6 @@
xalloc
c-ctype
+fnmatch
obstack
getopt
gitlog-to-changelog
diff --git a/src/builtin.c b/src/builtin.c
index 9786383..711694f 100644
--- a/src/builtin.c
+++ b/src/builtin.c
@@ -16,6 +16,11 @@
#include "wydawca.h"
#include "builtin.h"
+#include "fnmatch.h"
+#include "regex.h"
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free free
+#include "obstack.h"
int
builtin_init (struct access_method *meth)
@@ -35,11 +40,219 @@ builtin_open (struct access_method *meth)
return meth;
}
+#define CMP_EXACT 0
+#define CMP_FNMATCH 1
+#define CMP_REGEX 2
+
+#define RF_ICASE 0x1
+#define RF_BASIC 0x2
+
+#define STRMATCH(s, p, len) \
+ (len == sizeof(s) - 1 && memcmp (s, p, sizeof(s) - 1) == 0)
+
+typedef int (*strcmp_fn) (const char *, const char *, int flags);
+
+static int
+cmp_exact (const char *pat, const char *str, int flags)
+{
+ return strcmp (pat, str) == 0;
+}
+
+static int
+cmp_exact_ci (const char *pat, const char *str, int flags)
+{
+ return strcmp (pat, str) == 0;
+}
+
+static int
+cmp_fnmatch (const char *pat, const char *str, int flags)
+{
+ return fnmatch (pat, str, flags) == 0;
+}
+
+static int
+cmp_regex (const char *pat, const char *str, int flags)
+{
+ int rc;
+ regex_t regex;
+
+ rc = regcomp (&regex, pat, flags);
+ if (rc)
+ {
+ char errbuf[512];
+
+ regerror (rc, &regex, errbuf, sizeof (errbuf));
+ logmsg (LOG_ERR, "%s: cannot compile regexp: %s", pat, errbuf);
+ return 0;
+ }
+
+ rc = regexec (&regex, str, 0, NULL, 0);
+ regfree (&regex);
+ return rc == 0;
+}
+
+int
+parse_cmp_type (const char *pat, strcmp_fn *cmpfn, int *rf)
+{
+ size_t len = strcspn (pat, ",");
+ int flags = 0;
+ int cmp;
+
+ if (STRMATCH ("exact", pat, len))
+ cmp = CMP_EXACT;
+ else if (STRMATCH ("fnmatch", pat, len))
+ cmp = CMP_FNMATCH;
+ else if (STRMATCH ("regex", pat, len))
+ cmp = CMP_REGEX;
+ else
+ return 1;
+
+ pat += len;
+ if (*pat)
+ {
+ while (*++pat)
+ {
+ switch (*pat)
+ {
+ case 'i':
+ flags |= RF_ICASE;
+ break;
+
+ case 'b':
+ flags |= RF_BASIC;
+ break;
+
+ default:
+ logmsg (LOG_NOTICE, "unrecognized comparison flag: %c", *pat);
+ }
+ }
+ }
+
+ switch (cmp)
+ {
+ case CMP_EXACT:
+ *cmpfn = (flags & RF_ICASE) ? cmp_exact_ci : cmp_exact;
+ break;
+
+ case CMP_FNMATCH:
+ *cmpfn = cmp_fnmatch;
+ *rf = FNM_NOESCAPE | FNM_PERIOD |
+ ((flags & RF_ICASE) ? FNM_CASEFOLD : 0);
+ break;
+
+ case CMP_REGEX:
+ *cmpfn = cmp_regex;
+ *rf = ((flags & RF_BASIC) ? 0 : REG_EXTENDED) | REG_NOSUB;
+ if (flags & RF_ICASE)
+ *rf |= REG_ICASE;
+ break;
+ }
+ return 0;
+}
+
+struct builtin_data_storage
+{
+ struct obstack stk;
+ char **wp;
+};
+
+static int default_ncol[] = {
+ 1, /* verify-user: arbitrary return, usually user name */
+ 1, /* gpg-key: key */
+ 2, /* project-owner: email, realname */
+ 2, /* user-data: email, realname */
+};
+
int
builtin_run (struct access_method *meth, void *handle, const char *req)
{
- meth->nrow = meth->parmc;
- meth->ncol = 1;
+ int i;
+ size_t count = 0;
+ struct obstack stk;
+ int flags = 0;
+ strcmp_fn cmpfn = cmp_exact;
+ struct builtin_data_storage *bds;
+ int ncol = default_ncol[meth->id];
+
+ if (meth->parmc == 0)
+ {
+ meth->nrow = meth->ncol = 0;
+ return 0;
+ }
+
+ obstack_init (&stk);
+
+ for (i = 0; i < meth->parmc; i++)
+ {
+ char *pat = meth->parmv[i];
+ char *val;
+
+ if (pat[0] == '/')
+ {
+ pat++;
+ if (*pat != '/' && parse_cmp_type (pat, &cmpfn, &flags) == 0)
+ continue;
+ }
+
+ if (i + ncol >= meth->parmc)
+ break;
+
+ if (cmpfn (pat, req, flags))
+ {
+ size_t j;
+ for (j = 1; j <= ncol; j++)
+ {
+ char *val = meth->parmv[i + j];
+ obstack_grow (&stk, val, strlen (val) + 1);
+ }
+ count++;
+ }
+
+ i += ncol;
+ }
+
+ meth->nrow = count;
+ meth->ncol = ncol;
+
+ if (count == 0)
+ {
+ obstack_free (&stk, NULL);
+ bds = NULL;
+ }
+ else
+ {
+ size_t i;
+ char *p;
+
+ bds = xmalloc (sizeof (*bds));
+ count *= ncol;
+ bds->wp = xcalloc (count, sizeof (bds->wp[0]));
+ bds->stk = stk;
+ p = obstack_finish (&stk);
+
+ for (i = 0; i < count; i++)
+ {
+ bds->wp[i] = p;
+ p += strlen (p) + 1;
+ }
+ }
+
+ meth->storage = bds;
+
+ return 0;
+}
+
+int
+builtin_free_result (struct access_method *method, void *handle)
+{
+ if (method->storage)
+ {
+ struct builtin_data_storage *bds = method->storage;
+ obstack_free (&bds->stk, NULL);
+ free (bds->wp);
+ free (bds);
+ method->storage = NULL;
+ }
return 0;
}
@@ -47,10 +260,9 @@ int
builtin_get (struct access_method *method, void *handle,
unsigned nrow, unsigned ncol)
{
- if (nrow >= method->parmc)
- return 1;
- method_copy_result (method, method->parmv[nrow],
- strlen (method->parmv[nrow]));
+ struct builtin_data_storage *bds = method->storage;
+ char *str = bds->wp[nrow * method->ncol + ncol];
+ method_copy_result (method, str, strlen (str));
return 0;
}
diff --git a/src/builtin.h b/src/builtin.h
index 4fe40bd..500a6cb 100644
--- a/src/builtin.h
+++ b/src/builtin.h
@@ -18,4 +18,5 @@ int builtin_init (struct access_method *);
int builtin_done (struct access_method *);
void *builtin_open (struct access_method *);
int builtin_get (struct access_method *, void *, unsigned, unsigned);
-int builtin_run (struct access_method *meth, void *, const char *req);
+int builtin_run (struct access_method *, void *, const char *);
+int builtin_free_result (struct access_method *, void *);
diff --git a/src/method.c b/src/method.c
index a201f02..7811612 100644
--- a/src/method.c
+++ b/src/method.c
@@ -38,7 +38,7 @@ static struct method_descr method_tab[] = {
{ "none", NULL, NULL, NULL, NULL, NULL, NULL, NULL },
{ "sql", sql_init_method, sql_done_method, sql_free_result,
sql_open, NULL, sql_get_method, sql_run_method, sql_quote },
- { "builtin", builtin_init, builtin_done, NULL,
+ { "builtin", builtin_init, builtin_done, builtin_free_result,
builtin_open, NULL,
builtin_get,
builtin_run },
@@ -213,8 +213,9 @@ method_quote_string (struct access_method *method, void *handle,
return mp->quote (method, handle, input, poutput, psize);
size = argcv_quoted_length (input, &quote);
- output = xmalloc (size);
+ output = xmalloc (size + 1);
argcv_quote_copy (output, input);
+ output[size] = 0;
*poutput = output;
if (psize)

Return to:

Send suggestions and report system problems to the System administrator.