[Dctrl-tools-devel] CVS dctrl-tools

CVS User ajk ajk@haydn.debian.org
Wed, 08 Jun 2005 16:31:24 +0000


Update of /cvsroot/dctrl-tools/dctrl-tools
In directory haydn:/tmp/cvs-serv12348

Modified Files:
      Tag: r_2_6_maint
	Makefile grep-dctrl.1.cp grep-dctrl.c paragraph.c paragraph.h 
	predicate.c predicate.h 
Log Message:
Implement vesion number comparison.

--- /cvsroot/dctrl-tools/dctrl-tools/Makefile	2004/07/12 15:29:00	1.17.4.4
+++ /cvsroot/dctrl-tools/dctrl-tools/Makefile	2005/06/08 16:31:24	1.17.4.5
@@ -13,7 +13,7 @@
 #CFLAGS += -pg
 #LDFLAGS += -pg
 
-LDLIBS = -lgmp
+#LDLIBS = -lgmp
 
 obj = grep-dctrl.o misc.o msg.o predicate.o util.o fsaf.o paragraph.o \
       fieldtrie.o rc.o strutil.o getaline.o fnutil.o
--- /cvsroot/dctrl-tools/dctrl-tools/grep-dctrl.1.cp	2005/06/07 18:28:37	1.12.4.4
+++ /cvsroot/dctrl-tools/dctrl-tools/grep-dctrl.1.cp	2005/06/08 16:31:24	1.12.4.5
@@ -1,4 +1,4 @@
-.TH GREP-DCTRL 1 2005-04-08 "Debian Project" "Debian user's manual"
+.TH GREP-DCTRL 1 2005-06-08 "Debian Project" "Debian user's manual"
 \" Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
 \"               Antti-Juhani Kaijanaho <gaia@iki.fi>
 \"      This program is free software; you can redistribute it and/or modify
@@ -136,40 +136,35 @@
 Do an exact match (as opposed to a substring match) in the current
 atomic predicate.
 .IP "\-\-eq"
-Use numeric equality in matching.  The pattern must be an integer
-literal.  Any paragraphs where the field to be searched in does not
-parse as an integer literal are regarded as not matching.  Note that
-using numeric comparison when looking at full paragraphs does not make
-sense.
-.B WARNING!  The semantics of numeric comparison will change in the future.
+Do an equality comparison under the Debian version number system.  If
+the pattern or the field to be searched in is not a valid Debian
+version number, the paragraph is regarded as not matching.  As a
+special case, this is capable of comparing simple nonnegative integers
+for equality.
 .IP "\-\-lt"
-Use numeric strictly-less-than comparison in matching.  The pattern
-must be an integer literal.  Any paragraphs where the field to be
-searched in does not parse as an integer literal are regarded as not
-matching.  Note that using numeric comparison when looking at full
-paragraphs does not make sense.
-.B WARNING!  The semantics of numeric comparison will change in the future.
+Do an strictly-less-than comparison under the Debian version number
+system.  If the pattern or the field to be searched in is not a valid
+Debian version number, the paragraph is regarded as not matching.  As
+a special case, this is capable of comparing simple nonnegative
+integers.
 .IP "\-\-le"
-Use numeric less-than-or-equal comparison in matching.  The pattern
-must be an integer literal.  Any paragraphs where the field to be
-searched in does not parse as an integer literal are regarded as not
-matching.  Note that using numeric comparison when looking at full
-paragraphs does not make sense.
-.B WARNING!  The semantics of numeric comparison will change in the future.
+Do an less-than-or-equal comparison under the Debian version number
+system.  If the pattern or the field to be searched in is not a valid
+Debian version number, the paragraph is regarded as not matching.  As
+a special case, this is capable of comparing simple nonnegative
+integers.
 .IP "\-\-gt"
-Use numeric strictly-greater-than comparison in matching.  The pattern
-must be an integer literal.  Any paragraphs where the field to be
-searched in does not parse as an integer literal are regarded as not
-matching.  Note that using numeric comparison when looking at full
-paragraphs does not make sense.
-.B WARNING!  The semantics of numeric comparison will change in the future.
+Do an strictly-greater-than comparison under the Debian version number
+system.  If the pattern or the field to be searched in is not a valid
+Debian version number, the paragraph is regarded as not matching.  As
+a special case, this is capable of comparing simple nonnegative
+integers.
 .IP "\-\-ge"
