[Dctrl-tools-devel] [SCM] Debian control file query tools branch, maint-2.20, updated. 2.20-23-g34ce3e2

Antti-Juhani Kaijanaho ajk at debian.org
Wed Dec 14 18:40:16 UTC 2011


The following commit has been merged in the maint-2.20 branch:
commit 34ce3e24a1d922b8778ec0b764540e5bc43155b4
Author: Antti-Juhani Kaijanaho <ajk at debian.org>
Date:   Wed Dec 14 20:36:48 2011 +0200

    Bug #652034: Handle multiple instances of the same field gracefully.
    
    For grep-dctrl, this means having -F search for all of the same-name
    fields disjunctively.  The -s option selects all same-name fields for
    printing.
    
    For the other tools, all but the first are ignored.
    
    No string changes, so committing to maint-2.20 for release with 2.20.1.
    
    Signed-off-by: Antti-Juhani Kaijanaho <ajk at debian.org>

diff --git a/debian/changelog b/debian/changelog
index 5cf885c..b6c0269 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -5,7 +5,11 @@ dctrl-tools (2.20.1) UNRELEASED; urgency=low
     #651218).
   * man pages order in SEE ALSO, thanks to Chris Leick (closes: #651219).
 
- -- David Prévot <taffit at debian.org>  Wed, 07 Dec 2011 11:56:51 -0400
+  [ Antti-Juhani Kaijanaho ]
+  * Handle multiple instances of the same field gracefully.  No string changes.
+    Closes: #652034 (reported by myself)
+
+ -- Antti-Juhani Kaijanaho <ajk at debian.org>  Wed, 14 Dec 2011 20:33:28 +0200
 
 dctrl-tools (2.20) unstable; urgency=low
 
diff --git a/grep-dctrl/grep-dctrl.c b/grep-dctrl/grep-dctrl.c
index 9e661bb..99ea398 100644
--- a/grep-dctrl/grep-dctrl.c
+++ b/grep-dctrl/grep-dctrl.c
@@ -753,36 +753,38 @@ static void show_field(struct arguments *args,
                        struct paragraph *para,
                        struct field_attr *fa)
 {
-        struct field_data *fd =
+        struct field_data fds =
                 find_field_wr(para,
                               fa->inx,
                               GET_BACKUP_FIELD(fa->application_data));
-        if (fd == NULL) return;
-        struct fsaf_read_rv r =
-                fsaf_read(para->common->fp, fd->start, fd->end - fd->start);
-
-        if (args->short_descr &&
-            fa == description_attr) {
-                char * nl = memchr(r.b, '\n', r.len);
-                if (nl != 0) r.len = nl - r.b;
-        }
+        for (struct field_datum *fd = fds.first; fd != NULL; fd = fd->next) {
+                struct fsaf_read_rv r =
+                        fsaf_read(para->common->fp,
+                                  fd->start, fd->end - fd->start);
 
-        if (r.len == 0) {
-                /* don't display a field with an empty value */
-                return;
-        }
+                if (args->short_descr &&
+                    fa == description_attr) {
+                        char * nl = memchr(r.b, '\n', r.len);
+                        if (nl != 0) r.len = nl - r.b;
+                }
 
-        if (args->show_field_name) {
-                struct fsaf_read_rv rn =
-                        fsaf_read(para->common->fp,
-                                  fd->name_start,
-                                  fd->name_end - fd->name_start);
-                fwrite(rn.b, 1, rn.len, stdout);
-                fputs(": ", stdout);
-        }
+                if (r.len == 0) {
+                        /* don't display a field with an empty value */
+                        break;
+                }
+
+                if (args->show_field_name) {
+                        struct fsaf_read_rv rn =
+                                fsaf_read(para->common->fp,
+                                          fd->name_start,
+                                          fd->name_end - fd->name_start);
+                        fwrite(rn.b, 1, rn.len, stdout);
+                        fputs(": ", stdout);
+                }
 
-        fwrite(r.b, 1, r.len, stdout);
-        puts("");
+                fwrite(r.b, 1, r.len, stdout);
+                puts("");
+        }
 }
 
 static struct argp argp = { .options = options,
diff --git a/lib/atom.c b/lib/atom.c
index 831620b..26d223a 100644
--- a/lib/atom.c
+++ b/lib/atom.c
@@ -69,26 +69,11 @@ void atom_finish(struct atom * atom)
 
 }
 
-bool atom_verify(struct atom * atom, para_t * para)
+static bool atom_field_verify(struct atom * atom, FSAF * fp,
+                              size_t start, size_t end)
 {
-	size_t start = 0;
-        size_t end = 0;
-	if (atom->field_inx == -1) {
-		/* Take the full paragraph */
-		start = para->start;
-		end = para->end;
-	} else {
-		/* Take the field */
-		struct field_data * fd = find_field_wr(para,
-                                                       atom->field_inx,
-                                                       atom->repl_inx);
-                if (fd != NULL) {
-                        start = fd->start;
-                        end = fd->end;
-                }                        
-	}
 	size_t len = end - start;
-	struct fsaf_read_rv r = fsaf_read(para->common->fp, start, len);
+	struct fsaf_read_rv r = fsaf_read(fp, start, len);
 	assert(r.len == len);
 	switch (atom->mode) {
 	case M_EXACT:
@@ -169,3 +154,18 @@ bool atom_verify(struct atom * atom, para_t * para)
 	}
 	assert(0);
 }
+
+bool atom_verify(struct atom * at, para_t * par)
+{
+        FSAF * fp = par->common->fp;
+	if (at->field_inx == -1) {
+		/* Take the full paragraph */
+                return atom_field_verify(at, fp, par->start, par->end);
+        }
+        /* Test field(s) */
+        struct field_data fds = find_field_wr(par, at->field_inx, at->repl_inx);
+        for (struct field_datum * fd = fds.first; fd != NULL; fd = fd->next) {
+                if (atom_field_verify(at, fp, fd->start, fd->end)) return true;
+        }
+        return false;
+}
diff --git a/lib/paragraph.c b/lib/paragraph.c
index 4f91a2e..0cc2ea7 100644
--- a/lib/paragraph.c
+++ b/lib/paragraph.c
@@ -46,7 +46,8 @@ void para_init(para_parser_t * pp, para_t * para)
                 para->fields = malloc(para->nfields * sizeof *para->fields);
                 if (para->fields == 0) fatal_enomem(0);
                 for (size_t i = 0; i < para->nfields; i++) {
-                        para->fields[i].present = 0;
+                        para->fields[i].first = 0;
+                        para->fields[i].last = 0;
                 }
         } else {
                 para->fields = NULL;
@@ -59,6 +60,14 @@ void para_finalize(para_t * para)
 	para->start = 0;
 	para->end = 0;
 	if (para->fields != 0) {
+                for (size_t i = 0; i < para->nfields; i++) {
+                        struct field_datum *fp = para->fields[i].first;
+                        while (fp != 0) {
+                                struct field_datum *tmp = fp;
+                                fp = fp->next;
+                                free(tmp);
+                        }
+                }
 		free(para->fields);
 	}
         para->maxfields = 0;
@@ -80,7 +89,11 @@ static struct field_data * register_field(para_t * para,
                                        sizeof(para->fields[0]));
                 if (para->fields == 0) fatal_enomem(0);
         }
