If $LIBTOOL is empty we should not try to run it.
[mmh] / 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 <h/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 }