-Use numeric greater-than-or-equal comparison in matching.  The pattern
-must be an integer literal.  Any paragraphs where the field to be
-searched in does not parse as an integer literal are regarded as not
-matching.  Note that using numeric comparison when looking at full
-paragraphs does not make sense.
-.B WARNING!  The semantics of numeric comparison will change in the future.
+Do an greater-than-or-equal comparison under the Debian version number
+system.  If the pattern or the field to be searched in is not a valid
+Debian version number, the paragraph is regarded as not matching.  As
+a special case, this is capable of comparing simple nonnegative
+integers.
 .SS Predicate connectives
 .IP "\-!, \-\-not, !"
 Negate the following predicate.
--- /cvsroot/dctrl-tools/dctrl-tools/grep-dctrl.c	2005/03/26 04:13:05	1.26.4.3
+++ /cvsroot/dctrl-tools/dctrl-tools/grep-dctrl.c	2005/06/08 16:31:24	1.26.4.4
@@ -55,10 +55,6 @@
 #define OPT_GT 262
 #define OPT_GE 263
 
-static bool num_comp_warning_shown = false;
-static char const num_comp_warning [] = 
-"%s: WARNING: the semantics of numeric comparison will change in the future\n";
-
 #undef BANNER
 
 #ifdef BANNER
@@ -123,11 +119,11 @@
 	{ "and",	    'a', 0,		    0, N_("Conjunct predicates.") },
 	{ "or",		    'o', 0,		    0, N_("Disjunct predicates.") },
 	{ "not",	    '!', 0,		    0, N_("Negate the following predicate.") },
-	{ "eq",		    OPT_EQ, 0,		    0, N_("Test for numerical equality.") },
-	{ "lt",		    OPT_LT, 0,		    0, N_("Numerical test: <.") },
-	{ "le",		    OPT_LE, 0,		    0, N_("Numerical test: <=.") },
-	{ "gt",		    OPT_GT, 0,		    0, N_("Numerical test: >.") },
-	{ "ge",		    OPT_GE, 0,		    0, N_("Numerical test: >=.") },
+	{ "eq",		    OPT_EQ, 0,		    0, N_("Test for version number equality.") },
+	{ "lt",		    OPT_LT, 0,		    0, N_("Version number comparison: <.") },
+	{ "le",		    OPT_LE, 0,		    0, N_("Version number comparison: <=.") },
+	{ "gt",		    OPT_GT, 0,		    0, N_("Version number comparison: >.") },
+	{ "ge",		    OPT_GE, 0,		    0, N_("Version number comparison: >=.") },
 	{ "debug-optparse", OPT_OPTPARSE, 0,	    0, N_("Debug option parsing.") },
 	{ "quiet",	    'q', 0,		    0, N_("Do no output to stdout.") },
 	{ "silent",	    OPT_SILENT, 0,	    0, N_("Do no output to stdout.") },
@@ -461,43 +457,23 @@
 		break;
 	case OPT_EQ:
 		debug_message("parse_opt: eq", 0);
-		set_mode(M_NUM_EQ);
-		if (!num_comp_warning_shown && do_msg(L_IMPORTANT)) {
-			fprintf(stderr, num_comp_warning, get_progname());
-			num_comp_warning_shown = true;
-		}
+		set_mode(M_VER_EQ);
 		break;
 	case OPT_LT:
 		debug_message("parse_opt: lt", 0);
-		set_mode(M_NUM_LT);
-		if (!num_comp_warning_shown && do_msg(L_IMPORTANT)) {
-			fprintf(stderr, num_comp_warning, get_progname());
-			num_comp_warning_shown = true;
-		}
+		set_mode(M_VER_LT);
 		break;
 	case OPT_LE:
 		debug_message("parse_opt: le", 0);
-		set_mode(M_NUM_LE);
-		if (!num_comp_warning_shown && do_msg(L_IMPORTANT)) {
-			fprintf(stderr, num_comp_warning, get_progname());
-			num_comp_warning_shown = true;
-		}
+		set_mode(M_VER_LE);
 		break;
 	case OPT_GT:
 		debug_message("parse_opt: gt", 0);
-		set_mode(M_NUM_GT);
-		if (!num_comp_warning_shown && do_msg(L_IMPORTANT)) {
-			fprintf(stderr, num_comp_warning, get_progname());
-			num_comp_warning_shown = true;
-		}
+		set_mode(M_VER_GT);
 		break;
 	case OPT_GE:
 		debug_message("parse_opt: ge", 0);