-        if (inx >= para->nfields) para->nfields = inx + 1;
+        if (inx >= para->nfields) {
+                para->nfields = inx + 1;
+                para->fields[inx].first = 0;
+                para->fields[inx].last = 0;
+        }
         assert(para->nfields <= para->maxfields);
         struct field_data *field_data = &para->fields[inx];
         return field_data;
@@ -94,9 +107,14 @@ redo:
 	para->start = pp->loc;
 	para->line = pp->line;
 	for (size_t i = 0; i < para->nfields; i++) {
-                para->fields[i].present = 0;
-		para->fields[i].start = 0;
-		para->fields[i].end = 0;
+                struct field_datum *fp = para->fields[i].first;
+                while (fp != 0) {
+                        struct field_datum *tmp = fp;
+                        fp = fp->next;
+                        free(tmp);
+                }
+                para->fields[i].first = 0;
+                para->fields[i].last = 0;
 	}
 	if (pp->invalidate_p) {
 		fsaf_invalidate(pp->fp, para->start);
@@ -106,7 +124,7 @@ redo:
 	register size_t line = para->line;
 	register FSAF * fp = pp->fp;
 	size_t field_start = 0;
-	struct field_data * field_data = 0;
+	struct field_datum * field_datum = 0;
 
 #define GETC (c = fsaf_getc(fp, pos++), c == '\n' ? line++ : line)
 #define UNGETC (fsaf_getc(fp, --pos) == '\n' ? --line : line)
@@ -176,17 +194,22 @@ FIELD_NAME:
                 }
                 attr = fieldtrie_lookup(r.b, len);
                 if (attr == NULL) {
-                        field_data = 0;
+                        field_datum = 0;
                 } else {
                         assert(attr->inx < para->nfields);
-                        field_data = &para->fields[attr->inx];
-                }
-                if (field_data != NULL) {
-                        field_data->present = 1;
-                        field_data->start = pos;
-                        field_data->line = line;
-                        field_data->name_start = field_start;
-                        field_data->name_end = pos-1;
+                        struct field_data * fds = &para->fields[attr->inx];
+                        assert((fds->first == 0) == (fds->last == 0));
+                        field_datum = malloc(sizeof *field_datum);
+                        if (field_datum == 0) enomem(0);
+                        field_datum->start = pos;
+                        field_datum->line = line;
+                        field_datum->name_start = field_start;
+                        field_datum->name_end = pos-1;
+                        field_datum->next = 0;
+                        field_datum->prev = fds->last;
+                        if (fds->last != 0) fds->last->next = field_datum;
+                        fds->last = field_datum;
+                        if (fds->first == 0) fds->first = field_datum;
                 }
                 goto BODY;
         }
