[Dctrl-tools-devel] [SCM] Debian control file query tools branch, master, updated. 2.21.1-8-gb2a4f15

Antti-Juhani Kaijanaho ajk at debian.org
Sun Apr 22 19:16:08 UTC 2012


The following commit has been merged in the master branch:
commit b2a4f15ad801b30fb8ffdad6856433fcd43c6590
Author: Antti-Juhani Kaijanaho <ajk at debian.org>
Date:   Sun Apr 22 22:15:39 2012 +0300

    grep-dctrl: Allow distributing atom modifiers over a parenthesed predicate.
    
    
    Signed-off-by: Antti-Juhani Kaijanaho <ajk at debian.org>

diff --git a/debian/changelog b/debian/changelog
index f430b33..f260bda 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,8 +1,11 @@
 dctrl-tools (2.22) UNRELEASED; urgency=low
 
   * debian/copyright: Upgraded to copyright-format/1.0, and updated.
-
- -- Antti-Juhani Kaijanaho <ajk at debian.org>  Sat, 21 Apr 2012 11:32:47 +0300
+  * grep-dctrl: Allow distributing atom modifiers over a parenthesed predicate.
+    Closes: #319760 (allow -F modifiers to apply to an entire expression)
+    Reported by Enrico Zini <enrico at debian.org>
+  
+ -- Antti-Juhani Kaijanaho <ajk at debian.org>  Sun, 22 Apr 2012 22:09:30 +0300
 
 dctrl-tools (2.21.1) unstable; urgency=low
 
diff --git a/grep-dctrl/grep-dctrl.c b/grep-dctrl/grep-dctrl.c
index 526ad61..020681c 100644
--- a/grep-dctrl/grep-dctrl.c
+++ b/grep-dctrl/grep-dctrl.c
@@ -501,103 +501,109 @@ static void unexpected(int tok)
 	}
 }
 
-static struct predicate * parse_conj(struct arguments * args);
+struct predicate_qualifiers {
+        struct strlist *fields;
+        enum matching_mode mm;
+        bool ignore_case;
+        bool whole_pkg;
+};
 
+static struct predicate * parse_conj(struct arguments * args,
+                                     struct predicate_qualifiers pq);
 
-/* prim -> TOK_LP conj TOK_RP
-   prim -> prim'
+/* prim -> primtok
+   prim -> primtok prim
+   prim -> TOK_LP conj TOK_RP
+   prim -> TOK_PAT prim'
+   prim -> TOK_STR prim'
 
-   prim' -> primtok
+   prim' ->
    prim' -> primtok prim'
-   prim' -> TOK_PAT prim''
-   prim' -> TOK_STR prim''
-
-   prim'' ->
-   prim'' -> primtok prim''
 
    primtok -> TOK_FIELD
    primtok -> TOK_ERGEX | TOK_REGEX
    primtok -> TOK_ICASE | TOK_EXACT | TOK_WHOLE
    primtok -> TOK_EQ | TOK_LT | TOK_LE | TOK_GE | TOK_GT
 */