-		set_mode(M_NUM_GE);
-		if (!num_comp_warning_shown && do_msg(L_IMPORTANT)) {
-			fprintf(stderr, num_comp_warning, get_progname());
-			num_comp_warning_shown = true;
-		}
+		set_mode(M_VER_GE);
 		break;
 	case 'i':
 		debug_message("parse_opt: i", 0);
--- /cvsroot/dctrl-tools/dctrl-tools/paragraph.c	2004/07/04 17:40:33	1.11
+++ /cvsroot/dctrl-tools/dctrl-tools/paragraph.c	2005/06/08 16:31:24	1.11.4.1
@@ -16,30 +16,11 @@
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <gmp.h>
 #include <string.h>
 #include "msg.h"
 #include "paragraph.h"
 #include "strutil.h"
 
-static
-void parse_int(FSAF * fp, struct field_data * fd)
-{
-	const size_t len = fd->end - fd->start;
-	struct fsaf_read_rv rd = fsaf_read(fp, fd->start, len);
-	assert(rd.len == len);
-	fd->int_valid = false;
-	char * s = strndup(rd.b, len);
-	if (s == 0) fatal_enomem(0);
-	int r = mpz_set_str(fd->parsed, s, 10);
-	free(s);
-	fd->int_valid = (r == 0);
-	if (!fd->int_valid) {
-		message(L_INFORMATIONAL, _("parse of a numeric field failed"),
-			0);
-	}
-}
-
 void para_init(para_t * para, FSAF * fp, fieldtrie_t * trie)
 {
 	para->fp = fp;
@@ -47,9 +28,6 @@
 	para->start = 0;
 	para->end = 0;
 	para->eof = false;
-	for (size_t i = 0; i < MAX_FIELDS; i++) {
-		mpz_init(para->fields[i].parsed);
-	}
 	para_parse_next(para);
 }
 
@@ -60,7 +38,6 @@
 	for (size_t i = 0; i < fieldtrie_count(para->trie); i++) {
 		para->fields[i].start = 0;
 		para->fields[i].end = 0;
-		para->fields[i].int_valid = 0;
 	}
 	fsaf_invalidate(para->fp, para->start);
 	register enum { START, FIELD_NAME, BODY, BODY_NEWLINE,
@@ -130,7 +107,6 @@
 					       && fsaf_getc(fp, field_data->start) == ' ') {
 						++field_data->start;
 					}
-					parse_int(fp, field_data);
 				}
 				state = BODY_NEWLINE;
 				break;
--- /cvsroot/dctrl-tools/dctrl-tools/paragraph.h	2004/07/04 17:40:33	1.6
+++ /cvsroot/dctrl-tools/dctrl-tools/paragraph.h	2005/06/08 16:31:24	1.6.4.1
@@ -21,15 +21,12 @@
 
 #define MAX_FIELDS 100
 
