diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2015-02-12 16:30:53 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2015-02-12 16:30:53 +0200 |
commit | 133e104d9efac43c0cf243207c2c5eaf0343bced (patch) | |
tree | 64399bcc3d6b33de2fb911d291ba90656b028fc1 | |
parent | c36a2210ed6cd53c5c65418fa9c20ac22dec8c59 (diff) | |
download | vmod-variable-133e104d9efac43c0cf243207c2c5eaf0343bced.tar.gz vmod-variable-133e104d9efac43c0cf243207c2c5eaf0343bced.tar.bz2 |
Improve batchset
The new syntax allows for supplying replacement patterns as in
variable.batchset("x:duration=\2s", ...
* configure.ac: Remove unneeded check
* src/variable.c (vardef): New member repl.
(bref_expand): New function.
(vmod_batchset): Change handling of vars string.
* tests/batchset.at: Update.
-rw-r--r-- | configure.ac | 18 | ||||
-rw-r--r-- | src/variable.c | 139 | ||||
-rw-r--r-- | tests/batchset.at | 6 |
3 files changed, 101 insertions, 62 deletions
diff --git a/configure.ac b/configure.ac index 2fa32f6..f21fcfb 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -108,24 +108,6 @@ if test -z "$VMODDIR"; then | |||
108 | VMODDIR='$(libdir)/varnish/mods' | 108 | VMODDIR='$(libdir)/varnish/mods' |
109 | fi | 109 | fi |
110 | 110 | ||
111 | ########### | ||
112 | # Check for db.h and libdb | ||
113 | # | ||
114 | AC_CHECK_HEADER([db.h],,[AC_MSG_ERROR([Required header file db.h not found])]) | ||
115 | |||
116 | AC_CHECK_LIB(db, db_create, | ||
117 | [LIBS="$LIBS -ldb" | ||
118 | AC_RUN_IFELSE( | ||
119 | [AC_LANG_PROGRAM([#include "db.h"], | ||
120 | [int v_major, v_minor, v_patch; | ||
121 | db_version(&v_major, &v_minor, &v_patch); | ||
122 | return !(v_major == DB_VERSION_MAJOR | ||
123 | && v_minor == DB_VERSION_MINOR | ||
124 | && v_patch == DB_VERSION_PATCH); | ||
125 | ])], | ||
126 | [], | ||
127 | [AC_MSG_ERROR([header file db.h is not the same version as libdb])])]) | ||
128 | |||
129 | AC_CONFIG_COMMANDS([status],[ | 111 | AC_CONFIG_COMMANDS([status],[ |
130 | delim="-------------------------------------------------------------------" | 112 | delim="-------------------------------------------------------------------" |
131 | echo "" | 113 | echo "" |
diff --git a/src/variable.c b/src/variable.c index 6403c1a..9442b6b 100644 --- a/src/variable.c +++ b/src/variable.c | |||
@@ -500,7 +500,8 @@ log_error(const char *fmt, ...) | |||
500 | struct vardef { | 500 | struct vardef { |
501 | struct vardef *next; | 501 | struct vardef *next; |
502 | enum variable_type type; | 502 | enum variable_type type; |
503 | char name[1]; | 503 | char *name; |
504 | char *repl; | ||
504 | }; | 505 | }; |
505 | 506 | ||
506 | static void | 507 | static void |
@@ -570,6 +571,51 @@ str2duration(const char *str) | |||
570 | return *p ? 0 : r; | 571 | return *p ? 0 : r; |
571 | } | 572 | } |
572 | 573 | ||
574 | char * | ||
575 | bref_expand(const char *str, const char *input, pcre *re, | ||
576 | int ovsize, int *ovector) | ||
577 | { | ||
578 | size_t rlen = 0; | ||
579 | char *rbase = NULL; | ||
580 | char *rptr; | ||
581 | int nm = 2*ovsize/3; | ||
582 | const char *p; | ||
583 | |||
584 | for (p = str; *p; ) { | ||
585 | if (*p == '\\' && strchr("123456789", p[1])) { | ||
586 | int n = 2*(p[1] - '0'); | ||
587 | if (n < nm) { | ||
588 | rlen += ovector[n+1] - ovector[n]; | ||
589 | p += 2; | ||
590 | continue; | ||
591 | } | ||
592 | } | ||
593 | ++p; | ||
594 | ++rlen; | ||
595 | } | ||
596 | rbase = malloc(rlen + 1); | ||
597 | AN(rbase); | ||
598 | p = str; | ||
599 | rptr = rbase; | ||
600 | while (*p) { | ||
601 | if (*p == '\\' && strchr("123456789", p[1])) { | ||
602 | int n = 2*(p[1] - '0'); | ||
603 | if (n < nm) { | ||
604 | memcpy(rptr, input + ovector[n], | ||
605 | ovector[n+1] - ovector[n]); | ||
606 | rptr += ovector[n+1] - ovector[n]; | ||
607 | p += 2; | ||
608 | continue; | ||
609 | } | ||
610 | } | ||
611 | |||
612 | *rptr++ = *p++; | ||
613 | } | ||
614 | *rptr = 0; | ||
615 | |||
616 | return rbase; | ||
617 | } | ||
618 | |||
573 | VCL_VOID | 619 | VCL_VOID |
574 | vmod_batchset(VARIABLE_CTX ctx, | 620 | vmod_batchset(VARIABLE_CTX ctx, |
575 | VCL_STRING vars, VCL_STRING rxs, VCL_STRING input) | 621 | VCL_STRING vars, VCL_STRING rxs, VCL_STRING input) |
@@ -598,50 +644,63 @@ vmod_batchset(VARIABLE_CTX ctx, | |||
598 | } | 644 | } |
599 | 645 | ||
600 | while (*v) { | 646 | while (*v) { |
601 | size_t n = strcspn(v, "="); | 647 | char const *nameptr = v; |
648 | size_t n = strcspn(v, ":=,"); | ||
649 | size_t namelen; | ||
650 | char const *replptr; | ||
651 | size_t repllen; | ||
652 | char rbuf[3]; | ||
653 | enum variable_type type; | ||
654 | int delim; | ||
655 | |||
656 | namelen = n; | ||
602 | 657 | ||
603 | if (!v[n]) { | 658 | v += n; |
604 | log_error("variable.batchset: vars argument invalid near %s", | 659 | delim = *v ? *v++ : 0; |
605 | v); | 660 | |
606 | vardef_free(head); | 661 | if (delim == ':') { |
607 | return; | 662 | n = strcspn(v, "=,"); |
663 | type = str2type(v, n); | ||
664 | v += n; | ||
665 | delim = *v ? *v++ : 0; | ||
666 | } else | ||
667 | type = variable_string; | ||
668 | |||
669 | if (delim == '=') { | ||
670 | n = strcspn(v, ","); | ||
671 | replptr = v; | ||
672 | repllen = n; | ||
673 | v += n; | ||
674 | delim = *v ? *v++ : 0; | ||
675 | } else { | ||
676 | rbuf[0] = '\\'; | ||
677 | rbuf[1] = count + '1'; | ||
678 | rbuf[2] = 0; | ||
679 | replptr = rbuf; | ||
680 | repllen = 2; | ||
608 | } | 681 | } |
609 | def = malloc(sizeof(def[0]) + n); | 682 | |
683 | def = malloc(sizeof(def[0]) + namelen + repllen + 2); | ||
610 | def->next = NULL; | 684 | def->next = NULL; |
611 | memcpy(def->name, v, n); | ||
612 | def->name[n] = 0; | ||
613 | if (tail) | 685 | if (tail) |
614 | tail->next = def; | 686 | tail->next = def; |
615 | else | 687 | else |
616 | head = def; | 688 | head = def; |
617 | tail = def; | 689 | tail = def; |
618 | ++count; | 690 | ++count; |
619 | 691 | def->type = type; | |
620 | v += n + 1; | 692 | def->name = (char*)(def + 1); |
621 | if (!*v) { | 693 | memcpy(def->name, nameptr, namelen); |
622 | log_error("variable.batchset: no type for %s", def->name); | 694 | def->name[namelen] = 0; |
623 | vardef_free(head); | 695 | def->repl = def->name + namelen + 1; |
624 | return; | 696 | memcpy(def->repl, replptr, repllen); |
625 | } | 697 | def->repl[repllen] = 0; |
626 | |||
627 | n = strcspn(v, ","); | ||
628 | def->type = str2type(v, n); | ||
629 | if (def->type == variable_unset) { | ||
630 | log_error("variable.batchset: invalid type for %s", | ||
631 | def->name); | ||
632 | vardef_free(head); | ||
633 | return; | ||
634 | } | ||
635 | |||
636 | v += n; | ||
637 | if (*v) | ||
638 | ++v; | ||
639 | } | 698 | } |
640 | 699 | ||
641 | re = pcre_compile(rxs, cflags, &error_ptr, &error_offset, NULL); | 700 | re = pcre_compile(rxs, cflags, &error_ptr, &error_offset, NULL); |
642 | if (!re) { | 701 | if (!re) { |
643 | log_error("variable.batchset: %s: compilation failed near %s: %s", | 702 | log_error("variable.batchset: %s: compilation failed near %s: %s", |
644 | rxs, rxs + error_offset, error_ptr); | 703 | rxs, rxs + error_offset, error_ptr); |
645 | vardef_free(head); | 704 | vardef_free(head); |
646 | return; | 705 | return; |
647 | } | 706 | } |
@@ -673,16 +732,8 @@ vmod_batchset(VARIABLE_CTX ctx, | |||
673 | return; | 732 | return; |
674 | } | 733 | } |
675 | 734 | ||
676 | for (def = head, i = 1; def; def = def->next, i++) { | 735 | for (def = head; def; def = def->next, i++) { |
677 | const char *s; | 736 | char *s = bref_expand(def->repl, input, re, ovsize, ovector); |
678 | |||
679 | rc = pcre_get_substring(input, ovector, ovsize, i, &s); | ||
680 | if (rc < 0) { | ||
681 | log_error("variable.batchset: %s(%s) can't get subexpr #%d: %d", | ||
682 | rxs, input, i, rc); | ||
683 | vardef_free(head); | ||
684 | return; | ||
685 | } | ||
686 | 737 | ||
687 | switch (def->type) { | 738 | switch (def->type) { |
688 | case variable_string: | 739 | case variable_string: |
@@ -704,6 +755,7 @@ vmod_batchset(VARIABLE_CTX ctx, | |||
704 | value.i = 0; | 755 | value.i = 0; |
705 | } else | 756 | } else |
706 | value.i = lval; | 757 | value.i = lval; |
758 | free(s); | ||
707 | break; | 759 | break; |
708 | case variable_real: | 760 | case variable_real: |
709 | errno = 0; | 761 | errno = 0; |
@@ -716,11 +768,13 @@ vmod_batchset(VARIABLE_CTX ctx, | |||
716 |