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