-#include <gmp.h>
 #include <stddef.h>
 #include "fsaf.h"
 #include "fieldtrie.h"
 
 struct field_data {
 	size_t start, end; /* offsets to the file; [start,end) is the body */
-	bool int_valid;    /* whether .parsed is valid */
-	mpz_t parsed;   /* a parsed value for the data */
 };
 
 struct paragraph_private {
--- /cvsroot/dctrl-tools/dctrl-tools/predicate.c	2004/07/04 17:40:33	1.13
+++ /cvsroot/dctrl-tools/dctrl-tools/predicate.c	2005/06/08 16:31:24	1.13.4.1
@@ -14,10 +14,37 @@
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+*/
+
+// Marked portions of this file are covered by the following
+// copyright:
+/*
+ * libdpkg - Debian packaging suite library routines
+ * vercmp.c - comparison of version numbers
+ * utils.c - Helper functions for dpkg
+ *
+ * Copyright (C) 1995 Ian Jackson <ian@chiark.greenend.org.uk>
+ * Copyright (C) 2001 Wichert Akkerman <wakkerma@debian.org>
+ *
+ * This 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,
+ * or (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with dpkg; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+
 #include <ctype.h>
-#include <gmp.h>
 #include <stdlib.h>
 #include <regex.h>
 #include <string.h>
@@ -47,8 +74,8 @@
 void predicate_finish_atom(struct predicate * p)
 {
 	struct atom * atom =  get_current_atom(p);
-	bool numeric = M_FIRST_NUMERIC <= atom->mode
-		&& atom->mode <= M_LAST_NUMERIC;
+	bool numeric = M_FIRST_VERSION <= atom->mode
+		&& atom->mode <= M_LAST_VERSION;
 	debug_message("predicate_finish_atom", 0);
 	if (atom->field_name != 0) {
 		struct field_attr fa = { .numeric = numeric };
@@ -73,30 +100,138 @@
 		}
 	}
 
-	if (numeric) {
-		int r = mpz_init_set_str(atom->intpat, atom->pat, 10);
-		if (r != 0) {
-			message(L_FATAL, _("invalid numeric pattern"), 0);
-			fail();
+}
+
+/* <<<<<<< originally from dpkg >>>>>>> */
+
+struct versionrevision {
+  unsigned long epoch;
+  char *version;
+  char *revision;
+};  
+
+/* Reimplementation of the standard ctype.h is* functions. Since gettext
+ * has overloaded the meaning of LC_CTYPE we can't use that to force C
+ * locale, so use these cis* functions instead.
+ */
+static int cisdigit(int c) {
+        return (c>='0') && (c<='9');
+}
+
+static int cisalpha(int c) {
+        return ((c>='a') && (c<='z')) || ((c>='A') && (c<='Z'));
+}
+
+/* assume ascii; warning: evaluates x multiple times! */
+#define order(x) ((x) == '~' ? -1 \
+		: cisdigit((x)) ? 0 \
+		: !(x) ? 0 \
+		: cisalpha((x)) ? (x) \
+		: (x) + 256)
+
+static int verrevcmp(const char *val, const char *ref) {
+  if (!val) val= "";
+  if (!ref) ref= "";
+
+  while (*val || *ref) {
+    int first_diff= 0;
+
+    while ( (*val && !cisdigit(*val)) || (*ref && !cisdigit(*ref)) ) {
+      int vc= order(*val), rc= order(*ref);
+      if (vc != rc) return vc - rc;
+      val++; ref++;
+    }
+
+    while ( *val == '0' ) val++;
+    while ( *ref == '0' ) ref++;
+    while (cisdigit(*val) && cisdigit(*ref)) {
+      if (!first_diff) first_diff= *val - *ref;
+      val++; ref++;
+    }
+    if (cisdigit(*val)) return 1;
+    if (cisdigit(*ref)) return -1;
+    if (first_diff) return first_diff;
+  }
+  return 0;
+}
+
+static int versioncompare(const struct versionrevision *version,
+			  const struct versionrevision *refversion) {
+  int r;
+
+  if (version->epoch > refversion->epoch) return 1;
+  if (version->epoch < refversion->epoch) return -1;
+  r= verrevcmp(version->version,refversion->version);  if (r) return r;
+  return verrevcmp(version->revision,refversion->revision);
+}
+
+/* <<<<<<< END OF originally from dpkg >>>>>>> */
+
+/* warning: modifies ver by adding nul chars; return pointers point
+ * inside ver. */
+static bool parse_version(struct versionrevision *rv, char *ver, size_t len)
+{
+	rv->version = strchr(ver, ':');
+	if (rv->version == NULL) {
+		rv->version = ver;
+	} else {
+		*(rv->version++) = '\0';
+	}
+	rv->revision = strrchr(ver, '-');
+
+	if (rv->revision == NULL) {
+		rv->revision = ver + len;
+	} else {
+		*(rv->revision++) = '\0';
+	}
+	
+	if (rv->version != ver) {
+		rv->epoch = 0;
+		for (char *p = ver; *p != '\0'; p++) {
+			if (!('0' <= *p && *p <= '9')) return false;
+			rv->epoch = rv->epoch * 10 + (*p - '0');
 		}
+	} else {
+		rv->epoch = 0;
+	}
+
+	for (char *p = rv->version; *p != '\0'; p++) {
+		if (('a' <= *p && *p <= 'z') ||
+		    ('A' <= *p && *p <= 'Z') ||
+		    ('0' <= *p && *p <= '9') ||
+		    *p == '.' ||
+		    *p == '-' ||
+		    *p == '+' ||
+		    *p == ':' ||
+		    *p == '~') continue;
+		return false;
 	}
+
+	for (char *p = rv->revision; *p != '\0'; p++) {
+		if (('a' <= *p && *p <= 'z') ||
+		    ('A' <= *p && *p <= 'Z') ||
+		    ('0' <= *p && *p <= '9') ||
+		    *p == '.' ||
+		    *p == '+' ||
+		    *p == '~') continue;
+		return false;
+	}
+
+	return true;
 }
 
 static bool verify_atom(struct atom * atom, para_t * para)
 {
 	size_t start, end;
-	mpz_t * intval;
 	if (atom->field_inx == -1) {
 		/* Take the full paragraph */
 		start = para->start;
 		end = para->end;
-		intval = 0;
 	} else {
 		/* Take the field */
 		struct field_data * fd = &para->fields[atom->field_inx];
 		start = fd->start;
 		end = fd->end;
-		intval = fd->int_valid ? &fd->parsed : 0;
 	}
 	size_t len = end - start;
 	struct fsaf_read_rv r = fsaf_read(para->fp, start, len);
@@ -145,21 +280,38 @@
 		free(s);
 		return false;
 	}
