summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntti-Juhani Kaijanaho <ajk@debian.org>2011-10-19 21:48:06 +0300
committerAntti-Juhani Kaijanaho <ajk@debian.org>2011-10-19 21:48:06 +0300
commit56a84f637482bcf31f489372b98fa17da4a3c565 (patch)
tree0f2ade0612b4448d7a56f58cfa37fc32685ba887
parentcb69847d307ccf15ef7505129d602046ffe487a8 (diff)
downloaddctrl-tools-56a84f637482bcf31f489372b98fa17da4a3c565.tar.gz
Move atom into its own lib module.
Signed-off-by: Antti-Juhani Kaijanaho <ajk@debian.org>
-rw-r--r--grep-dctrl/grep-dctrl.c5
-rw-r--r--lib/atom.c171
-rw-r--r--lib/atom.h65
-rw-r--r--lib/predicate.c155
-rw-r--r--lib/predicate.h44
5 files changed, 246 insertions, 194 deletions
diff --git a/grep-dctrl/grep-dctrl.c b/grep-dctrl/grep-dctrl.c
index f549e24..ca994fc 100644
--- a/grep-dctrl/grep-dctrl.c
+++ b/grep-dctrl/grep-dctrl.c
@@ -29,6 +29,7 @@
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
+#include "atom.h"
#include "fnutil.h"
#include "fsaf.h"
#include "i18n.h"
@@ -261,11 +262,11 @@ static void finish_atom(struct arguments * args)
for (size_t i = 0; i < args->num_search_fields; i++) {
if (i > 0) atom = clone_atom(args);
atom->field_name = args->search_fields[i];
- predicate_finish_atom(&args->p);
+ atom_finish(atom);
}
// If there are no fields, we have not yet run this...
// ... but it must be done (especially with -r/-e atoms)
- if (args->num_search_fields == 0) predicate_finish_atom(&args->p);
+ if (args->num_search_fields == 0) atom_finish(atom);
args->num_search_fields = 0;
}
diff --git a/lib/atom.c b/lib/atom.c
new file mode 100644
index 0000000..831620b
--- /dev/null
+++ b/lib/atom.c
@@ -0,0 +1,171 @@
+/* dctrl-tools - Debian control file inspection tools
+ Copyright © 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <regex.h>
+#include <stdlib.h>
+#include "atom.h"
+#include "msg.h"
+#include "version.h"
+
+#define RE_PKG_BEGIN "(^| )"
+#define RE_PKG_END "([, \\(]|$)"
+
+void atom_finish(struct atom * atom)
+{
+ char * regex_pat = NULL;
+ int regex_patlen = atom->patlen + strlen(RE_PKG_BEGIN)
+ + strlen(RE_PKG_END) + 1;
+ debug_message("predicate_finish_atom", 0);
+ if (atom->field_name != 0) {
+ char * repl = strchr(atom->field_name, ':');
+ if (repl != NULL) {
+ *repl++ = '\0';
+ atom->repl_inx = fieldtrie_insert(repl)->inx;
+ } else {
+ atom->repl_inx = -1;
+ }
+ atom->field_inx = fieldtrie_insert(atom->field_name)->inx;
+ }
+
+ if (atom->mode == M_REGEX || atom->mode == M_EREGEX) {
+ regex_pat = calloc(1, regex_patlen); /* rely on mem 0-ing */
+ if (regex_pat == 0) fatal_enomem(0);
+ if (atom->whole_pkg)
+ strncat(regex_pat, RE_PKG_BEGIN, strlen(RE_PKG_BEGIN));
+ strncat(regex_pat, atom->pat, atom->patlen);
+ if (atom->whole_pkg)
+ strncat(regex_pat, RE_PKG_END, strlen(RE_PKG_END));
+ debug_message("compiling:", 0);
+ debug_message(regex_pat, 0);
+ int rerr = regcomp(&atom->regex, regex_pat,
+ (atom->mode == M_EREGEX ? REG_EXTENDED : 0)
+ | REG_NOSUB
+ | (atom->ignore_case ? REG_ICASE : 0));
+ free(regex_pat);
+ if (rerr != 0) {
+ char * s;
+ s = get_regerror(rerr, &atom->regex);
+ if (s == 0) fatal_enomem(0);
+ message(L_FATAL, 0, "%s", s);
+ free(s);
+ fail();
+ }
+ }
+
+}
+
+bool atom_verify(struct atom * atom, para_t * para)
+{
+ 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);
+ assert(r.len == len);
+ switch (atom->mode) {
+ case M_EXACT:
+ if (len != atom->patlen) return false;
+ if (atom->ignore_case) {
+ return strncasecmp(atom->pat, r.b, len) == 0;
+ } else {
+ return strncmp(atom->pat, r.b, len) == 0;
+ }
+ case M_SUBSTR: {
+#if 0
+ if (atom->ignore_case) {
+ return strncasestr(r.b, atom->pat, len);
+ } else {
+ return strnstr(r.b, atom->pat, len);
+ }
+#else
+ bool rv;
+ char * s = strndup(r.b, len);
+ if (s == 0) fatal_enomem(0);
+ if (atom->ignore_case) {
+ rv = strcasestr(s, atom->pat) != 0;
+ } else {
+ rv = strstr(s, atom->pat) != 0;
+ }
+ free(s);
+ return rv;
+#endif
+ }
+ case M_REGEX: case M_EREGEX: {
+ char * s = strndup(r.b, len);
+ if (s == 0) fatal_enomem(0);
+ int regex_errcode = regexec(&atom->regex, s, 0, 0, 0);
+ free(s);
+ if (regex_errcode == 0 || regex_errcode == REG_NOMATCH) {
+ return (regex_errcode == 0);
+ }
+ /* Error handling be here. */
+ assert(regex_errcode != 0 && regex_errcode != REG_NOMATCH);
+ s = get_regerror (regex_errcode, &atom->regex);
+ if (s == 0) { enomem (0); return false; }
+ message(L_IMPORTANT, 0, "%s", s);
+ free(s);
+ return false;
+ }
+ 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);
+}
diff --git a/lib/atom.h b/lib/atom.h
new file mode 100644
index 0000000..5674519
--- /dev/null
+++ b/lib/atom.h
@@ -0,0 +1,65 @@
+/* dctrl-tools - Debian control file inspection tools
+ Copyright © 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef GUARD_LIB_ATOM_H
+#define GUARD_LIB_ATOM_H
+
+#include <regex.h>
+#include "paragraph.h"
+#include "util.h"
+
+/* An atomic predicate. */
+struct atom {
+ /* The name of field to which matching is limited. Empty
+ * field_name specifies the whole paragraph (in which case
+ * field_inx is -1. */
+ char const * field_name; size_t field_inx;
+ /* The index to the field whose value is to be used when this
+ * field is empty. */
+ size_t repl_inx;
+ /* Matching mode */
+ enum matching_mode {
+ M_SUBSTR, /* substring matching */
+ M_REGEX, /* POSIX regular expression match */
+ M_EREGEX, /* POSIX extended regular expression matching */
+ M_EXACT, /* exact string match */
+#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;
+ /* The pattern as given on the command line; interpretation
+ * depends on matching mode. Must be null-terminated and
+ * patlen must equal strlen(pat). */
+ char const * pat; size_t patlen;
+ /* A compiled version of pat; valid only when mode is M_REGEX
+ * or M_EREGEX. */
+ regex_t regex;
+ /* Flag: (extended) regex should match whole package names */
+ unsigned whole_pkg;
+};
+
+void atom_finish(struct atom * atom);
+bool atom_verify(struct atom * atom, para_t * para);
+
+#endif /* GUARD_LIB_ATOM_H */
diff --git a/lib/predicate.c b/lib/predicate.c
index 5c213b2..cf78796 100644
--- a/lib/predicate.c
+++ b/lib/predicate.c
@@ -1,5 +1,5 @@
/* dctrl-tools - Debian control file inspection tools
- Copyright © 2003, 2004, 2008, 2010 Antti-Juhani Kaijanaho
+ Copyright © 2003, 2004, 2008, 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
@@ -20,6 +20,7 @@
#include <stdlib.h>
#include <regex.h>
#include <string.h>
+#include "atom.h"
#include "fsaf.h"
#include "msg.h"
#include "util.h"
@@ -27,13 +28,12 @@
#include "strutil.h"
#include "version.h"
-#define RE_PKG_BEGIN "(^| )"
-#define RE_PKG_END "([, \\(]|$)"
-
void init_predicate(struct predicate * p)
{
p->num_atoms = 0;
p->proglen = 0;
+ p->atoms = malloc(MAX_ATOMS * sizeof p->atoms[0]);
+ if (p->atoms == 0) enomem(0);
}
void addinsn(struct predicate * p, int insn)
@@ -46,151 +46,6 @@ void addinsn(struct predicate * p, int insn)
p->program[p->proglen++] = insn;
}
-void predicate_finish_atom(struct predicate * p)
-{
- struct atom * atom = get_current_atom(p);
- char * regex_pat = NULL;
- int regex_patlen = atom->patlen + strlen(RE_PKG_BEGIN)
- + strlen(RE_PKG_END) + 1;
- debug_message("predicate_finish_atom", 0);
- if (atom->field_name != 0) {
- char * repl = strchr(atom->field_name, ':');
- if (repl != NULL) {
- *repl++ = '\0';
- atom->repl_inx = fieldtrie_insert(repl)->inx;
- } else {
- atom->repl_inx = -1;
- }
- atom->field_inx = fieldtrie_insert(atom->field_name)->inx;
- }
-
- if (atom->mode == M_REGEX || atom->mode == M_EREGEX) {
- regex_pat = calloc(1, regex_patlen); /* rely on mem 0-ing */
- if (regex_pat == 0) fatal_enomem(0);
- if (atom->whole_pkg)
- strncat(regex_pat, RE_PKG_BEGIN, strlen(RE_PKG_BEGIN));
- strncat(regex_pat, atom->pat, atom->patlen);
- if (atom->whole_pkg)
- strncat(regex_pat, RE_PKG_END, strlen(RE_PKG_END));
- debug_message("compiling:", 0);
- debug_message(regex_pat, 0);
- int rerr = regcomp(&atom->regex, regex_pat,
- (atom->mode == M_EREGEX ? REG_EXTENDED : 0)
- | REG_NOSUB
- | (atom->ignore_case ? REG_ICASE : 0));
- free(regex_pat);
- if (rerr != 0) {
- char * s;
- s = get_regerror(rerr, &atom->regex);
- if (s == 0) fatal_enomem(0);
- message(L_FATAL, 0, "%s", s);
- free(s);
- fail();
- }
- }
-
-}
-
-static bool verify_atom(struct atom * atom, para_t * para)
-{
- 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);
- assert(r.len == len);
- switch (atom->mode) {
- case M_EXACT:
- if (len != atom->patlen) return false;
- if (atom->ignore_case) {
- return strncasecmp(atom->pat, r.b, len) == 0;
- } else {
- return strncmp(atom->pat, r.b, len) == 0;
- }
- case M_SUBSTR: {
-#if 0
- if (atom->ignore_case) {
- return strncasestr(r.b, atom->pat, len);
- } else {
- return strnstr(r.b, atom->pat, len);
- }
-#else
- bool rv;
- char * s = strndup(r.b, len);
- if (s == 0) fatal_enomem(0);
- if (atom->ignore_case) {
- rv = strcasestr(s, atom->pat) != 0;
- } else {
- rv = strstr(s, atom->pat) != 0;
- }
- free(s);
- return rv;
-#endif
- }
- case M_REGEX: case M_EREGEX: {
- char * s = strndup(r.b, len);
- if (s == 0) fatal_enomem(0);
- int regex_errcode = regexec(&atom->regex, s, 0, 0, 0);
- free(s);
- if (regex_errcode == 0 || regex_errcode == REG_NOMATCH) {
- return (regex_errcode == 0);
- }
- /* Error handling be here. */
- assert(regex_errcode != 0 && regex_errcode != REG_NOMATCH);
- s = get_regerror (regex_errcode, &atom->regex);
- if (s == 0) { enomem (0); return false; }
- message(L_IMPORTANT, 0, "%s", s);
- free(s);
- return false;
- }
- 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);
-}
bool check_predicate(struct predicate * p)
{
@@ -222,7 +77,7 @@ bool does_para_satisfy(struct predicate * p, para_t * para)
/* Verify atoms. */
for (size_t i = 0; i < p->num_atoms; i++) {
- sat_atom[i] = verify_atom(&p->atoms[i], para);
+ sat_atom[i] = atom_verify(&p->atoms[i], para);
}
/* Run the program. */
diff --git a/lib/predicate.h b/lib/predicate.h
index 82ca63a..47d700c 100644
--- a/lib/predicate.h
+++ b/lib/predicate.h
@@ -19,10 +19,6 @@
#ifndef PREDICATE_H
#define PREDICATE_H
-#include <assert.h>
-#include <regex.h>
-#include <stdint.h>
-#include "fieldtrie.h"
#include "paragraph.h"
#define MAX_OPS 4096
@@ -34,41 +30,7 @@
#define I_OR 3 /* --or; 2-1 */
#define I_PUSH(n) (4+(n)) /* push result of nth atomic proposition */
-/* An atomic predicate. */
-struct atom {
- /* The name of field to which matching is limited. Empty
- * field_name specifies the whole paragraph (in which case
- * field_inx is -1. */
- char const * field_name; size_t field_inx;
- /* The index to the field whose value is to be used when this
- * field is empty. */
- size_t repl_inx;
- /* Matching mode */
- enum matching_mode {
- M_SUBSTR, /* substring matching */
- M_REGEX, /* POSIX regular expression match */
- M_EREGEX, /* POSIX extended regular expression matching */
- M_EXACT, /* exact string match */
-#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;
- /* The pattern as given on the command line; interpretation
- * depends on matching mode. Must be null-terminated and
- * patlen must equal strlen(pat). */
- char const * pat; size_t patlen;
- /* A compiled version of pat; valid only when mode is M_REGEX
- * or M_EREGEX. */
- regex_t regex;
- /* Flag: (extended) regex should match whole package names */
- unsigned whole_pkg;
-};
+struct atom;
/* A predicate is represented as a set of atomic predicates and a
* program - a sequence of stack-based "bytecode" instructions - that
@@ -81,7 +43,7 @@ struct predicate {
/* The program */
int program[MAX_OPS];
/* The atomic predicates */
- struct atom atoms[MAX_ATOMS];
+ struct atom *atoms;
};
void init_predicate(struct predicate * p);
@@ -93,8 +55,6 @@ struct atom * get_current_atom(struct predicate * p)
return &p->atoms[p->num_atoms-1];
}
-void predicate_finish_atom(struct predicate *);
-
void addinsn(struct predicate * p, int insn);
bool does_para_satisfy(struct predicate * p, para_t *);