]> diplodocus.org Git - nmh/blob - uip/picksbr.c
Just reworded the bit about '%s' being safe not to quote (it's only safe not to
[nmh] / uip / picksbr.c
1
2 /*
3 * picksbr.c -- routines to help pick along...
4 *
5 * $Id$
6 */
7
8 #include <h/mh.h>
9 #include <zotnet/tws/tws.h>
10 #include <h/picksbr.h>
11
12 #ifdef TIME_WITH_SYS_TIME
13 # include <sys/time.h>
14 # include <time.h>
15 #else
16 # ifdef TM_IN_SYS_TIME
17 # include <sys/time.h>
18 # else
19 # include <time.h>
20 # endif
21 #endif
22
23 static struct swit parswit[] = {
24 #define PRAND 0
25 { "and", 0 },
26 #define PROR 1
27 { "or", 0 },
28 #define PRNOT 2
29 { "not", 0 },
30 #define PRLBR 3
31 { "lbrace", 0 },
32 #define PRRBR 4
33 { "rbrace", 0 },
34 #define PRCC 5
35 { "cc pattern", 0 },
36 #define PRDATE 6
37 { "date pattern", 0 },
38 #define PRFROM 7
39 { "from pattern", 0 },
40 #define PRSRCH 8
41 { "search pattern", 0 },
42 #define PRSUBJ 9
43 { "subject pattern", 0 },
44 #define PRTO 10
45 { "to pattern", 0 },
46 #define PROTHR 11
47 { "-othercomponent pattern", 15 },
48 #define PRAFTR 12
49 { "after date", 0 },
50 #define PRBEFR 13
51 { "before date", 0 },
52 #define PRDATF 14
53 { "datefield field", 5 },
54 { NULL, 0 }
55 };
56
57 /* DEFINITIONS FOR PATTERN MATCHING */
58
59 /*
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".
65 *
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.
68 */
69
70 #define CCHR 2
71 #define CDOT 4
72 #define CCL 6
73 #define NCCL 8
74 #define CDOL 10
75 #define CEOF 11
76
77 #define STAR 01
78
79 #define LBSIZE 1024
80 #define ESIZE 256
81
82
83 static char linebuf[LBSIZE + 1];
84
85 /* the magic array for case-independence */
86 static char cc[] = {
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,
103 };
104
105 /*
106 * DEFINITIONS FOR NEXUS
107 */
108
109 #define nxtarg() (*argp ? *argp++ : NULL)
110 #define prvarg() argp--
111
112 #define padvise if (!talked++) advise
113
114 struct nexus {
115 int (*n_action)();
116
117 union {
118 /* for {OR,AND,NOT}action */
119 struct {
120 struct nexus *un_L_child;
121 struct nexus *un_R_child;
122 } st1;
123
124 /* for GREPaction */
125 struct {
126 int un_header;
127 int un_circf;
128 char un_expbuf[ESIZE];
129 char *un_patbuf;
130 } st2;
131
132 /* for TWSaction */
133 struct {
134 char *un_datef;
135 int un_after;
136 struct tws un_tws;
137 } st3;
138 } un;
139 };
140
141 #define n_L_child un.st1.un_L_child
142 #define n_R_child un.st1.un_R_child
143
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
148
149 #define n_datef un.st3.un_datef
150 #define n_after un.st3.un_after
151 #define n_tws un.st3.un_tws
152
153 static int talked;
154 static int pdebug = 0;
155
156 static char *datesw;
157 static char **argp;
158
159 static struct nexus *head;
160
161 /*
162 * prototypes for date routines
163 */
164 static struct tws *tws_parse();
165 static struct tws *tws_special();
166
167 /*
168 * static prototypes
169 */
170 static void PRaction();
171 static int gcompile();
172 static int advance();
173 static int cclass();
174 static int tcompile();
175
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();
181
182 static int ORaction();
183 static int ANDaction();
184 static int NOTaction();
185 static int GREPaction();
186 static int TWSaction();
187
188
189 int
190 pcompile (char **vec, char *date)
191 {
192 register char *cp;
193
194 if ((cp = getenv ("MHPDEBUG")) && *cp)
195 pdebug++;
196
197 argp = vec;
198 if ((datesw = date) == NULL)
199 datesw = "date";
200 talked = 0;
201
202 if ((head = parse ()) == NULL)
203 return (talked ? 0 : 1);
204
205 if (*argp) {
206 padvise (NULL, "%s unexpected", *argp);
207 return 0;
208 }
209
210 return 1;
211 }
212
213
214 static struct nexus *
215 parse (void)
216 {
217 register char *cp;
218 register struct nexus *n, *o;
219
220 if ((n = exp1 ()) == NULL || (cp = nxtarg ()) == NULL)
221 return n;
222
223 if (*cp != '-') {
224 padvise (NULL, "%s unexpected", cp);
225 return NULL;
226 }
227
228 if (*++cp == '-')
229 goto header;
230 switch (smatch (cp, parswit)) {
231 case AMBIGSW:
232 ambigsw (cp, parswit);
233 talked++;
234 return NULL;
235 case UNKWNSW:
236 fprintf (stderr, "-%s unknown\n", cp);
237 talked++;
238 return NULL;
239
240 case PROR:
241 o = newnexus (ORaction);
242 o->n_L_child = n;
243 if ((o->n_R_child = parse ()))
244 return o;
245 padvise (NULL, "missing disjunctive");
246 return NULL;
247
248 header: ;
249 default:
250 prvarg ();
251 return n;
252 }
253 }
254
255 static struct nexus *
256 exp1 (void)
257 {
258 register char *cp;
259 register struct nexus *n, *o;
260
261 if ((n = exp2 ()) == NULL || (cp = nxtarg ()) == NULL)
262 return n;
263
264 if (*cp != '-') {
265 padvise (NULL, "%s unexpected", cp);
266 return NULL;
267 }
268
269 if (*++cp == '-')
270 goto header;
271 switch (smatch (cp, parswit)) {
272 case AMBIGSW:
273 ambigsw (cp, parswit);
274 talked++;
275 return NULL;
276 case UNKWNSW:
277 fprintf (stderr, "-%s unknown\n", cp);
278 talked++;
279 return NULL;
280
281 case PRAND:
282 o = newnexus (ANDaction);
283 o->n_L_child = n;
284 if ((o->n_R_child = exp1 ()))
285 return o;
286 padvise (NULL, "missing conjunctive");
287 return NULL;
288
289 header: ;
290 default:
291 prvarg ();
292 return n;
293 }
294 }
295
296
297 static struct nexus *
298 exp2 (void)
299 {
300 register char *cp;
301 register struct nexus *n;
302
303 if ((cp = nxtarg ()) == NULL)
304 return NULL;
305
306 if (*cp != '-') {
307 prvarg ();
308 return exp3 ();
309 }
310
311 if (*++cp == '-')
312 goto header;
313 switch (smatch (cp, parswit)) {
314 case AMBIGSW:
315 ambigsw (cp, parswit);
316 talked++;
317 return NULL;
318 case UNKWNSW:
319 fprintf (stderr, "-%s unknown\n", cp);
320 talked++;
321 return NULL;
322
323 case PRNOT:
324 n = newnexus (NOTaction);
325 if ((n->n_L_child = exp3 ()))
326 return n;
327 padvise (NULL, "missing negation");
328 return NULL;
329
330 header: ;
331 default:
332 prvarg ();
333 return exp3 ();
334 }
335 }
336
337 static struct nexus *
338 exp3 (void)
339 {
340 int i;
341 register char *cp, *dp;
342 char buffer[BUFSIZ], temp[64];
343 register struct nexus *n;
344
345 if ((cp = nxtarg ()) == NULL)
346 return NULL;
347
348 if (*cp != '-') {
349 padvise (NULL, "%s unexpected", cp);
350 return NULL;
351 }
352
353 if (*++cp == '-') {
354 dp = ++cp;
355 goto header;
356 }
357 switch (i = smatch (cp, parswit)) {
358 case AMBIGSW:
359 ambigsw (cp, parswit);
360 talked++;
361 return NULL;
362 case UNKWNSW:
363 fprintf (stderr, "-%s unknown\n", cp);
364 talked++;
365 return NULL;
366
367 case PRLBR:
368 if ((n = parse ()) == NULL) {
369 padvise (NULL, "missing group");
370 return NULL;
371 }
372 if ((cp = nxtarg ()) == NULL) {
373 padvise (NULL, "missing -rbrace");
374 return NULL;
375 }
376 if (*cp++ == '-' && smatch (cp, parswit) == PRRBR)
377 return n;
378 padvise (NULL, "%s unexpected", --cp);
379 return NULL;
380
381 default:
382 prvarg ();
383 return NULL;
384
385 case PRCC:
386 case PRDATE:
387 case PRFROM:
388 case PRTO:
389 case PRSUBJ:
390 strncpy(temp, parswit[i].sw, sizeof(temp));
391 temp[sizeof(temp) - 1] = '\0';
392 dp = *brkstring (temp, " ", NULL);
393 header: ;
394 if (!(cp = nxtarg ())) {/* allow -xyz arguments */
395 padvise (NULL, "missing argument to %s", argp[-2]);
396 return NULL;
397 }
398 n = newnexus (GREPaction);
399 n->n_header = 1;
400 snprintf (buffer, sizeof(buffer), "^%s[ \t]*:.*%s", dp, cp);
401 dp = buffer;
402 goto pattern;
403
404 case PRSRCH:
405 n = newnexus (GREPaction);
406 n->n_header = 0;
407 if (!(cp = nxtarg ())) {/* allow -xyz arguments */
408 padvise (NULL, "missing argument to %s", argp[-2]);
409 return NULL;
410 }
411 dp = cp;
412 pattern: ;
413 if (!gcompile (n, dp)) {
414 padvise (NULL, "pattern error in %s %s", argp[-2], cp);
415 return NULL;
416 }
417 n->n_patbuf = getcpy (dp);
418 return n;
419
420 case PROTHR:
421 padvise (NULL, "internal error!");
422 return NULL;
423
424 case PRDATF:
425 if (!(datesw = nxtarg ()) || *datesw == '-') {
426 padvise (NULL, "missing argument to %s", argp[-2]);
427 return NULL;
428 }
429 return exp3 ();
430
431 case PRAFTR:
432 case PRBEFR:
433 if (!(cp = nxtarg ())) {/* allow -xyz arguments */
434 padvise (NULL, "missing argument to %s", argp[-2]);
435 return NULL;
436 }
437 n = newnexus (TWSaction);
438 n->n_datef = datesw;
439 if (!tcompile (cp, &n->n_tws, n->n_after = i == PRAFTR)) {
440 padvise (NULL, "unable to parse %s %s", argp[-2], cp);
441 return NULL;
442 }
443 return n;
444 }
445 }
446
447
448 static struct nexus *
449 newnexus (int (*action)())
450 {
451 register struct nexus *p;
452
453 if ((p = (struct nexus *) calloc ((size_t) 1, sizeof *p)) == NULL)
454 adios (NULL, "unable to allocate component storage");
455
456 p->n_action = action;
457 return p;
458 }
459
460
461 #define args(a) a, fp, msgnum, start, stop
462 #define params args (n)
463 #define plist \
464 register struct nexus *n; \
465 register FILE *fp; \
466 int msgnum; \
467 long start, \
468 stop;
469
470 int
471 pmatches (FILE *fp, int msgnum, long start, long stop)
472 {
473 if (!head)
474 return 1;
475
476 if (!talked++ && pdebug)
477 PRaction (head, 0);
478
479 return (*head->n_action) (args (head));
480 }
481
482
483 static void
484 PRaction (struct nexus *n, int level)
485 {
486 register int i;
487
488 for (i = 0; i < level; i++)
489 fprintf (stderr, "| ");
490
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);
495 return;
496 }
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);
501 return;
502 }
503 if (n->n_action == NOTaction) {
504 fprintf (stderr, "NOT\n");
505 PRaction (n->n_L_child, level + 1);
506 return;
507 }
508 if (n->n_action == GREPaction) {
509 fprintf (stderr, "PATTERN(%s) %s\n",
510 n->n_header ? "header" : "body", n->n_patbuf);
511 return;
512 }
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));
517 return;
518 }
519 fprintf (stderr, "UNKNOWN(0x%x)\n", (unsigned int) (*n->n_action));
520 }
521
522
523 static int
524 ORaction (params)
525 plist
526 {
527 if ((*n->n_L_child->n_action) (args (n->n_L_child)))
528 return 1;
529 return (*n->n_R_child->n_action) (args (n->n_R_child));
530 }
531
532
533 static int
534 ANDaction (params)
535 plist
536 {
537 if (!(*n->n_L_child->n_action) (args (n->n_L_child)))
538 return 0;
539 return (*n->n_R_child->n_action) (args (n->n_R_child));
540 }
541
542
543 static int
544 NOTaction (params)
545 plist
546 {
547 return (!(*n->n_L_child->n_action) (args (n->n_L_child)));
548 }
549
550
551 static int
552 gcompile (struct nexus *n, char *astr)
553 {
554 register int c;
555 int cclcnt;
556 register char *ep, *dp, *sp, *lastep;
557
558 dp = (ep = n->n_expbuf) + sizeof n->n_expbuf;
559 sp = astr;
560 if (*sp == '^') {
561 n->n_circf = 1;
562 sp++;
563 }
564 else
565 n->n_circf = 0;
566 for (;;) {
567 if (ep >= dp)
568 goto cerror;
569 if ((c = *sp++) != '*')
570 lastep = ep;
571 switch (c) {
572 case '\0':
573 *ep++ = CEOF;
574 return 1;
575
576 case '.':
577 *ep++ = CDOT;
578 continue;
579
580 case '*':
581 if (lastep == 0)
582 goto defchar;
583 *lastep |= STAR;
584 continue;
585
586 case '$':
587 if (*sp != '\0')
588 goto defchar;
589 *ep++ = CDOL;
590 continue;
591
592 case '[':
593 *ep++ = CCL;
594 *ep++ = 0;
595 cclcnt = 1;
596 if ((c = *sp++) == '^') {
597 c = *sp++;
598 ep[-2] = NCCL;
599 }
600 do {
601 *ep++ = c;
602 cclcnt++;
603 if (c == '\0' || ep >= dp)
604 goto cerror;
605 } while ((c = *sp++) != ']');
606 lastep[1] = cclcnt;
607 continue;
608
609 case '\\':
610 if ((c = *sp++) == '\0')
611 goto cerror;
612 defchar:
613 default:
614 *ep++ = CCHR;
615 *ep++ = c;
616 }
617 }
618
619 cerror: ;
620 return 0;
621 }
622
623
624 static int
625 GREPaction (params)
626 plist
627 {
628 int c, body, lf;
629 long pos = start;
630 register char *p1, *p2, *ebp, *cbp;
631 char ibuf[BUFSIZ];
632
633 fseek (fp, start, SEEK_SET);
634 body = 0;
635 ebp = cbp = ibuf;
636 for (;;) {
637 if (body && n->n_header)
638 return 0;
639 p1 = linebuf;
640 p2 = cbp;
641 lf = 0;
642 for (;;) {
643 if (p2 >= ebp) {
644 if (fgets (ibuf, sizeof ibuf, fp) == NULL
645 || (stop && pos >= stop)) {
646 if (lf)
647 break;
648 return 0;
649 }
650 pos += (long) strlen (ibuf);
651 p2 = ibuf;
652 ebp = ibuf + strlen (ibuf);
653 }
654 c = *p2++;
655 if (lf && c != '\n') {
656 if (c != ' ' && c != '\t') {
657 --p2;
658 break;
659 }
660 else
661 lf = 0;
662 }
663 if (c == '\n') {
664 if (body)
665 break;
666 else {
667 if (lf) {
668 body++;
669 break;
670 }
671 lf++;
672 c = ' ';
673 }
674 }
675 if (c && p1 < &linebuf[LBSIZE - 1])
676 *p1++ = c;
677 }
678
679 *p1++ = 0;
680 cbp = p2;
681 p1 = linebuf;
682 p2 = n->n_expbuf;
683
684 if (n->n_circf) {
685 if (advance (p1, p2))
686 return 1;
687 continue;
688 }
689
690 if (*p2 == CCHR) {
691 c = p2[1];
692 do {
693 if (*p1 == c || cc[(unsigned char)*p1] == c)
694 if (advance (p1, p2))
695 return 1;
696 } while (*p1++);
697 continue;
698 }
699
700 do {
701 if (advance (p1, p2))
702 return 1;
703 } while (*p1++);
704 }
705 }
706
707
708 static int
709 advance (char *alp, char *aep)
710 {
711 register char *lp, *ep, *curlp;
712
713 lp = alp;
714 ep = aep;
715 for (;;)
716 switch (*ep++) {
717 case CCHR:
718 if (*ep++ == *lp++ || ep[-1] == cc[(unsigned char)lp[-1]])
719 continue;
720 return 0;
721
722 case CDOT:
723 if (*lp++)
724 continue;
725 return 0;
726
727 case CDOL:
728 if (*lp == 0)
729 continue;
730 return 0;
731
732 case CEOF:
733 return 1;
734
735 case CCL:
736 if (cclass (ep, *lp++, 1)) {
737 ep += *ep;
738 continue;
739 }
740 return 0;
741
742 case NCCL:
743 if (cclass (ep, *lp++, 0)) {
744 ep += *ep;
745 continue;
746 }
747 return 0;
748
749 case CDOT | STAR:
750 curlp = lp;
751 while (*lp++)
752 continue;
753 goto star;
754
755 case CCHR | STAR:
756 curlp = lp;
757 while (*lp++ == *ep || cc[(unsigned char)lp[-1]] == *ep)
758 continue;
759 ep++;
760 goto star;
761
762 case CCL | STAR:
763 case NCCL | STAR:
764 curlp = lp;
765 while (cclass (ep, *lp++, ep[-1] == (CCL | STAR)))
766 continue;
767 ep += *ep;
768 goto star;
769
770 star:
771 do {
772 lp--;
773 if (advance (lp, ep))
774 return (1);
775 } while (lp > curlp);
776 return 0;
777
778 default:
779 admonish (NULL, "advance() botch -- you lose big");
780 return 0;
781 }
782 }
783
784
785 static int
786 cclass (char *aset, int ac, int af)
787 {
788 register int n;
789 register char c,
790 *set;
791
792 set = aset;
793 if ((c = ac) == 0)
794 return (0);
795
796 n = *set++;
797 while (--n)
798 if (*set++ == c)
799 return (af);
800
801 return (!af);
802 }
803
804
805 static int
806 tcompile (char *ap, struct tws *tb, int isafter)
807 {
808 register struct tws *tw;
809
810 if ((tw = tws_parse (ap, isafter)) == NULL)
811 return 0;
812
813 twscopy (tb, tw);
814 return 1;
815 }
816
817
818 static struct tws *
819 tws_parse (char *ap, int isafter)
820 {
821 char buffer[BUFSIZ];
822 register struct tws *tw, *ts;
823
824 if ((tw = tws_special (ap)) != NULL) {
825 tw->tw_sec = tw->tw_min = isafter ? 59 : 0;
826 tw->tw_hour = isafter ? 23 : 0;
827 return tw;
828 }
829 if ((tw = dparsetime (ap)) != NULL)
830 return tw;
831
832 if ((ts = dlocaltimenow ()) == NULL)
833 return NULL;
834
835 snprintf (buffer, sizeof(buffer), "%s %s", ap, dtwszone (ts));
836 if ((tw = dparsetime (buffer)) != NULL)
837 return tw;
838
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)
842 return tw;
843
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)
847 return tw;
848
849 snprintf (buffer, sizeof(buffer), "%02d %s %04d %s %s",
850 ts->tw_mday, tw_moty[ts->tw_mon], ts->tw_year,
851 ap, dtwszone (ts));
852 if ((tw = dparsetime (buffer)) != NULL)
853 return tw;
854
855 return NULL;
856 }
857
858
859 static struct tws *
860 tws_special (char *ap)
861 {
862 int i;
863 time_t clock;
864 register struct tws *tw;
865
866 time (&clock);
867 if (!strcasecmp (ap, "today"))
868 return dlocaltime (&clock);
869 if (!strcasecmp (ap, "yesterday")) {
870 clock -= (long) (60 * 60 * 24);
871 return dlocaltime (&clock);
872 }
873 if (!strcasecmp (ap, "tomorrow")) {
874 clock += (long) (60 * 60 * 24);
875 return dlocaltime (&clock);
876 }
877
878 for (i = 0; tw_ldotw[i]; i++)
879 if (!strcasecmp (ap, tw_ldotw[i]))
880 break;
881 if (tw_ldotw[i]) {
882 if ((tw = dlocaltime (&clock)) == NULL)
883 return NULL;
884 if ((i -= tw->tw_wday) > 0)
885 i -= 7;
886 }
887 else
888 if (*ap != '-')
889 return NULL;
890 else /* -ddd days ago */
891 i = atoi (ap); /* we should error check this */
892
893 clock += (long) ((60 * 60 * 24) * i);
894 return dlocaltime (&clock);
895 }
896
897
898 static int
899 TWSaction (params)
900 plist
901 {
902 int state;
903 register char *bp;
904 char buf[BUFSIZ], name[NAMESZ];
905 register struct tws *tw;
906
907 fseek (fp, start, SEEK_SET);
908 for (state = FLD, bp = NULL;;) {
909 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
910 case FLD:
911 case FLDEOF:
912 case FLDPLUS:
913 if (bp != NULL)
914 free (bp), bp = NULL;
915 bp = add (buf, NULL);
916 while (state == FLDPLUS) {
917 state = m_getfld (state, name, buf, sizeof buf, fp);
918 bp = add (buf, bp);
919 }
920 if (!strcasecmp (name, n->n_datef))
921 break;
922 if (state != FLDEOF)
923 continue;
924
925 case BODY:
926 case BODYEOF:
927 case FILEEOF:
928 case LENERR:
929 case FMTERR:
930 if (state == LENERR || state == FMTERR)
931 advise (NULL, "format error in message %d", msgnum);
932 if (bp != NULL)
933 free (bp);
934 return 0;
935
936 default:
937 adios (NULL, "internal error -- you lose");
938 }
939 break;
940 }
941
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;
945 else
946 state = n->n_after ? (twsort (tw, &n->n_tws) > 0)
947 : (twsort (tw, &n->n_tws) < 0);
948
949 if (bp != NULL)
950 free (bp);
951 return state;
952 }