-	case M_NUM_EQ:
-		if (*intval == 0) return false;
-		return mpz_cmp(atom->intpat, *intval) == 0;
-	case M_NUM_LT:
-		if (*intval == 0) return false;
-		return mpz_cmp(atom->intpat, *intval) > 0;
-	case M_NUM_LE:
-		if (*intval == 0) return false;
-		return mpz_cmp(atom->intpat, *intval) >= 0;
-	case M_NUM_GT:
-		if (*intval == 0) return false;
-		return mpz_cmp(atom->intpat, *intval) < 0;
-	case M_NUM_GE:
-		if (*intval == 0) return false;
-		return mpz_cmp(atom->intpat, *intval) <= 0;
+	case M_VER_EQ:case M_VER_LT:case M_VER_LE:case M_VER_GT:case M_VER_GE:
+		;
+		char *pats = strndup(atom->pat, atom->patlen);
+		char *cands = strndup(r.b, len);
+		struct versionrevision pat, cand;
+		if (!parse_version(&pat, pats, atom->patlen)) {
+			free(pats);
+			free(cands);
+			return false;
+		}
+		if (!parse_version(&cand, cands, len)) {
+			free(pats);
+			free(cands);
+			return false;
+		}
+		int res = versioncompare(&cand, &pat);
+		free(pats);
+		free(cands);
+		switch (atom->mode) {
+		case M_VER_EQ:
+			return res == 0;
+		case M_VER_LT:
+			return res < 0;
+		case M_VER_LE:
+			return res <= 0;
+		case M_VER_GT:
+			return res > 0;
+		case M_VER_GE:
+			return res >= 0;
+		default:
+			assert(0);
+		}
 	}
 	assert(0);
 }
--- /cvsroot/dctrl-tools/dctrl-tools/predicate.h	2004/07/04 17:40:33	1.8
+++ /cvsroot/dctrl-tools/dctrl-tools/predicate.h	2005/06/08 16:31:24	1.8.4.1
@@ -20,7 +20,6 @@
 #define PREDICATE_H
 
 #include <assert.h>
-#include <gmp.h>
 #include <regex.h>
 #include <stdint.h>
 #include "fieldtrie.h"
@@ -47,13 +46,13 @@
 		M_REGEX, /* POSIX regular expression match */
 		M_EREGEX, /* POSIX extended regular expression matching */
 		M_EXACT, /* exact string match */
-#define M_FIRST_NUMERIC M_NUM_EQ
-		M_NUM_EQ, /* numeric equality comparison */
-		M_NUM_LT, /* numeric < */
-		M_NUM_LE, /* numeric <= */
-		M_NUM_GT, /* numeric > */
-		M_NUM_GE, /* numeric >= */
-#define M_LAST_NUMERIC M_NUM_GE
+#define M_FIRST_VERSION M_VER_EQ
+		M_VER_EQ, /* numeric equality comparison */
+		M_VER_LT, /* numeric < */
+		M_VER_LE, /* numeric <= */
+		M_VER_GT, /* numeric > */
+		M_VER_GE, /* numeric >= */
+#define M_LAST_VERSION M_VER_GE
 	} mode;
 	/* Flag: should matching ignore case */
 	unsigned ignore_case;
@@ -61,8 +60,6 @@
 	 * depends on matching mode. Must be null-terminated and
 	 * patlen must equal strlen(pat).  */
 	char const * pat; size_t patlen;
-	/* A parsed value of an integer pattern */
-	mpz_t intpat;
 	/* A compiled version of pat; valid only when mode is M_REGEX
 	 * or M_EREGEX.  */
 	regex_t regex;