@@ -198,12 +221,12 @@ FIELD_NAME:
 BODY:
         GETC;
         if (c == -1 || c == '\n') {
-                if (field_data != 0) {
-                        field_data->end = pos-1;
-                        while (field_data->start < field_data->end
-                               && fsaf_getc(fp, field_data->start)
+                if (field_datum != 0) {
+                        field_datum->end = pos-1;
+                        while (field_datum->start < field_datum->end
+                               && fsaf_getc(fp, field_datum->start)
                                == ' ') {
-                                ++field_data->start;
+                                ++field_datum->start;
                         }
                 }
                 goto BODY_NEWLINE;
diff --git a/lib/paragraph.h b/lib/paragraph.h
index a8be095..c76d124 100644
--- a/lib/paragraph.h
+++ b/lib/paragraph.h
@@ -25,11 +25,16 @@
 #include "fsaf.h"
 #include "fieldtrie.h"
 
-struct field_data {
-        _Bool present;
+struct field_datum {
 	size_t line;
 	size_t start, end; /* offsets to the file; [start,end) is the body */
         size_t name_start, name_end; /* as start and end, but for the name */
+        struct field_datum *next, *prev;
+};
+
+struct field_data {
+        struct field_datum *first;
+        struct field_datum *last;
 };
 
 struct paragraph_parser {
@@ -71,49 +76,52 @@ struct fsaf_read_rv get_whole_para(para_t * p)
 }
 
 static inline
-struct field_data * find_field(const para_t *p, size_t fld_inx)
+struct field_data find_field(const para_t *p, size_t fld_inx)
 {
-	struct field_data * fd = fld_inx < p->nfields
-                ? &p->fields[fld_inx]
-                : NULL;
-        if (fd != NULL && !fd->present) fd = NULL;
-        return fd;
+	return fld_inx < p->nfields
+                ? p->fields[fld_inx]
+                : (struct field_data){ NULL, NULL };
 }
 
 static inline
-struct field_data *find_field_wr(const para_t *p,
-                                 size_t fld_inx,
-                                 size_t repl_inx)
+struct field_data find_field_wr(const para_t *p,
+                                size_t fld_inx,
+                                size_t repl_inx)
 {
-	struct field_data * fd = find_field(p, fld_inx);
-        if ((fd == NULL || fd->start == fd->end) && repl_inx != (size_t)(-1)) {
+	struct field_data fd = find_field(p, fld_inx);
+        if (fd.first == NULL && repl_inx != (size_t)(-1)) {
                 fd = find_field(p, repl_inx);
         }
         return fd;
 }
 
+// NOTE: get_field finds the FIRST field of the name!
 static inline
 struct fsaf_read_rv get_field(para_t * p, size_t fld_inx, size_t repl_inx)
 {
-        struct field_data *fd = find_field_wr(p, fld_inx, repl_inx);
-        if (fd == NULL) {
+        struct field_data fds = find_field_wr(p, fld_inx, repl_inx);
+        if (fds.first == NULL) {
                 const struct fsaf_read_rv fail = {
                         .b = NULL,
                         .len = 0
                 };
                 return fail;
         }
+        struct field_datum *fd = fds.first;
 	return fsaf_read(p->common->fp, fd->start, fd->end - fd->start);
 }
 
+// NOTE: get_field_as finds the FIRST field of the name!
 static inline
 char * get_field_as(const para_t * p, size_t fld_inx)
 {
-	struct field_data * fd = find_field(p, fld_inx);
-        if (fd == NULL) return strdup("");
+	struct field_data fds = find_field(p, fld_inx);
+        if (fds.first == NULL) return strdup("");
+        struct field_datum *fd = fds.first;
 	return fsaf_getas(p->common->fp, fd->start, fd->end - fd->start);
 }
 
+
 static inline
 bool para_eof(para_parser_t * para) { return para->eof; }
 
diff --git a/tbl-dctrl/tbl-dctrl.c b/tbl-dctrl/tbl-dctrl.c
index b90a578..848f3f3 100644
--- a/tbl-dctrl/tbl-dctrl.c
+++ b/tbl-dctrl/tbl-dctrl.c
@@ -1,5 +1,5 @@
 /*  dctrl-tools - Debian control file inspection tools
-    Copyright © 2005, 2006, 2007, 2008, 2009, 2010 Antti-Juhani Kaijanaho
+    Copyright © 2005, 2006, 2007, 2008, 2009, 2010, 2011 Antti-Juhani Kaijanaho
 
     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
@@ -418,7 +418,7 @@ int main(int argc, char * argv[])
 			struct paragraph *p = pb.paras[i];
 			assert(p->nfields <= n);
 			for (size_t j = 0; j < p->nfields; j++) {
-                                if (!p->fields[j].present) continue;
+                                if (p->fields[j].first == NULL) continue;
 				struct fsaf_read_rv r = get_field(p, j, -1);
 				size_t len = mbs_len(r.b, r.len,
 						     p->common->fp->fname);
diff --git a/tester.sh b/tester.sh
index 1c35d0b..dfe609e 100644
--- a/tester.sh
+++ b/tester.sh
@@ -46,6 +46,9 @@ for tst in $tests ; do
     if [ ! -r $tst_in ] ; then
         tst_in=/dev/null
     fi
+    if [ ! -r $tst_ero ] ; then
+        tst_ero=/dev/null
+    fi
     if [ ! -r $tst_out ] && [ ! -r $tst_err ] ; then
         echo 1>&2 "neither $tst_out nor $tst_err exists"
         exit 1
@@ -82,10 +85,8 @@ for tst in $tests ; do
         echo "FAILED."
         echo "stdout diff:"
         cat .diffout
-        if [ -r $tst_ero ] ; then
-            echo "stderr diff:"
-            cat .differr
-        fi
+        echo "stderr diff:"
+        cat .differr
         rv=1
     fi
 done
diff --git a/tests/bug652034.in b/tests/bug652034.in
new file mode 100644
index 0000000..287f616
--- /dev/null
+++ b/tests/bug652034.in
@@ -0,0 +1,3 @@
+Foo: a
+Foo: b
+
diff --git a/tests/bug652034.out b/tests/bug652034.out
new file mode 100644
index 0000000..845b68c
--- /dev/null
+++ b/tests/bug652034.out
@@ -0,0 +1,10 @@
+Foo: a
+Foo: b
+
+###
+Foo: a
+Foo: b
+
+###
+Foo: a
+Foo: b
diff --git a/tests/bug652034.sh b/tests/bug652034.sh
new file mode 100644
index 0000000..af5e018
--- /dev/null
+++ b/tests/bug652034.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+set -e
+
+${GREP_DCTRL:-grep-dctrl} -FFoo a bug652034.in
+echo '###'
+${GREP_DCTRL:-grep-dctrl} -FFoo b bug652034.in
+echo '###'
+${GREP_DCTRL:-grep-dctrl} -sFoo -FFoo b bug652034.in

-- 
Debian control file query tools



More information about the Dctrl-tools-devel mailing list