From: Philipp Takacs Date: Sun, 2 Apr 2017 21:15:19 +0000 (+0200) Subject: complete rewrite of pick X-Git-Tag: mmh-0.4~10^2~8 X-Git-Url: http://git.marmaro.de/?p=mmh;a=commitdiff_plain;h=e0bd1185d5a6a854a04f3c567195cfe96df112d0;hp=641a9d953e86685f9ca2f3da72e9a94e5bcfd69e complete rewrite of pick this make the code cleaner and removes the regex implementation. The mail itself is now read by pick and the match functions only check if the field match. --- diff --git a/uip/pick.c b/uip/pick.c index 3e250a7..1c195be 100644 --- a/uip/pick.c +++ b/uip/pick.c @@ -9,11 +9,13 @@ #include #include #include +#include +#include #include #include #include -#include -#include +#include +#include #ifdef HAVE_SYS_TIME_H # include @@ -78,11 +80,22 @@ static struct swit switches[] = { char *version=VERSION; +struct nexus { + boolean (*action)(struct field *, int, void *); + void (*free)(struct nexus **); + void (*debug)(void *, size_t); + + void *data; +}; + +static struct nexus *head; +static boolean body = FALSE; + /* ** static prototypes */ static int pcompile(char **, char *); -static int pmatches(FILE *, int, long, long); +static int pmatches(FILE *, int); static int listsw = -1; @@ -293,7 +306,7 @@ main(int argc, char **argv) if (is_selected(mp, msgnum)) { if ((fp = fopen(cp = m_name(msgnum), "r")) == NULL) admonish(cp, "unable to read message"); - if (fp && pmatches(fp, msgnum, 0L, 0L)) { + if (fp && pmatches(fp, msgnum)) { if (msgnum < lo) lo = msgnum; if (msgnum > hi) @@ -311,6 +324,8 @@ main(int argc, char **argv) } } + head->free(&head); + mp->lowsel = lo; mp->hghsel = hi; @@ -434,47 +449,6 @@ static struct swit parswit[] = { #define LBSIZE 1024 #define ESIZE 1024 - -static char linebuf[LBSIZE + 1]; -static char decoded_linebuf[LBSIZE + 1]; - -/* the magic array for case-independence */ -static char cc[] = { - 0000,0001,0002,0003,0004,0005,0006,0007, - 0010,0011,0012,0013,0014,0015,0016,0017, - 0020,0021,0022,0023,0024,0025,0026,0027, - 0030,0031,0032,0033,0034,0035,0036,0037, - 0040,0041,0042,0043,0044,0045,0046,0047, - 0050,0051,0052,0053,0054,0055,0056,0057, - 0060,0061,0062,0063,0064,0065,0066,0067, - 0070,0071,0072,0073,0074,0075,0076,0077, - 0100,0141,0142,0143,0144,0145,0146,0147, - 0150,0151,0152,0153,0154,0155,0156,0157, - 0160,0161,0162,0163,0164,0165,0166,0167, - 0170,0171,0172,0133,0134,0135,0136,0137, - 0140,0141,0142,0143,0144,0145,0146,0147, - 0150,0151,0152,0153,0154,0155,0156,0157, - 0160,0161,0162,0163,0164,0165,0166,0167, - 0170,0171,0172,0173,0174,0175,0176,0177, - - 0200,0201,0202,0203,0204,0205,0206,0207, - 0210,0211,0212,0213,0214,0215,0216,0217, - 0220,0221,0222,0223,0224,0225,0226,0227, - 0230,0231,0232,0233,0234,0235,0236,0237, - 0240,0241,0242,0243,0244,0245,0246,0247, - 0250,0251,0252,0253,0254,0255,0256,0257, - 0260,0261,0262,0263,0264,0265,0266,0267, - 0270,0271,0272,0273,0274,0275,0276,0277, - 0300,0301,0302,0303,0304,0305,0306,0307, - 0310,0311,0312,0313,0314,0315,0316,0317, - 0320,0321,0322,0323,0324,0325,0326,0327, - 0330,0331,0332,0333,0334,0335,0336,0337, - 0340,0341,0342,0343,0344,0345,0346,0347, - 0350,0351,0352,0353,0354,0355,0356,0357, - 0360,0361,0362,0363,0364,0365,0366,0367, - 0370,0371,0372,0373,0374,0375,0376,0377, -}; - /* ** DEFINITIONS FOR NEXUS */ @@ -484,44 +458,36 @@ static char cc[] = { #define padvise if (!talked++) advise -struct nexus { - int (*n_action)(); - - union { - /* for {OR,AND,NOT}action */ - struct { - struct nexus *un_L_child; - struct nexus *un_R_child; - } st1; - - /* for GREPaction */ - struct { - int un_header; - int un_circf; - char un_expbuf[ESIZE]; - char *un_patbuf; - } st2; - - /* for TWSaction */ - struct { - char *un_datef; - int un_after; - struct tws un_tws; - } st3; - } un; + +enum nexus_type { + TYPE_GREP, + TYPE_DATE, + TYPE_OR, + TYPE_AND, + TYPE_NOT }; -#define n_L_child un.st1.un_L_child -#define n_R_child un.st1.un_R_child +struct bin_data { + struct nexus *left; + struct nexus *right; + enum nexus_type type; + int oldmsgnum; + boolean leftmatch; + boolean rightmatch; + boolean match; +}; -#define n_header un.st2.un_header -#define n_circf un.st2.un_circf -#define n_expbuf un.st2.un_expbuf -#define n_patbuf un.st2.un_patbuf +struct date_data { + char *datef; + boolean after; + struct tws tws; +}; -#define n_datef un.st3.un_datef -#define n_after un.st3.un_after -#define n_tws un.st3.un_tws +struct grep_data { + char *header; + char *pattern; + regex_t *preg; +}; static int talked; static int pdebug = 0; @@ -529,7 +495,6 @@ static int pdebug = 0; static char *datesw; static char **argp; -static struct nexus *head; /* ** prototypes for date routines @@ -540,24 +505,27 @@ static struct tws *tws_special(char *); /* ** static prototypes */ -static void PRaction(struct nexus *, int); -static int gcompile(struct nexus *, char *); -static int advance(char *, char *); -static int cclass(unsigned char *, int, int); +static int gcompile(struct grep_data *, const char *); static int tcompile(char *, struct tws *, int); static struct nexus *parse(void); static struct nexus *nexp1(void); static struct nexus *nexp2(void); static struct nexus *nexp3(void); -static struct nexus *newnexus(int (*)()); +static struct nexus *newnexus(enum nexus_type); -static int ORaction(); -static int ANDaction(); -static int NOTaction(); -static int GREPaction(); -static int TWSaction(); +static boolean BINaction(struct field *, int, void *); +static boolean NOTaction(struct field *, int, void *); +static boolean GREPaction(struct field *, int, void *); +static boolean DATEaction(struct field *, int, void *); +static void BINfree(struct nexus **); +static void GREPfree(struct nexus **); +static void DATEfree(struct nexus **); + +static void BINdebug(void *, size_t); +static void GREPdebug(void *, size_t); +static void DATEdebug(void *, size_t); static int pcompile(char **vec, char *date) @@ -589,6 +557,7 @@ parse(void) { char *cp; struct nexus *n, *o; + struct bin_data *bin; if ((n = nexp1()) == NULL || (cp = nxtarg()) == NULL) return n; @@ -611,9 +580,10 @@ parse(void) return NULL; case PROR: - o = newnexus(ORaction); - o->n_L_child = n; - if ((o->n_R_child = parse())) + o = newnexus(TYPE_OR); + bin = o->data; + bin->left = n; + if ((bin->right = parse())) return o; padvise(NULL, "missing disjunctive"); return NULL; @@ -630,6 +600,7 @@ nexp1(void) { char *cp; struct nexus *n, *o; + struct bin_data *bin; if ((n = nexp2()) == NULL || (cp = nxtarg()) == NULL) return n; @@ -652,9 +623,10 @@ nexp1(void) return NULL; case PRAND: - o = newnexus(ANDaction); - o->n_L_child = n; - if ((o->n_R_child = nexp1())) + o = newnexus(TYPE_AND); + bin = o->data; + bin->left = n; + if ((bin->right = nexp1())) return o; padvise(NULL, "missing conjunctive"); return NULL; @@ -672,6 +644,7 @@ nexp2(void) { char *cp; struct nexus *n; + struct bin_data *bin; if ((cp = nxtarg()) == NULL) return NULL; @@ -694,8 +667,9 @@ nexp2(void) return NULL; case PRNOT: - n = newnexus(NOTaction); - if ((n->n_L_child = nexp3())) + n = newnexus(TYPE_NOT); + bin = n->data; + if ((bin->left = nexp3())) return n; padvise(NULL, "missing negation"); return NULL; @@ -714,6 +688,8 @@ nexp3(void) char *cp, *dp; char buffer[BUFSIZ], temp[64]; struct nexus *n; + struct grep_data *gdata; + struct date_data *twsd; if ((cp = nxtarg()) == NULL) return NULL; @@ -768,26 +744,28 @@ header: ; padvise(NULL, "missing argument to %s", argp[-2]); return NULL; } - n = newnexus(GREPaction); - n->n_header = 1; - snprintf(buffer, sizeof(buffer), "^%s[ \t]*:.*%s", dp, cp); + n = newnexus(TYPE_GREP); + gdata = n->data; + gdata->header = mh_xstrdup(dp); + snprintf(buffer, sizeof(buffer), "%s", cp); dp = buffer; goto pattern; case PRSRCH: - n = newnexus(GREPaction); - n->n_header = 0; + n = newnexus(TYPE_GREP); + gdata = n->data; + gdata->header = NULL; + body = TRUE; if (!(cp = nxtarg())) { /* allow -xyz arguments */ padvise(NULL, "missing argument to %s", argp[-2]); return NULL; } dp = cp; pattern: ; - if (!gcompile(n, dp)) { - padvise(NULL, "pattern error in %s %s", argp[-2], cp); + if (!gcompile(gdata, dp)) { + padvise("regcomp", "pattern error in %s %s", argp[-2], cp); return NULL; } - n->n_patbuf = mh_xstrdup(dp); return n; case PROTHR: @@ -808,9 +786,10 @@ pattern: ; padvise(NULL, "missing argument to %s", argp[-2]); return NULL; } - n = newnexus(TWSaction); - n->n_datef = datesw; - if (!tcompile(cp, &n->n_tws, n->n_after = i == PRAFTR)) { + n = newnexus(TYPE_DATE); + twsd = n->data; + twsd->datef = datesw; + if (!tcompile(cp, &twsd->tws, twsd->after = i == PRAFTR)) { padvise(NULL, "unable to parse %s %s", argp[-2], cp); return NULL; } @@ -820,386 +799,287 @@ pattern: ; static struct nexus * -newnexus(int (*action)()) +newnexus(enum nexus_type t) { - struct nexus *p; - - p = mh_xcalloc(1, sizeof *p); + struct nexus *p = NULL; + struct bin_data *bin; + + p = mh_xcalloc(1, sizeof(struct nexus)); + + switch (t) { + case TYPE_NOT: + p->action = NOTaction; + p->debug = BINdebug; + p->free = BINfree; + p->data = bin = mh_xcalloc(1, sizeof(struct bin_data)); + bin->type = t; + break; + case TYPE_AND: + case TYPE_OR: + p->action = BINaction; + p->debug = BINdebug; + p->free = BINfree; + p->data = bin = mh_xcalloc(1, sizeof(struct bin_data)); + bin->type = t; + break; + case TYPE_GREP: + p->action = GREPaction; + p->debug = GREPdebug; + p->free = GREPfree; + p->data = mh_xcalloc(1, sizeof(struct grep_data)); + break; + case TYPE_DATE: + p->action = DATEaction; + p->debug = DATEdebug; + p->free = DATEfree; + p->data = mh_xcalloc(1, sizeof(struct date_data)); + break; + default: + adios(EX_SOFTWARE, NULL, "unknown nexus type %d", t); + } - p->n_action = action; return p; -} - -#define args(a) a, fp, msgnum, start, stop -#define params args(n) -#define plist \ - struct nexus *n; \ - FILE *fp; \ - int msgnum; \ - long start, \ - stop; +} static int -pmatches(FILE *fp, int msgnum, long start, long stop) +pmatches(FILE *fp, int msgnum) { + struct field f = {{0}}; + enum state s = FLD2; + if (!head) return 1; - if (!talked++ && pdebug) - PRaction(head, 0); + if (!talked++ && pdebug && head->debug) { + head->debug(head->data, 0); + } - return (*head->n_action) (args(head)); + while (s == FLD2 || s == BODY2) { + switch (s = m_getfld2(s, &f, fp)) { + case LENERR2: + s = FLD2; + /* FALL */ + case FLD2: + if (head->action(&f, msgnum, head->data)) { + return TRUE; + } + break; + case BODY2: + if (!body) { + return FALSE; + } + if (head->action(&f, msgnum, head->data)) { + return TRUE; + } + break; + case IOERR2: + advise(NULL, "IOERR in message %d\n", msgnum); + return FALSE; + case FILEEOF2: + return FALSE; + default: + adios(EX_SOFTWARE, "m_getfld2", "returned unknown state %d at message %d", s, msgnum); + } + } + return FALSE; } +void +print_debug_level(size_t level) +{ + size_t i; -static void -PRaction(struct nexus *n, int level) + for (i = 0; i < level; i++) { + fputs("| ", stderr); + } +} + +void +BINdebug(void *data, size_t level) { - int i; + struct bin_data *bd = data; - for (i = 0; i < level; i++) - fprintf(stderr, "| "); + print_debug_level(level); - if (n->n_action == ORaction) { - fprintf(stderr, "OR\n"); - PRaction(n->n_L_child, level + 1); - PRaction(n->n_R_child, level + 1); - return; - } - if (n->n_action == ANDaction) { - fprintf(stderr, "AND\n"); - PRaction(n->n_L_child, level + 1); - PRaction(n->n_R_child, level + 1); - return; - } - if (n->n_action == NOTaction) { - fprintf(stderr, "NOT\n"); - PRaction(n->n_L_child, level + 1); + switch (bd->type) { + case TYPE_OR: + fputs("OR\n", stderr); + break; + case TYPE_AND: + fputs("AND\n", stderr); + break; + case TYPE_NOT: + fputs("NOT\n", stderr); + break; + default: + advise(NULL, "binary nexus has unknown type: %d\n", bd->type); return; } - if (n->n_action == GREPaction) { - fprintf(stderr, "PATTERN(%s) %s\n", - n->n_header ? "header" : "body", n->n_patbuf); - return; + + if (bd->left && bd->left->debug) { + bd->left->debug(bd->left->data, level+1); + } else { + print_debug_level(level+1); + fputs("can't debug left child\n", stderr); } - if (n->n_action == TWSaction) { - fprintf(stderr, "TEMPORAL(%s) %s: %s\n", - n->n_after ? "after" : "before", n->n_datef, - dasctime(&n->n_tws)); - return; + + if (bd->right && bd->right->debug) { + bd->right->debug(bd->right->data, level+1); + } else if (bd->type != TYPE_NOT) { + print_debug_level(level+1); + fputs("can't debug right child\n", stderr); } - fprintf(stderr, "UNKNOWN(0x%x)\n", - (unsigned int)(unsigned long) (*n->n_action)); } - -static int -ORaction(params) -plist +static boolean +NOTaction(struct field *f, int msgnum, void *data) { - if ((*n->n_L_child->n_action) (args(n->n_L_child))) - return 1; - return (*n->n_R_child->n_action) (args(n->n_R_child)); + struct bin_data *bin = data; + return !bin->left->action(f, msgnum, bin->left->data); } - -static int -ANDaction(params) -plist +static boolean +BINaction(struct field *f, int msgnum, void *data) { - if (!(*n->n_L_child->n_action) (args(n->n_L_child))) - return 0; - return (*n->n_R_child->n_action) (args(n->n_R_child)); -} + struct bin_data *bin = data; + if (bin->oldmsgnum != msgnum) { + bin->oldmsgnum = msgnum; + bin->match = FALSE; + bin->leftmatch = FALSE; + bin->rightmatch = FALSE; + } -static int -NOTaction(params) -plist -{ - return (!(*n->n_L_child->n_action) (args(n->n_L_child))); -} + if (bin->match) { + return bin->match; + } + bin->leftmatch = bin->leftmatch || bin->left->action(f, msgnum, bin->left->data); + bin->rightmatch = bin->rightmatch || bin->right->action(f, msgnum, bin->right->data); -static int -gcompile(struct nexus *n, char *astr) -{ - int c; - int cclcnt; - unsigned char *ep, *dp, *sp, *lastep = 0; - - dp = (ep = n->n_expbuf) + sizeof n->n_expbuf; - sp = astr; - if (*sp == '^') { - n->n_circf = 1; - sp++; - } - else - n->n_circf = 0; - for (;;) { - if (ep >= dp) - goto cerror; - if ((c = *sp++) != '*') - lastep = ep; - switch (c) { - case '\0': - *ep++ = CEOF; - return 1; - - case '.': - *ep++ = CDOT; - continue; - - case '*': - if (lastep == 0) - goto defchar; - *lastep |= STAR; - continue; - - case '$': - if (*sp != '\0') - goto defchar; - *ep++ = CDOL; - continue; - - case '[': - *ep++ = CCL; - *ep++ = 0; - cclcnt = 0; - if ((c = *sp++) == '^') { - c = *sp++; - ep[-2] = NCCL; - } - if (c == '-') { - *ep++ = c; - cclcnt++; - c = *sp++; - } - do { - if (c == '-' && *sp != '\0' && *sp != ']') { - for (c = ep[-1]+1; c < *sp; c++) { - *ep++ = c; - cclcnt++; - if (c == '\0' || ep >= dp) - goto cerror; - } - } else { - *ep++ = c; - cclcnt++; - if (c == '\0' || ep >= dp) - goto cerror; - } - } while ((c = *sp++) != ']'); - if (cclcnt > 255) - goto cerror; - lastep[1] = cclcnt; - continue; - - case '\\': - if ((c = *sp++) == '\0') - goto cerror; -defchar: - default: - *ep++ = CCHR; - *ep++ = c; - } + switch (bin->type) { + case TYPE_OR: + bin->match = bin->leftmatch || bin->rightmatch; + break; + case TYPE_AND: + bin->match = bin->leftmatch && bin->rightmatch; + break; + default: + adios(EX_SOFTWARE, NULL, "unknown nexus type: %d\n", bin->type); } -cerror: ; - return 0; + return bin->match; } - -static int -GREPaction(params) -plist +static void +BINfree(struct nexus **n) { - int c, body, lf; - long pos = start; - char *p1, *p2, *ebp, *cbp; - char ibuf[BUFSIZ]; - - fseek(fp, start, SEEK_SET); - body = 0; - ebp = cbp = ibuf; - for (;;) { - if (body && n->n_header) - return 0; - p1 = linebuf; - p2 = cbp; - lf = 0; - for (;;) { - if (p2 >= ebp) { - if (fgets(ibuf, sizeof ibuf, fp) == NULL - || (stop && pos >= stop)) { - if (lf) - break; - return 0; - } - pos += (long) strlen(ibuf); - p2 = ibuf; - ebp = ibuf + strlen(ibuf); - } - c = *p2++; - if (lf && c != '\n') { - if (c != ' ' && c != '\t') { - --p2; - break; - } - else - lf = 0; - } - if (c == '\n') { - if (body) - break; - else { - if (lf) { - body++; - break; - } - lf++; - c = ' '; - } - } - if (c && p1 < &linebuf[LBSIZE - 1]) - *p1++ = c; - } + struct nexus *bin = *n; + struct bin_data *bd = bin->data; - *p1++ = 0; - cbp = p2; - p1 = linebuf; - p2 = n->n_expbuf; - - /* - ** Attempt to decode as a MIME header. If it's the - ** last header, body will be 1 and lf will be at least 1. - */ - if ((body == 0 || lf > 0) && decode_rfc2047(linebuf, - decoded_linebuf, sizeof decoded_linebuf)) { - p1 = decoded_linebuf; - } - - if (n->n_circf) { - if (advance(p1, p2)) - return 1; - continue; - } - - if (*p2 == CCHR) { - c = p2[1]; - do { - if (*p1 == c || cc[(unsigned char)*p1] == c) - if (advance(p1, p2)) - return 1; - } while (*p1++); - continue; - } + if (bd->left && bd->left->free) { + bd->left->free(&bd->left); + } else { + advise(NULL, "BUG: can't free left child"); + } - do { - if (advance(p1, p2)) - return 1; - } while (*p1++); + if (bd->right && bd->right->free) { + bd->right->free(&bd->right); + } else { + advise(NULL, "BUG: can't free right child"); } -} + mh_free0(n); +} static int -advance(char *alp, char *aep) +gcompile(struct grep_data *g, const char *astr) { - unsigned char *lp, *ep, *curlp; - - lp = (unsigned char *)alp; - ep = (unsigned char *)aep; - for (;;) - switch (*ep++) { - case CCHR: - if (*ep++ == *lp++ || ep[-1] == cc[lp[-1]]) - continue; - return 0; - - case CDOT: - if (*lp++) - continue; - return 0; - - case CDOL: - if (*lp == 0) - continue; - return 0; - - case CEOF: - return 1; - - case CCL: - if (cclass(ep, *lp++, 1)) { - ep += *ep + 1; - continue; - } - return 0; + regex_t *preg = mh_xcalloc(1, sizeof(regex_t)); + char *buf; + int ret; + + g->preg = preg; + g->pattern = mh_xstrdup(astr); + ret = regcomp(preg, astr, REG_ICASE | REG_NOSUB); + if (ret != 0) { + buf = mh_xcalloc(BUFSIZ, sizeof(char)); + regerror(ret, g->preg, buf, BUFSIZ*sizeof(char)); + fprintf(stderr, "%s\n", buf); + return FALSE; + } + return TRUE; - case NCCL: - if (cclass(ep, *lp++, 0)) { - ep += *ep + 1; - continue; - } - return 0; +} - case CDOT | STAR: - curlp = lp; - while (*lp++) - continue; - goto star; +static boolean +GREPaction(struct field *f, int msgnum, void *data) +{ + struct grep_data *g = data; + int ret; + char *buf; - case CCHR | STAR: - curlp = lp; - while (*lp++ == *ep || cc[lp[-1]] == *ep) - continue; - ep++; - goto star; + /* check for the write field */ + if (g->header && *g->header && mh_strcasecmp(g->header, f->name)) { + return FALSE; + } - case CCL | STAR: - case NCCL | STAR: - curlp = lp; - while (cclass(ep, *lp++, ep[-1] == (CCL | STAR))) - continue; - ep += *ep + 1; - goto star; + if (!g->header && *f->name) { + return FALSE; + } -star: - do { - lp--; - if (advance(lp, ep)) - return (1); - } while (lp > curlp); - return 0; + ret = regexec(g->preg, f->value, 0, NULL, 0) == REG_NOMATCH; + switch (ret) { + case 0: + return TRUE; + case REG_NOMATCH: + return FALSE; + default: + buf = mh_xcalloc(BUFSIZ, sizeof(char)); + regerror(ret, g->preg, buf, BUFSIZ*sizeof(char)); + fprintf(stderr, "%s\n", buf); + return FALSE; + } - default: - admonish(NULL, "advance() botch -- you lose big"); - return 0; - } } +static void +GREPfree(struct nexus **n) +{ + struct grep_data *gd = (*n)->data; + mh_free0(&gd->header); + regfree(gd->preg); + mh_free0(n); +} -static int -cclass(unsigned char *aset, int ac, int af) +static void +GREPdebug(void *data, size_t level) { - unsigned int n; - unsigned char c, *set; + struct grep_data *gd = data; + char *buf, *buf2, *pbuf, *pbuf2; + + pbuf = pbuf2 = mh_xstrdup(gd->pattern); - set = aset; - if ((c = ac) == 0) - return (0); + for (;*pbuf2; pbuf2++) { + *pbuf2 = tolower(*pbuf2); + } - n = *set++; - while (n--) - if (*set++ == c || set[-1] == cc[c]) - return (af); + print_debug_level(level); - return (!af); + if (gd->header) { + buf = buf2 = mh_xstrdup(gd->header); + for (;*buf2; buf2++) { + *buf2 = tolower(*buf2); + } + fprintf(stderr, "PETTERN(%s) %s\n", buf, pbuf); + } else { + fprintf(stderr, "PETTERN(BODY) %s\n", pbuf); + } + mh_free0(&buf); + mh_free0(&pbuf); } - static int tcompile(char *ap, struct tws *tb, int isafter) { @@ -1293,60 +1173,45 @@ tws_special(char *ap) } -static int -TWSaction(params) -plist +static boolean +DATEaction(struct field *f, int msgnum, void *data) { - enum state state; - struct field f = {{0}}; + struct date_data *dd = data; + boolean state = FALSE; char *bp; struct tws *tw; - fseek(fp, start, SEEK_SET); - for (state = FLD2, bp = NULL;;) { - switch (state = m_getfld2(state, &f, fp)) { - case LENERR2: - state = FLD2; - /* FALL */ - - case FLD2: - if (bp) { - mh_free0(&bp); - } - bp = mh_xstrdup(f.value); - if (mh_strcasecmp(f.name, n->n_datef)==0) { - break; - } - continue; - - case FMTERR2: - advise(NULL, "format error in message %d", msgnum); - state = FLD2; - continue; + if (mh_strcasecmp(f->name, dd->datef)!=0) { + return FALSE; + } + bp = mh_xstrdup(f->value); + if ((tw = dparsetime(bp)) == NULL) { + advise(NULL, "unable to parse %s field in message %d, not matching...", dd->datef, msgnum); + state = FALSE; + } else if (dd->after) { + state = twsort(tw, &dd->tws) > 0; + } else { + state = twsort(tw, &dd->tws) < 0; + } - case IOERR2: - adios(EX_IOERR, "m_getfld2", "io error on message %d", msgnum); - /* FALL */ + mh_free0(&bp); - case BODY2: - case FILEEOF2: - mh_free0(&bp); - return 0; + return state; +} - default: - adios(EX_SOFTWARE, NULL, "internal error -- you lose"); - } - break; - } +static void +DATEfree(struct nexus **n) +{ + struct date_data *dd = (*n)->data; - if ((tw = dparsetime(bp)) == NULL) - advise(NULL, "unable to parse %s field in message %d, matching...", - n->n_datef, msgnum), state = 1; - else - state = n->n_after ? (twsort(tw, &n->n_tws) > 0) - : (twsort(tw, &n->n_tws) < 0); + mh_free0(&dd->datef); + mh_free0(n); +} - if (bp != NULL) - mh_free0(&bp); - return state; +static void +DATEdebug(void *data, size_t level) +{ + struct date_data *dd = data; + print_debug_level(level); + fprintf(stderr, "TEMPORAL(%s) %s: %s\n",dd->after ? "after" : "before", dd->datef, dasctime(&dd->tws)); }