[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 = ¶->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;