3 * picksbr.c -- routines to help pick along...
10 #include <h/picksbr.h>
12 #ifdef TIME_WITH_SYS_TIME
13 # include <sys/time.h>
16 # ifdef TM_IN_SYS_TIME
17 # include <sys/time.h>
23 static struct swit parswit[] = {
37 { "date pattern", 0 },
39 { "from pattern", 0 },
41 { "search pattern", 0 },
43 { "subject pattern", 0 },
47 { "-othercomponent pattern", 15 },
53 { "datefield field", 5 },
57 /* DEFINITIONS FOR PATTERN MATCHING */
60 * We really should be using re_comp() and re_exec() here. Unfortunately,
61 * pick advertises that lowercase characters matches characters of both
62 * cases. Since re_exec() doesn't exhibit this behavior, we are stuck
63 * with this version. Furthermore, we need to be able to save and restore
64 * the state of the pattern matcher in order to do things "efficiently".
66 * The matching power of this algorithm isn't as powerful as the re_xxx()
67 * routines (no \(xxx\) and \n constructs). Such is life.
83 static char linebuf[LBSIZE + 1];
85 /* the magic array for case-independence */
87 0000,0001,0002,0003,0004,0005,0006,0007,
88 0010,0011,0012,0013,0014,0015,0016,0017,
89 0020,0021,0022,0023,0024,0025,0026,0027,
90 0030,0031,0032,0033,0034,0035,0036,0037,
91 0040,0041,0042,0043,0044,0045,0046,0047,
92 0050,0051,0052,0053,0054,0055,0056,0057,
93 0060,0061,0062,0063,0064,0065,0066,0067,
94 0070,0071,0072,0073,0074,0075,0076,0077,
95 0100,0141,0142,0143,0144,0145,0146,0147,
96 0150,0151,0152,0153,0154,0155,0156,0157,
97 0160,0161,0162,0163,0164,0165,0166,0167,
98 0170,0171,0172,0133,0134,0135,0136,0137,
99 0140,0141,0142,0143,0144,0145,0146,0147,
100 0150,0151,0152,0153,0154,0155,0156,0157,
101 0160,0161,0162,0163,0164,0165,0166,0167,
102 0170,0171,0172,0173,0174,0175,0176,0177,
106 * DEFINITIONS FOR NEXUS
109 #define nxtarg() (*argp ? *argp++ : NULL)
110 #define prvarg() argp--
112 #define padvise if (!talked++) advise
118 /* for {OR,AND,NOT}action */
120 struct nexus *un_L_child;
121 struct nexus *un_R_child;
128 char un_expbuf[ESIZE];
141 #define n_L_child un.st1.un_L_child
142 #define n_R_child un.st1.un_R_child
144 #define n_header un.st2.un_header
145 #define n_circf un.st2.un_circf
146 #define n_expbuf un.st2.un_expbuf
147 #define n_patbuf un.st2.un_patbuf
149 #define n_datef un.st3.un_datef
150 #define n_after un.st3.un_after
151 #define n_tws un.st3.un_tws
154 static int pdebug = 0;
159 static struct nexus *head;
162 * prototypes for date routines
164 static struct tws *tws_parse();
165 static struct tws *tws_special();
170 static void PRaction();
171 static int gcompile();
172 static int advance();
174 static int tcompile();
176 static struct nexus *parse();
177 static struct nexus *exp1();
178 static struct nexus *exp2();
179 static struct nexus *exp3();
180 static struct nexus *newnexus();
182 static int ORaction();
183 static int ANDaction();
184 static int NOTaction();
185 static int GREPaction();
186 static int TWSaction();
190 pcompile (char **vec, char *date)
194 if ((cp = getenv ("MHPDEBUG")) && *cp)
198 if ((datesw = date) == NULL)
202 if ((head = parse ()) == NULL)
203 return (talked ? 0 : 1);
206 padvise (NULL, "%s unexpected", *argp);
214 static struct nexus *
218 register struct nexus *n, *o;
220 if ((n = exp1 ()) == NULL || (cp = nxtarg ()) == NULL)
224 padvise (NULL, "%s unexpected", cp);
230 switch (smatch (cp, parswit)) {
232 ambigsw (cp, parswit);
236 fprintf (stderr, "-%s unknown\n", cp);
241 o = newnexus (ORaction);
243 if ((o->n_R_child = parse ()))
245 padvise (NULL, "missing disjunctive");
255 static struct nexus *
259 register struct nexus *n, *o;
261 if ((n = exp2 ()) == NULL || (cp = nxtarg ()) == NULL)
265 padvise (NULL, "%s unexpected", cp);
271 switch (smatch (cp, parswit)) {
273 ambigsw (cp, parswit);
277 fprintf (stderr, "-%s unknown\n", cp);
282 o = newnexus (ANDaction);
284 if ((o->n_R_child = exp1 ()))
286 padvise (NULL, "missing conjunctive");
297 static struct nexus *
301 register struct nexus *n;
303 if ((cp = nxtarg ()) == NULL)
313 switch (smatch (cp, parswit)) {
315 ambigsw (cp, parswit);
319 fprintf (stderr, "-%s unknown\n", cp);
324 n = newnexus (NOTaction);
325 if ((n->n_L_child = exp3 ()))
327 padvise (NULL, "missing negation");
337 static struct nexus *
341 register char *cp, *dp;
342 char buffer[BUFSIZ], temp[64];
343 register struct nexus *n;
345 if ((cp = nxtarg ()) == NULL)
349 padvise (NULL, "%s unexpected", cp);
357 switch (i = smatch (cp, parswit)) {
359 ambigsw (cp, parswit);
363 fprintf (stderr, "-%s unknown\n", cp);
368 if ((n = parse ()) == NULL) {
369 padvise (NULL, "missing group");
372 if ((cp = nxtarg ()) == NULL) {
373 padvise (NULL, "missing -rbrace");
376 if (*cp++ == '-' && smatch (cp, parswit) == PRRBR)
378 padvise (NULL, "%s unexpected", --cp);
390 strncpy(temp, parswit[i].sw, sizeof(temp));
391 temp[sizeof(temp) - 1] = '\0';
392 dp = *brkstring (temp, " ", NULL);
394 if (!(cp = nxtarg ())) {/* allow -xyz arguments */
395 padvise (NULL, "missing argument to %s", argp[-2]);
398 n = newnexus (GREPaction);
400 snprintf (buffer, sizeof(buffer), "^%s[ \t]*:.*%s", dp, cp);
405 n = newnexus (GREPaction);
407 if (!(cp = nxtarg ())) {/* allow -xyz arguments */
408 padvise (NULL, "missing argument to %s", argp[-2]);
413 if (!gcompile (n, dp)) {
414 padvise (NULL, "pattern error in %s %s", argp[-2], cp);
417 n->n_patbuf = getcpy (dp);
421 padvise (NULL, "internal error!");
425 if (!(datesw = nxtarg ()) || *datesw == '-') {
426 padvise (NULL, "missing argument to %s", argp[-2]);
433 if (!(cp = nxtarg ())) {/* allow -xyz arguments */
434 padvise (NULL, "missing argument to %s", argp[-2]);
437 n = newnexus (TWSaction);
439 if (!tcompile (cp, &n->n_tws, n->n_after = i == PRAFTR)) {
440 padvise (NULL, "unable to parse %s %s", argp[-2], cp);
448 static struct nexus *
449 newnexus (int (*action)())
451 register struct nexus *p;
453 if ((p = (struct nexus *) calloc ((size_t) 1, sizeof *p)) == NULL)
454 adios (NULL, "unable to allocate component storage");
456 p->n_action = action;
461 #define args(a) a, fp, msgnum, start, stop
462 #define params args (n)
464 register struct nexus *n; \
471 pmatches (FILE *fp, int msgnum, long start, long stop)
476 if (!talked++ && pdebug)
479 return (*head->n_action) (args (head));
484 PRaction (struct nexus *n, int level)
488 for (i = 0; i < level; i++)
489 fprintf (stderr, "| ");
491 if (n->n_action == ORaction) {
492 fprintf (stderr, "OR\n");
493 PRaction (n->n_L_child, level + 1);
494 PRaction (n->n_R_child, level + 1);
497 if (n->n_action == ANDaction) {
498 fprintf (stderr, "AND\n");
499 PRaction (n->n_L_child, level + 1);
500 PRaction (n->n_R_child, level + 1);
503 if (n->n_action == NOTaction) {
504 fprintf (stderr, "NOT\n");
505 PRaction (n->n_L_child, level + 1);
508 if (n->n_action == GREPaction) {
509 fprintf (stderr, "PATTERN(%s) %s\n",
510 n->n_header ? "header" : "body", n->n_patbuf);
513 if (n->n_action == TWSaction) {
514 fprintf (stderr, "TEMPORAL(%s) %s: %s\n",
515 n->n_after ? "after" : "before", n->n_datef,
516 dasctime (&n->n_tws, TW_NULL));
519 fprintf (stderr, "UNKNOWN(0x%x)\n", (unsigned int) (*n->n_action));
527 if ((*n->n_L_child->n_action) (args (n->n_L_child)))
529 return (*n->n_R_child->n_action) (args (n->n_R_child));
537 if (!(*n->n_L_child->n_action) (args (n->n_L_child)))
539 return (*n->n_R_child->n_action) (args (n->n_R_child));
547 return (!(*n->n_L_child->n_action) (args (n->n_L_child)));
552 gcompile (struct nexus *n, char *astr)
556 register char *ep, *dp, *sp, *lastep;
558 dp = (ep = n->n_expbuf) + sizeof n->n_expbuf;
569 if ((c = *sp++) != '*')
596 if ((c = *sp++) == '^') {
603 if (c == '\0' || ep >= dp)
605 } while ((c = *sp++) != ']');
610 if ((c = *sp++) == '\0')
630 register char *p1, *p2, *ebp, *cbp;
633 fseek (fp, start, SEEK_SET);
637 if (body && n->n_header)
644 if (fgets (ibuf, sizeof ibuf, fp) == NULL
645 || (stop && pos >= stop)) {
650 pos += (long) strlen (ibuf);
652 ebp = ibuf + strlen (ibuf);
655 if (lf && c != '\n') {
656 if (c != ' ' && c != '\t') {
675 if (c && p1 < &linebuf[LBSIZE - 1])
685 if (advance (p1, p2))
693 if (*p1 == c || cc[(unsigned char)*p1] == c)
694 if (advance (p1, p2))
701 if (advance (p1, p2))
709 advance (char *alp, char *aep)
711 register char *lp, *ep, *curlp;
718 if (*ep++ == *lp++ || ep[-1] == cc[(unsigned char)lp[-1]])
736 if (cclass (ep, *lp++, 1)) {
743 if (cclass (ep, *lp++, 0)) {
757 while (*lp++ == *ep || cc[(unsigned char)lp[-1]] == *ep)
765 while (cclass (ep, *lp++, ep[-1] == (CCL | STAR)))
773 if (advance (lp, ep))
775 } while (lp > curlp);
779 admonish (NULL, "advance() botch -- you lose big");
786 cclass (char *aset, int ac, int af)
806 tcompile (char *ap, struct tws *tb, int isafter)
808 register struct tws *tw;
810 if ((tw = tws_parse (ap, isafter)) == NULL)
819 tws_parse (char *ap, int isafter)
822 register struct tws *tw, *ts;
824 if ((tw = tws_special (ap)) != NULL) {
825 tw->tw_sec = tw->tw_min = isafter ? 59 : 0;
826 tw->tw_hour = isafter ? 23 : 0;
829 if ((tw = dparsetime (ap)) != NULL)
832 if ((ts = dlocaltimenow ()) == NULL)
835 snprintf (buffer, sizeof(buffer), "%s %s", ap, dtwszone (ts));
836 if ((tw = dparsetime (buffer)) != NULL)
839 snprintf (buffer, sizeof(buffer), "%s %02d:%02d:%02d %s", ap,
840 ts->tw_hour, ts->tw_min, ts->tw_sec, dtwszone (ts));
841 if ((tw = dparsetime (buffer)) != NULL)
844 snprintf (buffer, sizeof(buffer), "%02d %s %04d %s",
845 ts->tw_mday, tw_moty[ts->tw_mon], ts->tw_year, ap);
846 if ((tw = dparsetime (buffer)) != NULL)
849 snprintf (buffer, sizeof(buffer), "%02d %s %04d %s %s",
850 ts->tw_mday, tw_moty[ts->tw_mon], ts->tw_year,
852 if ((tw = dparsetime (buffer)) != NULL)
860 tws_special (char *ap)
864 register struct tws *tw;
867 if (!strcasecmp (ap, "today"))
868 return dlocaltime (&clock);
869 if (!strcasecmp (ap, "yesterday")) {
870 clock -= (long) (60 * 60 * 24);
871 return dlocaltime (&clock);
873 if (!strcasecmp (ap, "tomorrow")) {
874 clock += (long) (60 * 60 * 24);
875 return dlocaltime (&clock);
878 for (i = 0; tw_ldotw[i]; i++)
879 if (!strcasecmp (ap, tw_ldotw[i]))
882 if ((tw = dlocaltime (&clock)) == NULL)
884 if ((i -= tw->tw_wday) > 0)
890 else /* -ddd days ago */
891 i = atoi (ap); /* we should error check this */
893 clock += (long) ((60 * 60 * 24) * i);
894 return dlocaltime (&clock);
904 char buf[BUFSIZ], name[NAMESZ];
905 register struct tws *tw;
907 fseek (fp, start, SEEK_SET);
908 for (state = FLD, bp = NULL;;) {
909 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
914 free (bp), bp = NULL;
915 bp = add (buf, NULL);
916 while (state == FLDPLUS) {
917 state = m_getfld (state, name, buf, sizeof buf, fp);
920 if (!strcasecmp (name, n->n_datef))
930 if (state == LENERR || state == FMTERR)
931 advise (NULL, "format error in message %d", msgnum);
937 adios (NULL, "internal error -- you lose");
942 if ((tw = dparsetime (bp)) == NULL)
943 advise (NULL, "unable to parse %s field in message %d, matching...",
944 n->n_datef, msgnum), state = 1;
946 state = n->n_after ? (twsort (tw, &n->n_tws) > 0)
947 : (twsort (tw, &n->n_tws) < 0);