diff options
author | Antti-Juhani Kaijanaho <ajk@debian.org> | 2011-10-19 21:48:06 +0300 |
---|---|---|
committer | Antti-Juhani Kaijanaho <ajk@debian.org> | 2011-10-19 21:48:06 +0300 |
commit | 56a84f637482bcf31f489372b98fa17da4a3c565 (patch) | |
tree | 0f2ade0612b4448d7a56f58cfa37fc32685ba887 | |
parent | cb69847d307ccf15ef7505129d602046ffe487a8 (diff) | |
download | dctrl-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.c | 5 | ||||
-rw-r--r-- | lib/atom.c | 171 | ||||
-rw-r--r-- | lib/atom.h | 65 | ||||
-rw-r--r-- | lib/predicate.c | 155 | ||||
-rw-r--r-- | lib/predicate.h | 44 |
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 *); |