diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-02-18 00:04:51 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-02-18 00:04:51 +0200 |
commit | 8c4ab07dbf003ba07bec6e77fd803b9c54b91e52 (patch) | |
tree | 9f4e1b0dcd3f10e78c815d6c5baecc8da8ad1c47 | |
parent | 317095181674a01651602ddf6817e888d0ad5280 (diff) | |
download | wydawca-8c4ab07dbf003ba07bec6e77fd803b9c54b91e52.tar.gz wydawca-8c4ab07dbf003ba07bec6e77fd803b9c54b91e52.tar.bz2 |
Various fixes
-rw-r--r-- | gconf/gnulib.modules | 13 | ||||
-rw-r--r-- | gnulib.modules | 1 | ||||
-rw-r--r-- | src/builtin.c | 224 | ||||
-rw-r--r-- | src/builtin.h | 3 | ||||
-rw-r--r-- | src/method.c | 5 |
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 (®ex, pat, flags); + if (rc) + { + char errbuf[512]; + + regerror (rc, ®ex, errbuf, sizeof (errbuf)); + logmsg (LOG_ERR, "%s: cannot compile regexp: %s", pat, errbuf); + return 0; + } + + rc = regexec (®ex, str, 0, NULL, 0); + regfree (®ex); + 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, "e); - output = xmalloc (size); + output = xmalloc (size + 1); argcv_quote_copy (output, input); + output[size] = 0; *poutput = output; if (psize) |