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