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