From 27826f9353e0f0b04590b7d0f8f83e60462b90f0 Mon Sep 17 00:00:00 2001 From: markus schnalke Date: Sat, 11 Feb 2012 11:17:53 +0100 Subject: [PATCH] Merged picksbr.c into pick.c. --- h/Makefile.in | 2 +- h/picksbr.h | 9 - uip/Makefile.in | 6 +- uip/pick.c | 988 +++++++++++++++++++++++++++++++++++++++++++++++++++++- uip/picksbr.c | 991 ------------------------------------------------------- 5 files changed, 991 insertions(+), 1005 deletions(-) delete mode 100644 h/picksbr.h delete mode 100644 uip/picksbr.c diff --git a/h/Makefile.in b/h/Makefile.in index a2c4061..ad2cbd1 100644 --- a/h/Makefile.in +++ b/h/Makefile.in @@ -10,7 +10,7 @@ VPATH = @srcdir@ # header files included in distribution HDRS = addrsbr.h aliasbr.h crawl_folders.h dropsbr.h fmt_compile.h \ fmt_scan.h md5.h mf.h mh.h mhcachesbr.h mhparse.h mime.h \ - netdb.h nmh.h picksbr.h popsbr.h prototypes.h rcvmail.h \ + netdb.h nmh.h popsbr.h prototypes.h rcvmail.h \ scansbr.h signals.h tws.h utils.h # auxiliary files diff --git a/h/picksbr.h b/h/picksbr.h deleted file mode 100644 index 31b904e..0000000 --- a/h/picksbr.h +++ /dev/null @@ -1,9 +0,0 @@ -/* -** picksbr.h -- definitions for picksbr.c -*/ - -/* -** prototypes -*/ -int pcompile(char **, char *); -int pmatches(FILE *, int, long, long); diff --git a/uip/Makefile.in b/uip/Makefile.in index 403147f..48b8524 100644 --- a/uip/Makefile.in +++ b/uip/Makefile.in @@ -71,7 +71,7 @@ SRCS = ali.c aliasbr.c anno.c annosbr.c ap.c burst.c comp.c \ mhbuildsbr.c mhcachesbr.c mhfree.c mhl.c mhlist.c mhlistsbr.c \ mhmail.c mhmisc.c mhoutsbr.c mhparam.c mhparse.c \ mhpath.c mhshow.c mhshowsbr.c mhstore.c mhstoresbr.c mhtest.c \ - msgchk.c new.c packf.c pick.c picksbr.c \ + msgchk.c new.c packf.c pick.c \ prompter.c rcvdist.c rcvpack.c rcvstore.c \ refile.c repl.c rmf.c rmm.c scan.c scansbr.c send.c \ sendfiles.sh show.c slocal.c sortm.c spost.c termsbr.c \ @@ -171,8 +171,8 @@ new: new.o $(LOCALLIBS) packf: packf.o dropsbr.o $(LOCALLIBS) $(LINK) packf.o dropsbr.o $(LINKLIBS) -pick: pick.o picksbr.o $(LOCALLIBS) - $(LINK) pick.o picksbr.o $(LINKLIBS) +pick: pick.o $(LOCALLIBS) + $(LINK) pick.o $(LINKLIBS) prompter: prompter.o $(LOCALLIBS) $(LINK) prompter.o $(LINKLIBS) diff --git a/uip/pick.c b/uip/pick.c index e4d1370..73babad 100644 --- a/uip/pick.c +++ b/uip/pick.c @@ -8,9 +8,19 @@ #include #include -#include #include +#ifdef TIME_WITH_SYS_TIME +# include +# include +#else +# ifdef TM_IN_SYS_TIME +# include +# else +# include +# endif +#endif + static struct swit switches[] = { #define ANDSW 0 { "and", 0 }, @@ -63,6 +73,13 @@ static struct swit switches[] = { { NULL, 0 } }; +/* +** static prototypes +*/ +static int pcompile(char **, char *); +static int pmatches(FILE *, int, long, long); + + static int listsw = -1; static void putzero_done(int) NORETURN; @@ -304,3 +321,972 @@ putzero_done(int status) printf("0\n"); exit(status); } + + +static struct swit parswit[] = { +#define PRAND 0 + { "and", 0 }, +#define PROR 1 + { "or", 0 }, +#define PRNOT 2 + { "not", 0 }, +#define PRLBR 3 + { "lbrace", 0 }, +#define PRRBR 4 + { "rbrace", 0 }, +#define PRCC 5 + { "cc pattern", 0 }, +#define PRDATE 6 + { "date pattern", 0 }, +#define PRFROM 7 + { "from pattern", 0 }, +#define PRSRCH 8 + { "search pattern", 0 }, +#define PRSUBJ 9 + { "subject pattern", 0 }, +#define PRTO 10 + { "to pattern", 0 }, +#define PROTHR 11 + { "-othercomponent pattern", 15 }, +#define PRAFTR 12 + { "after date", 0 }, +#define PRBEFR 13 + { "before date", 0 }, +#define PRDATF 14 + { "datefield field", 5 }, + { NULL, 0 } +}; + +/* DEFINITIONS FOR PATTERN MATCHING */ + +/* +** We really should be using re_comp() and re_exec() here. Unfortunately, +** pick advertises that lowercase characters matches characters of both +** cases. Since re_exec() doesn't exhibit this behavior, we are stuck +** with this version. Furthermore, we need to be able to save and restore +** the state of the pattern matcher in order to do things "efficiently". +** +** The matching power of this algorithm isn't as powerful as the re_xxx() +** routines (no \(xxx\) and \n constructs). Such is life. +*/ + +#define CCHR 2 +#define CDOT 4 +#define CCL 6 +#define NCCL 8 +#define CDOL 10 +#define CEOF 11 + +#define STAR 01 + +#define LBSIZE 1024 +#define ESIZE 1024 + + +static char 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 +*/ + +#define nxtarg() (*argp ? *argp++ : NULL) +#define prvarg() argp-- + +#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; +}; + +#define n_L_child un.st1.un_L_child +#define n_R_child un.st1.un_R_child + +#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 + +#define n_datef un.st3.un_datef +#define n_after un.st3.un_after +#define n_tws un.st3.un_tws + +static int talked; +static int pdebug = 0; + +static char *datesw; +static char **argp; + +static struct nexus *head; + +/* +** prototypes for date routines +*/ +static struct tws *tws_parse(); +static struct tws *tws_special(); + +/* +** static prototypes +*/ +static void PRaction(); +static int gcompile(); +static int advance(); +static int cclass(); +static int tcompile(); + +static struct nexus *parse(); +static struct nexus *nexp1(); +static struct nexus *nexp2(); +static struct nexus *nexp3(); +static struct nexus *newnexus(); + +static int ORaction(); +static int ANDaction(); +static int NOTaction(); +static int GREPaction(); +static int TWSaction(); + + +static int +pcompile(char **vec, char *date) +{ + register char *cp; + + if ((cp = getenv("MHPDEBUG")) && *cp) + pdebug++; + + argp = vec; + if ((datesw = date) == NULL) + datesw = "date"; + talked = 0; + + if ((head = parse()) == NULL) + return (talked ? 0 : 1); + + if (*argp) { + padvise(NULL, "%s unexpected", *argp); + return 0; + } + + return 1; +} + + +static struct nexus * +parse(void) +{ + register char *cp; + register struct nexus *n, *o; + + if ((n = nexp1()) == NULL || (cp = nxtarg()) == NULL) + return n; + + if (*cp != '-') { + padvise(NULL, "%s unexpected", cp); + return NULL; + } + + if (*++cp == '-') + goto header; + switch (smatch(cp, parswit)) { + case AMBIGSW: + ambigsw(cp, parswit); + talked++; + return NULL; + case UNKWNSW: + fprintf(stderr, "-%s unknown\n", cp); + talked++; + return NULL; + + case PROR: + o = newnexus(ORaction); + o->n_L_child = n; + if ((o->n_R_child = parse())) + return o; + padvise(NULL, "missing disjunctive"); + return NULL; + +header: ; + default: + prvarg(); + return n; + } +} + +static struct nexus * +nexp1(void) +{ + register char *cp; + register struct nexus *n, *o; + + if ((n = nexp2()) == NULL || (cp = nxtarg()) == NULL) + return n; + + if (*cp != '-') { + padvise(NULL, "%s unexpected", cp); + return NULL; + } + + if (*++cp == '-') + goto header; + switch (smatch(cp, parswit)) { + case AMBIGSW: + ambigsw(cp, parswit); + talked++; + return NULL; + case UNKWNSW: + fprintf(stderr, "-%s unknown\n", cp); + talked++; + return NULL; + + case PRAND: + o = newnexus(ANDaction); + o->n_L_child = n; + if ((o->n_R_child = nexp1())) + return o; + padvise(NULL, "missing conjunctive"); + return NULL; + +header: ; + default: + prvarg(); + return n; + } +} + + +static struct nexus * +nexp2(void) +{ + register char *cp; + register struct nexus *n; + + if ((cp = nxtarg()) == NULL) + return NULL; + + if (*cp != '-') { + prvarg(); + return nexp3(); + } + + if (*++cp == '-') + goto header; + switch (smatch(cp, parswit)) { + case AMBIGSW: + ambigsw(cp, parswit); + talked++; + return NULL; + case UNKWNSW: + fprintf(stderr, "-%s unknown\n", cp); + talked++; + return NULL; + + case PRNOT: + n = newnexus(NOTaction); + if ((n->n_L_child = nexp3())) + return n; + padvise(NULL, "missing negation"); + return NULL; + +header: ; + default: + prvarg(); + return nexp3(); + } +} + +static struct nexus * +nexp3(void) +{ + int i; + register char *cp, *dp; + char buffer[BUFSIZ], temp[64]; + register struct nexus *n; + + if ((cp = nxtarg()) == NULL) + return NULL; + + if (*cp != '-') { + padvise(NULL, "%s unexpected", cp); + return NULL; + } + + if (*++cp == '-') { + dp = ++cp; + goto header; + } + switch (i = smatch(cp, parswit)) { + case AMBIGSW: + ambigsw(cp, parswit); + talked++; + return NULL; + case UNKWNSW: + fprintf(stderr, "-%s unknown\n", cp); + talked++; + return NULL; + + case PRLBR: + if ((n = parse()) == NULL) { + padvise(NULL, "missing group"); + return NULL; + } + if ((cp = nxtarg()) == NULL) { + padvise(NULL, "missing -rbrace"); + return NULL; + } + if (*cp++ == '-' && smatch(cp, parswit) == PRRBR) + return n; + padvise(NULL, "%s unexpected", --cp); + return NULL; + + default: + prvarg(); + return NULL; + + case PRCC: + case PRDATE: + case PRFROM: + case PRTO: + case PRSUBJ: + strncpy(temp, parswit[i].sw, sizeof(temp)); + temp[sizeof(temp) - 1] = '\0'; + dp = *brkstring(temp, " ", NULL); +header: ; + if (!(cp = nxtarg())) { /* allow -xyz arguments */ + 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); + dp = buffer; + goto pattern; + + case PRSRCH: + n = newnexus(GREPaction); + n->n_header = 0; + 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); + return NULL; + } + n->n_patbuf = getcpy(dp); + return n; + + case PROTHR: + padvise(NULL, "internal error!"); + return NULL; + + case PRDATF: + if (!(datesw = nxtarg()) || *datesw == '-') { + padvise(NULL, "missing argument to %s", + argp[-2]); + return NULL; + } + return nexp3(); + + case PRAFTR: + case PRBEFR: + if (!(cp = nxtarg())) { /* allow -xyz arguments */ + 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)) { + padvise(NULL, "unable to parse %s %s", argp[-2], cp); + return NULL; + } + return n; + } +} + + +static struct nexus * +newnexus(int (*action)()) +{ + register struct nexus *p; + + if ((p = (struct nexus *) calloc((size_t) 1, sizeof *p)) == NULL) + adios(NULL, "unable to allocate component storage"); + + p->n_action = action; + return p; +} + + +#define args(a) a, fp, msgnum, start, stop +#define params args(n) +#define plist \ + register struct nexus *n; \ + register FILE *fp; \ + int msgnum; \ + long start, \ + stop; + +static int +pmatches(FILE *fp, int msgnum, long start, long stop) +{ + if (!head) + return 1; + + if (!talked++ && pdebug) + PRaction(head, 0); + + return (*head->n_action) (args(head)); +} + + +static void +PRaction(struct nexus *n, int level) +{ + register int i; + + for (i = 0; i < level; i++) + fprintf(stderr, "| "); + + 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); + return; + } + if (n->n_action == GREPaction) { + fprintf(stderr, "PATTERN(%s) %s\n", + n->n_header ? "header" : "body", n->n_patbuf); + return; + } + if (n->n_action == TWSaction) { + fprintf(stderr, "TEMPORAL(%s) %s: %s\n", + n->n_after ? "after" : "before", n->n_datef, + dasctime(&n->n_tws, TW_NULL)); + return; + } + fprintf(stderr, "UNKNOWN(0x%x)\n", + (unsigned int)(unsigned long) (*n->n_action)); +} + + +static int +ORaction(params) +plist +{ + 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)); +} + + +static int +ANDaction(params) +plist +{ + 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)); +} + + +static int +NOTaction(params) +plist +{ + return (!(*n->n_L_child->n_action) (args(n->n_L_child))); +} + + +static int +gcompile(struct nexus *n, char *astr) +{ + register int c; + int cclcnt; + register 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; + } + } + +cerror: ; + return 0; +} + + +static int +GREPaction(params) +plist +{ + int c, body, lf; + long pos = start; + register 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; + } + + *p1++ = 0; + cbp = p2; + p1 = linebuf; + p2 = n->n_expbuf; + + 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; + } + + do { + if (advance(p1, p2)) + return 1; + } while (*p1++); + } +} + + +static int +advance(char *alp, char *aep) +{ + register 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; + + case NCCL: + if (cclass(ep, *lp++, 0)) { + ep += *ep + 1; + continue; + } + return 0; + + case CDOT | STAR: + curlp = lp; + while (*lp++) + continue; + goto star; + + case CCHR | STAR: + curlp = lp; + while (*lp++ == *ep || cc[lp[-1]] == *ep) + continue; + ep++; + goto star; + + case CCL | STAR: + case NCCL | STAR: + curlp = lp; + while (cclass(ep, *lp++, ep[-1] == (CCL | STAR))) + continue; + ep += *ep + 1; + goto star; + +star: + do { + lp--; + if (advance(lp, ep)) + return (1); + } while (lp > curlp); + return 0; + + default: + admonish(NULL, "advance() botch -- you lose big"); + return 0; + } +} + + +static int +cclass(unsigned char *aset, int ac, int af) +{ + register unsigned int n; + register unsigned char c, *set; + + set = aset; + if ((c = ac) == 0) + return (0); + + n = *set++; + while (n--) + if (*set++ == c || set[-1] == cc[c]) + return (af); + + return (!af); +} + + +static int +tcompile(char *ap, struct tws *tb, int isafter) +{ + register struct tws *tw; + + if ((tw = tws_parse(ap, isafter)) == NULL) + return 0; + + twscopy(tb, tw); + return 1; +} + + +static struct tws * +tws_parse(char *ap, int isafter) +{ + char buffer[BUFSIZ]; + register struct tws *tw, *ts; + + if ((tw = tws_special(ap)) != NULL) { + tw->tw_sec = tw->tw_min = isafter ? 59 : 0; + tw->tw_hour = isafter ? 23 : 0; + return tw; + } + if ((tw = dparsetime(ap)) != NULL) + return tw; + + if ((ts = dlocaltimenow()) == NULL) + return NULL; + + snprintf(buffer, sizeof(buffer), "%s %s", ap, dtwszone(ts)); + if ((tw = dparsetime(buffer)) != NULL) + return tw; + + snprintf(buffer, sizeof(buffer), "%s %02d:%02d:%02d %s", ap, + ts->tw_hour, ts->tw_min, ts->tw_sec, dtwszone(ts)); + if ((tw = dparsetime(buffer)) != NULL) + return tw; + + snprintf(buffer, sizeof(buffer), "%02d %s %04d %s", + ts->tw_mday, tw_moty[ts->tw_mon], ts->tw_year, ap); + if ((tw = dparsetime(buffer)) != NULL) + return tw; + + snprintf(buffer, sizeof(buffer), "%02d %s %04d %s %s", + ts->tw_mday, tw_moty[ts->tw_mon], ts->tw_year, + ap, dtwszone(ts)); + if ((tw = dparsetime(buffer)) != NULL) + return tw; + + return NULL; +} + + +static struct tws * +tws_special(char *ap) +{ + int i; + time_t clock; + register struct tws *tw; + + time(&clock); + if (!mh_strcasecmp(ap, "today")) + return dlocaltime(&clock); + if (!mh_strcasecmp(ap, "yesterday")) { + clock -= (long) (60 * 60 * 24); + return dlocaltime(&clock); + } + if (!mh_strcasecmp(ap, "tomorrow")) { + clock += (long) (60 * 60 * 24); + return dlocaltime(&clock); + } + + for (i = 0; tw_ldotw[i]; i++) + if (!mh_strcasecmp(ap, tw_ldotw[i])) + break; + if (tw_ldotw[i]) { + if ((tw = dlocaltime(&clock)) == NULL) + return NULL; + if ((i -= tw->tw_wday) > 0) + i -= 7; + } + else + if (*ap != '-') + return NULL; + else /* -ddd days ago */ + i = atoi(ap); /* we should error check this */ + + clock += (long) ((60 * 60 * 24) * i); + return dlocaltime(&clock); +} + + +static int +TWSaction(params) +plist +{ + int state; + register char *bp; + char buf[BUFSIZ], name[NAMESZ]; + register struct tws *tw; + + fseek(fp, start, SEEK_SET); + for (state = FLD, bp = NULL;;) { + switch (state = m_getfld(state, name, buf, sizeof buf, fp)) { + case FLD: + case FLDEOF: + case FLDPLUS: + if (bp != NULL) { + free(bp); + bp = NULL; + } + bp = getcpy(buf); + while (state == FLDPLUS) { + state = m_getfld(state, name, buf, + sizeof buf, fp); + bp = add(buf, bp); + } + if (!mh_strcasecmp(name, n->n_datef)) + break; + if (state != FLDEOF) + continue; + + case BODY: + case BODYEOF: + case FILEEOF: + case LENERR: + case FMTERR: + if (state == LENERR || state == FMTERR) + advise(NULL, "format error in message %d", msgnum); + if (bp != NULL) + free(bp); + return 0; + + default: + adios(NULL, "internal error -- you lose"); + } + break; + } + + 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); + + if (bp != NULL) + free(bp); + return state; +} diff --git a/uip/picksbr.c b/uip/picksbr.c deleted file mode 100644 index 872e18a..0000000 --- a/uip/picksbr.c +++ /dev/null @@ -1,991 +0,0 @@ -/* -** picksbr.c -- routines to help pick along... -** -** This code is Copyright (c) 2002, by the authors of nmh. See the -** COPYRIGHT file in the root directory of the nmh distribution for -** complete copyright information. -*/ - -#include -#include -#include -#include - -#ifdef TIME_WITH_SYS_TIME -# include -# include -#else -# ifdef TM_IN_SYS_TIME -# include -# else -# include -# endif -#endif - -static struct swit parswit[] = { -#define PRAND 0 - { "and", 0 }, -#define PROR 1 - { "or", 0 }, -#define PRNOT 2 - { "not", 0 }, -#define PRLBR 3 - { "lbrace", 0 }, -#define PRRBR 4 - { "rbrace", 0 }, -#define PRCC 5 - { "cc pattern", 0 }, -#define PRDATE 6 - { "date pattern", 0 }, -#define PRFROM 7 - { "from pattern", 0 }, -#define PRSRCH 8 - { "search pattern", 0 }, -#define PRSUBJ 9 - { "subject pattern", 0 }, -#define PRTO 10 - { "to pattern", 0 }, -#define PROTHR 11 - { "-othercomponent pattern", 15 }, -#define PRAFTR 12 - { "after date", 0 }, -#define PRBEFR 13 - { "before date", 0 }, -#define PRDATF 14 - { "datefield field", 5 }, - { NULL, 0 } -}; - -/* DEFINITIONS FOR PATTERN MATCHING */ - -/* -** We really should be using re_comp() and re_exec() here. Unfortunately, -** pick advertises that lowercase characters matches characters of both -** cases. Since re_exec() doesn't exhibit this behavior, we are stuck -** with this version. Furthermore, we need to be able to save and restore -** the state of the pattern matcher in order to do things "efficiently". -** -** The matching power of this algorithm isn't as powerful as the re_xxx() -** routines (no \(xxx\) and \n constructs). Such is life. -*/ - -#define CCHR 2 -#define CDOT 4 -#define CCL 6 -#define NCCL 8 -#define CDOL 10 -#define CEOF 11 - -#define STAR 01 - -#define LBSIZE 1024 -#define ESIZE 1024 - - -static char 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 -*/ - -#define nxtarg() (*argp ? *argp++ : NULL) -#define prvarg() argp-- - -#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; -}; - -#define n_L_child un.st1.un_L_child -#define n_R_child un.st1.un_R_child - -#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 - -#define n_datef un.st3.un_datef -#define n_after un.st3.un_after -#define n_tws un.st3.un_tws - -static int talked; -static int pdebug = 0; - -static char *datesw; -static char **argp; - -static struct nexus *head; - -/* -** prototypes for date routines -*/ -static struct tws *tws_parse(); -static struct tws *tws_special(); - -/* -** static prototypes -*/ -static void PRaction(); -static int gcompile(); -static int advance(); -static int cclass(); -static int tcompile(); - -static struct nexus *parse(); -static struct nexus *nexp1(); -static struct nexus *nexp2(); -static struct nexus *nexp3(); -static struct nexus *newnexus(); - -static int ORaction(); -static int ANDaction(); -static int NOTaction(); -static int GREPaction(); -static int TWSaction(); - - -int -pcompile(char **vec, char *date) -{ - register char *cp; - - if ((cp = getenv("MHPDEBUG")) && *cp) - pdebug++; - - argp = vec; - if ((datesw = date) == NULL) - datesw = "date"; - talked = 0; - - if ((head = parse()) == NULL) - return (talked ? 0 : 1); - - if (*argp) { - padvise(NULL, "%s unexpected", *argp); - return 0; - } - - return 1; -} - - -static struct nexus * -parse(void) -{ - register char *cp; - register struct nexus *n, *o; - - if ((n = nexp1()) == NULL || (cp = nxtarg()) == NULL) - return n; - - if (*cp != '-') { - padvise(NULL, "%s unexpected", cp); - return NULL; - } - - if (*++cp == '-') - goto header; - switch (smatch(cp, parswit)) { - case AMBIGSW: - ambigsw(cp, parswit); - talked++; - return NULL; - case UNKWNSW: - fprintf(stderr, "-%s unknown\n", cp); - talked++; - return NULL; - - case PROR: - o = newnexus(ORaction); - o->n_L_child = n; - if ((o->n_R_child = parse())) - return o; - padvise(NULL, "missing disjunctive"); - return NULL; - -header: ; - default: - prvarg(); - return n; - } -} - -static struct nexus * -nexp1(void) -{ - register char *cp; - register struct nexus *n, *o; - - if ((n = nexp2()) == NULL || (cp = nxtarg()) == NULL) - return n; - - if (*cp != '-') { - padvise(NULL, "%s unexpected", cp); - return NULL; - } - - if (*++cp == '-') - goto header; - switch (smatch(cp, parswit)) { - case AMBIGSW: - ambigsw(cp, parswit); - talked++; - return NULL; - case UNKWNSW: - fprintf(stderr, "-%s unknown\n", cp); - talked++; - return NULL; - - case PRAND: - o = newnexus(ANDaction); - o->n_L_child = n; - if ((o->n_R_child = nexp1())) - return o; - padvise(NULL, "missing conjunctive"); - return NULL; - -header: ; - default: - prvarg(); - return n; - } -} - - -static struct nexus * -nexp2(void) -{ - register char *cp; - register struct nexus *n; - - if ((cp = nxtarg()) == NULL) - return NULL; - - if (*cp != '-') { - prvarg(); - return nexp3(); - } - - if (*++cp == '-') - goto header; - switch (smatch(cp, parswit)) { - case AMBIGSW: - ambigsw(cp, parswit); - talked++; - return NULL; - case UNKWNSW: - fprintf(stderr, "-%s unknown\n", cp); - talked++; - return NULL; - - case PRNOT: - n = newnexus(NOTaction); - if ((n->n_L_child = nexp3())) - return n; - padvise(NULL, "missing negation"); - return NULL; - -header: ; - default: - prvarg(); - return nexp3(); - } -} - -static struct nexus * -nexp3(void) -{ - int i; - register char *cp, *dp; - char buffer[BUFSIZ], temp[64]; - register struct nexus *n; - - if ((cp = nxtarg()) == NULL) - return NULL; - - if (*cp != '-') { - padvise(NULL, "%s unexpected", cp); - return NULL; - } - - if (*++cp == '-') { - dp = ++cp; - goto header; - } - switch (i = smatch(cp, parswit)) { - case AMBIGSW: - ambigsw(cp, parswit); - talked++; - return NULL; - case UNKWNSW: - fprintf(stderr, "-%s unknown\n", cp); - talked++; - return NULL; - - case PRLBR: - if ((n = parse()) == NULL) { - padvise(NULL, "missing group"); - return NULL; - } - if ((cp = nxtarg()) == NULL) { - padvise(NULL, "missing -rbrace"); - return NULL; - } - if (*cp++ == '-' && smatch(cp, parswit) == PRRBR) - return n; - padvise(NULL, "%s unexpected", --cp); - return NULL; - - default: - prvarg(); - return NULL; - - case PRCC: - case PRDATE: - case PRFROM: - case PRTO: - case PRSUBJ: - strncpy(temp, parswit[i].sw, sizeof(temp)); - temp[sizeof(temp) - 1] = '\0'; - dp = *brkstring(temp, " ", NULL); -header: ; - if (!(cp = nxtarg())) { /* allow -xyz arguments */ - 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); - dp = buffer; - goto pattern; - - case PRSRCH: - n = newnexus(GREPaction); - n->n_header = 0; - 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); - return NULL; - } - n->n_patbuf = getcpy(dp); - return n; - - case PROTHR: - padvise(NULL, "internal error!"); - return NULL; - - case PRDATF: - if (!(datesw = nxtarg()) || *datesw == '-') { - padvise(NULL, "missing argument to %s", - argp[-2]); - return NULL; - } - return nexp3(); - - case PRAFTR: - case PRBEFR: - if (!(cp = nxtarg())) { /* allow -xyz arguments */ - 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)) { - padvise(NULL, "unable to parse %s %s", argp[-2], cp); - return NULL; - } - return n; - } -} - - -static struct nexus * -newnexus(int (*action)()) -{ - register struct nexus *p; - - if ((p = (struct nexus *) calloc((size_t) 1, sizeof *p)) == NULL) - adios(NULL, "unable to allocate component storage"); - - p->n_action = action; - return p; -} - - -#define args(a) a, fp, msgnum, start, stop -#define params args(n) -#define plist \ - register struct nexus *n; \ - register FILE *fp; \ - int msgnum; \ - long start, \ - stop; - -int -pmatches(FILE *fp, int msgnum, long start, long stop) -{ - if (!head) - return 1; - - if (!talked++ && pdebug) - PRaction(head, 0); - - return (*head->n_action) (args(head)); -} - - -static void -PRaction(struct nexus *n, int level) -{ - register int i; - - for (i = 0; i < level; i++) - fprintf(stderr, "| "); - - 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); - return; - } - if (n->n_action == GREPaction) { - fprintf(stderr, "PATTERN(%s) %s\n", - n->n_header ? "header" : "body", n->n_patbuf); - return; - } - if (n->n_action == TWSaction) { - fprintf(stderr, "TEMPORAL(%s) %s: %s\n", - n->n_after ? "after" : "before", n->n_datef, - dasctime(&n->n_tws, TW_NULL)); - return; - } - fprintf(stderr, "UNKNOWN(0x%x)\n", - (unsigned int)(unsigned long) (*n->n_action)); -} - - -static int -ORaction(params) -plist -{ - 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)); -} - - -static int -ANDaction(params) -plist -{ - 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)); -} - - -static int -NOTaction(params) -plist -{ - return (!(*n->n_L_child->n_action) (args(n->n_L_child))); -} - - -static int -gcompile(struct nexus *n, char *astr) -{ - register int c; - int cclcnt; - register 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; - } - } - -cerror: ; - return 0; -} - - -static int -GREPaction(params) -plist -{ - int c, body, lf; - long pos = start; - register 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; - } - - *p1++ = 0; - cbp = p2; - p1 = linebuf; - p2 = n->n_expbuf; - - 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; - } - - do { - if (advance(p1, p2)) - return 1; - } while (*p1++); - } -} - - -static int -advance(char *alp, char *aep) -{ - register 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; - - case NCCL: - if (cclass(ep, *lp++, 0)) { - ep += *ep + 1; - continue; - } - return 0; - - case CDOT | STAR: - curlp = lp; - while (*lp++) - continue; - goto star; - - case CCHR | STAR: - curlp = lp; - while (*lp++ == *ep || cc[lp[-1]] == *ep) - continue; - ep++; - goto star; - - case CCL | STAR: - case NCCL | STAR: - curlp = lp; - while (cclass(ep, *lp++, ep[-1] == (CCL | STAR))) - continue; - ep += *ep + 1; - goto star; - -star: - do { - lp--; - if (advance(lp, ep)) - return (1); - } while (lp > curlp); - return 0; - - default: - admonish(NULL, "advance() botch -- you lose big"); - return 0; - } -} - - -static int -cclass(unsigned char *aset, int ac, int af) -{ - register unsigned int n; - register unsigned char c, *set; - - set = aset; - if ((c = ac) == 0) - return (0); - - n = *set++; - while (n--) - if (*set++ == c || set[-1] == cc[c]) - return (af); - - return (!af); -} - - -static int -tcompile(char *ap, struct tws *tb, int isafter) -{ - register struct tws *tw; - - if ((tw = tws_parse(ap, isafter)) == NULL) - return 0; - - twscopy(tb, tw); - return 1; -} - - -static struct tws * -tws_parse(char *ap, int isafter) -{ - char buffer[BUFSIZ]; - register struct tws *tw, *ts; - - if ((tw = tws_special(ap)) != NULL) { - tw->tw_sec = tw->tw_min = isafter ? 59 : 0; - tw->tw_hour = isafter ? 23 : 0; - return tw; - } - if ((tw = dparsetime(ap)) != NULL) - return tw; - - if ((ts = dlocaltimenow()) == NULL) - return NULL; - - snprintf(buffer, sizeof(buffer), "%s %s", ap, dtwszone(ts)); - if ((tw = dparsetime(buffer)) != NULL) - return tw; - - snprintf(buffer, sizeof(buffer), "%s %02d:%02d:%02d %s", ap, - ts->tw_hour, ts->tw_min, ts->tw_sec, dtwszone(ts)); - if ((tw = dparsetime(buffer)) != NULL) - return tw; - - snprintf(buffer, sizeof(buffer), "%02d %s %04d %s", - ts->tw_mday, tw_moty[ts->tw_mon], ts->tw_year, ap); - if ((tw = dparsetime(buffer)) != NULL) - return tw; - - snprintf(buffer, sizeof(buffer), "%02d %s %04d %s %s", - ts->tw_mday, tw_moty[ts->tw_mon], ts->tw_year, - ap, dtwszone(ts)); - if ((tw = dparsetime(buffer)) != NULL) - return tw; - - return NULL; -} - - -static struct tws * -tws_special(char *ap) -{ - int i; - time_t clock; - register struct tws *tw; - - time(&clock); - if (!mh_strcasecmp(ap, "today")) - return dlocaltime(&clock); - if (!mh_strcasecmp(ap, "yesterday")) { - clock -= (long) (60 * 60 * 24); - return dlocaltime(&clock); - } - if (!mh_strcasecmp(ap, "tomorrow")) { - clock += (long) (60 * 60 * 24); - return dlocaltime(&clock); - } - - for (i = 0; tw_ldotw[i]; i++) - if (!mh_strcasecmp(ap, tw_ldotw[i])) - break; - if (tw_ldotw[i]) { - if ((tw = dlocaltime(&clock)) == NULL) - return NULL; - if ((i -= tw->tw_wday) > 0) - i -= 7; - } - else - if (*ap != '-') - return NULL; - else /* -ddd days ago */ - i = atoi(ap); /* we should error check this */ - - clock += (long) ((60 * 60 * 24) * i); - return dlocaltime(&clock); -} - - -static int -TWSaction(params) -plist -{ - int state; - register char *bp; - char buf[BUFSIZ], name[NAMESZ]; - register struct tws *tw; - - fseek(fp, start, SEEK_SET); - for (state = FLD, bp = NULL;;) { - switch (state = m_getfld(state, name, buf, sizeof buf, fp)) { - case FLD: - case FLDEOF: - case FLDPLUS: - if (bp != NULL) { - free(bp); - bp = NULL; - } - bp = getcpy(buf); - while (state == FLDPLUS) { - state = m_getfld(state, name, buf, - sizeof buf, fp); - bp = add(buf, bp); - } - if (!mh_strcasecmp(name, n->n_datef)) - break; - if (state != FLDEOF) - continue; - - case BODY: - case BODYEOF: - case FILEEOF: - case LENERR: - case FMTERR: - if (state == LENERR || state == FMTERR) - advise(NULL, "format error in message %d", msgnum); - if (bp != NULL) - free(bp); - return 0; - - default: - adios(NULL, "internal error -- you lose"); - } - break; - } - - 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); - - if (bp != NULL) - free(bp); - return state; -} -- 1.7.10.4