-static struct predicate * parse_prim(struct arguments * args)
+static struct predicate * parse_prim(struct arguments * args,
+                                     struct predicate_qualifiers pq_)
 {
-	if (peek_token(args) == TOK_LP) {
-		get_token(args);
-		struct predicate * rv = parse_conj(args);
-		if (get_token(args) != TOK_RP) {
-			message(L_FATAL, 0, _("missing ')' in command line"));
-			fail();
-		}
-		return rv;
-	}
-
         char *pattern = 0;
-        struct strlist *fields = strlist_new();
-        if (fields == 0) enomem(0);
-        enum matching_mode mm = M_SUBSTR;
-        bool ignore_case = false;
-        bool whole_pkg = false;
-        bool nonempty = false;
+        struct predicate *rv = 0;
 
+        struct predicate_qualifiers pq = pq_;
+        struct strlist_memento mem = strlist_save(pq.fields);
+
+        bool nonempty = false;
         while (1) {
-                debug("tok = %s, mm = %d", tokdescr(peek_token(args)), mm);
+                debug("tok = %s, mm = %d", tokdescr(peek_token(args)), pq.mm);
                 switch (peek_token(args)) {
                 case TOK_FIELD:
-                        if (!strlist_append(fields, get_string(args))) {
+                        if (!strlist_append(pq.fields, get_string(args))) {
                                 enomem(0);
                         }
                         break;
                 case TOK_ERGEX:
-                        if (mm != M_SUBSTR) goto failmode;
-                        mm = M_EREGEX;
+                        if (pq.mm != M_SUBSTR) goto failmode;
+                        pq.mm = M_EREGEX;
                         get_token(args);
                         break;
                 case TOK_REGEX:
-                        if (mm != M_SUBSTR) goto failmode;
-                        mm = M_REGEX;
+                        if (pq.mm != M_SUBSTR) goto failmode;
+                        pq.mm = M_REGEX;
                         get_token(args);
                         break;
                 case TOK_ICASE:
-                        ignore_case = true;
+                        pq.ignore_case = true;
                         get_token(args);
                         break;
                 case TOK_EXACT:
-                        if (mm != M_SUBSTR) goto failmode;
-                        mm = M_EXACT;
+                        if (pq.mm != M_SUBSTR) goto failmode;
+                        pq.mm = M_EXACT;
                         get_token(args);
                         break;
                 case TOK_WHOLE:
-                        if (mm != M_SUBSTR) goto failmode;
-                        mm = M_EREGEX;
-                        whole_pkg = true;
+                        if (pq.mm != M_SUBSTR) goto failmode;
+                        pq.mm = M_EREGEX;
+                        pq.whole_pkg = true;
                         get_token(args);
                         break;
                 case TOK_EQ:
-                        if (mm != M_SUBSTR) goto failmode;
-                        mm = M_VER_EQ;
+                        if (pq.mm != M_SUBSTR) goto failmode;
+                        pq.mm = M_VER_EQ;
                         get_token(args);
                         break;
                 case TOK_LT:
-                        if (mm != M_SUBSTR) goto failmode;
-                        mm = M_VER_LT;
+                        if (pq.mm != M_SUBSTR) goto failmode;
+                        pq.mm = M_VER_LT;
                         get_token(args);
                         break;
                 case TOK_LE:
-                        if (mm != M_SUBSTR) goto failmode;
-                        mm = M_VER_LE;
+                        if (pq.mm != M_SUBSTR) goto failmode;
+                        pq.mm = M_VER_LE;
                         get_token(args);
                         break;
                 case TOK_GT:
-                        if (mm != M_SUBSTR) goto failmode;
-                        mm = M_VER_GT;
+                        if (pq.mm != M_SUBSTR) goto failmode;
+                        pq.mm = M_VER_GT;
                         get_token(args);
                         break;
                 case TOK_GE:
-                        if (mm != M_SUBSTR) goto failmode;
-                        mm = M_VER_GE;
+                        if (pq.mm != M_SUBSTR) goto failmode;
+                        pq.mm = M_VER_GE;
                         get_token(args);
                         break;
+                case TOK_LP:
+                {
+                        get_token(args);
+                        rv = parse_conj(args, pq);
+                        if (get_token(args) != TOK_RP) {
+                                message(L_FATAL, 0,
+                                        _("missing ')' in command line"));
+                                fail();
+                        }
+                        goto finally;
+                }
                 case TOK_PAT:
                         if (pattern != 0) {
                                 message(L_FATAL, 0,
@@ -613,7 +619,7 @@ static struct predicate * parse_prim(struct arguments * args)
                 default:
                         goto loop_done;
                 }
-                 nonempty = true;
+                nonempty = true;
         } loop_done:
 
         if (!nonempty) {
@@ -625,20 +631,19 @@ static struct predicate * parse_prim(struct arguments * args)
                 fail();
         }
         
-        if (strlist_is_empty(fields)) {
-                strlist_append(fields, 0);
+        if (strlist_is_empty(pq.fields)) {
+                strlist_append(pq.fields, 0);
          }
         
-        struct predicate *rv = 0;
-        for (struct strlist_iterator it = strlist_begin(fields);
+        for (struct strlist_iterator it = strlist_begin(pq.fields);
              !strlist_iterator_at_end(it); strlist_iterator_next(&it)) {
                 struct atom * atom = malloc(sizeof *atom);
                 if (atom == 0) enomem(0);
                 atom->field_name = strlist_iterator_get(it);
                 atom->field_inx = -1;
-                atom->mode = mm;
-                atom->ignore_case = ignore_case;
-                atom->whole_pkg = whole_pkg;
+                atom->mode = pq.mm;
+                atom->ignore_case = pq.ignore_case;
+                atom->whole_pkg = pq.whole_pkg;
                 atom->pat = pattern;
                 atom->patlen = strlen(pattern);
                 atom_finish(atom);
@@ -646,26 +651,28 @@ static struct predicate * parse_prim(struct arguments * args)
                 rv = rv != 0 ? predicate_OR(rv, tmp) : tmp;
         }
         
-        strlist_free(fields);
+finally:
+        strlist_restore(mem);
         return rv;
 failmode:
-        strlist_free(fields);
         message(L_FATAL, 0, _("inconsistent modifiers of simple filters")); 
         fail();
-        return 0;
+        rv = 0;
+        goto finally;
 }
 
 /* neg -> TOK_NOT prim
    neg -> prim
 */
-static struct predicate * parse_neg(struct arguments * args)
+static struct predicate * parse_neg(struct arguments * args,
+                                    struct predicate_qualifiers pq)
 {
 	bool neg = false;
 	if (peek_token(args) == TOK_NOT) {
 		neg = true;
 		get_token(args);
 	}
-	struct predicate * rv = parse_prim(args);
+	struct predicate * rv = parse_prim(args, pq);
 	if (neg) rv = predicate_NOT(rv);
         return rv;
 }
@@ -673,12 +680,13 @@ static struct predicate * parse_neg(struct arguments * args)
 /* disj -> neg
    disj -> disj TOK_OR neg
 */
-static struct predicate * parse_disj(struct arguments * args)
+static struct predicate * parse_disj(struct arguments * args,
+                                     struct predicate_qualifiers pq)
 {
-	struct predicate * rv = parse_neg(args);
+	struct predicate * rv = parse_neg(args, pq);
 	while (peek_token(args) == TOK_OR) {
 		get_token(args);
-		struct predicate * tmp = parse_neg(args);
+		struct predicate * tmp = parse_neg(args, pq);
                 rv = predicate_OR(rv, tmp);
 	}
         return rv;
@@ -687,12 +695,13 @@ static struct predicate * parse_disj(struct arguments * args)
 /* conj -> disj
    conj -> conj TOK_AND disj
 */
-static struct predicate * parse_conj(struct arguments * args)
+static struct predicate * parse_conj(struct arguments * args,
+                                     struct predicate_qualifiers pq)
 {
-	struct predicate * rv = parse_disj(args);
+	struct predicate * rv = parse_disj(args, pq);
 	while (peek_token(args) == TOK_AND) {
 		get_token(args);
-		struct predicate * tmp = parse_disj(args);
+		struct predicate * tmp = parse_disj(args, pq);
                 rv = predicate_AND(rv, tmp);
 	}
         return rv;
@@ -705,7 +714,18 @@ static struct predicate * parse_conj(struct arguments * args)
 static void parse_predicate(struct arguments * args)
 {
 	args->toks_pos = 0;
-	args->p = parse_conj(args);
+
+        struct predicate_qualifiers pq;
+        pq.fields = strlist_new();
+        if (pq.fields == 0) enomem(0);
+        pq.mm = M_SUBSTR;
+        pq.ignore_case = false;
+        pq.whole_pkg = false;
+
+	args->p = parse_conj(args, pq);
+
+        strlist_free(pq.fields);
+
         while (peek_token(args) == TOK_STR) {
                 if (args->num_fnames >= MAX_FNAMES) {
                         message(L_FATAL, 0, _("too many file names"));
diff --git a/lib/strlist.c b/lib/strlist.c
index c21a410..2877dc5 100644
--- a/lib/strlist.c
+++ b/lib/strlist.c
@@ -85,3 +85,17 @@ void strlist_iterator_next(struct strlist_iterator * it)
 {
         it->i++;
 }
+
+struct strlist_memento strlist_save(struct strlist *sl)
+{
+        struct strlist_memento rv = {
+                .sl = sl,
+                .n = sl->n
+        };
+        return rv;
+}
+void strlist_restore(struct strlist_memento mem)
+{
+        mem.sl->n = mem.n;
+}
+
diff --git a/lib/strlist.h b/lib/strlist.h
index da64623..d0de21a 100644
--- a/lib/strlist.h
+++ b/lib/strlist.h
@@ -24,12 +24,19 @@ struct strlist_iterator {
         struct strlist *sl;
         size_t i;
 };
+struct strlist_memento {
+        struct strlist *sl;
+        size_t n;
+};
 
 struct strlist *strlist_new(void);
 _Bool strlist_append(struct strlist *, const char *);
 _Bool strlist_is_empty(struct strlist *);
 void strlist_free(struct strlist *);
 
+struct strlist_memento strlist_save(struct strlist *);
+void strlist_restore(struct strlist_memento);
+
 struct strlist_iterator strlist_begin(struct strlist *);
 _Bool strlist_iterator_at_end(struct strlist_iterator);
 const char *strlist_iterator_get(struct strlist_iterator);
diff --git a/man/grep-dctrl.1.cp b/man/grep-dctrl.1.cp
index 4fe24f0..4729376 100644
--- a/man/grep-dctrl.1.cp
+++ b/man/grep-dctrl.1.cp
@@ -1,6 +1,7 @@
-.TH GREP-DCTRL 1 2011-12-18 "Debian Project" "Debian user's manual"
-\" Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2011
-\"               Antti-Juhani Kaijanaho <gaia at iki.fi>
+.TH GREP-DCTRL 1 2012-04-22 "Debian Project" "Debian user's manual"
+\" Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2011,
+\"               2012
+\"               Antti-Juhani Kaijanaho <ajk at debian.org>
 \"      This program is free software; you can redistribute it and/or modify
 \"      it under the terms of the GNU General Public License as published by
 \"      the Free Software Foundation; either version 2 of the License, or
@@ -247,7 +248,9 @@ matches.
 Match if both the preceding and the following filter match.
 .IP "\fB(\fR ... \fB)"
 Parentheses can be used for grouping.  Note that they need to be
-escaped for most shells.
+escaped for most shells.  Filter modifiers can be given before the
+opening parentheses; they will be treated as if they had been repeated
+for each simple filter inside the parentheses.
 .SS Output format modifiers
 .IP "\fB\-s \fIfield\fR,\fIfield\fR, ... | \fB\-\-show\-field=\fIfield\fR,\fIfield\fR, ..."
 Show only the body of these
diff --git a/tests/0016.out b/tests/bug319760.in
similarity index 50%
copy from tests/0016.out
copy to tests/bug319760.in
index b0bcef9..6d4f0df 100644
--- a/tests/0016.out
+++ b/tests/bug319760.in
@@ -1,4 +1,3 @@
-Source: foo
-
 Package: foo
+Whatever: bar
 
diff --git a/tests/0016.out b/tests/bug319760.out
similarity index 50%
copy from tests/0016.out
copy to tests/bug319760.out
index b0bcef9..6d4f0df 100644
--- a/tests/0016.out
+++ b/tests/bug319760.out
@@ -1,4 +1,3 @@
-Source: foo
-
 Package: foo
+Whatever: bar
 
diff --git a/tests/bug319760.sh b/tests/bug319760.sh
new file mode 100644
index 0000000..eb6cff6
--- /dev/null
+++ b/tests/bug319760.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+set -e
+
+${GREP_DCTRL:-grep-dctrl} -FPackage \( foo -a ! bar \)

-- 
Debian control file query tools



More information about the Dctrl-tools-devel mailing list