1 /* picksbr.c - routines to help pick along... */
3 static char ident[] = "@(#)$Id: picksbr.c,v 1.8 1992/12/15 00:20:22 jromine Exp $";
7 #include "../zotnet/tws.h"
12 static struct swit parswit[] = {
37 "-othercomponent pattern", 15,
49 /*
\f DEFINITIONS FOR PATTERN MATCHING */
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".
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.
75 static char linebuf[LBSIZE + 1];
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,
96 /*
\f DEFINITIONS FOR DATE MATCHING */
98 static struct tws *tws_parse (), *tws_special ();
103 /*
\f DEFINITIONS FOR NEXUS */
105 #define nxtarg() (*argp ? *argp++ : NULL)
106 #define prvarg() argp--
109 #define padvise if (!talked++) advise
116 struct { /* for {OR,AND,NOT}action */
117 struct nexus *un_L_child;
118 struct nexus *un_R_child;
120 #define n_L_child un.st1.un_L_child
121 #define n_R_child un.st1.un_R_child
123 struct { /* for GREPaction */
126 char un_expbuf[ESIZE];
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
134 struct { /* for TWSaction */
139 #define n_datef un.st3.un_datef
140 #define n_after un.st3.un_after
141 #define n_tws un.st3.un_tws
147 static int pdebug = 0;
152 static struct nexus *head;
154 static void PRaction();
155 static int gcompile(), advance(), cclass(), tcompile();
157 static struct nexus *parse (), *exp1 (), *exp2 (), *exp3 (), *newnexus ();
159 static int ORaction (), ANDaction (), NOTaction (), GREPaction (),
164 int pcompile (vec, date)
170 if ((cp = getenv ("MHPDEBUG")) && *cp)
174 if ((datesw = date) == NULL)
178 if ((head = parse ()) == NULL)
179 return (talked ? 0 : 1);
182 padvise (NULLCP, "%s unexpected", *argp);
191 static struct nexus *parse () {
193 register struct nexus *n,
196 if ((n = exp1 ()) == NULL || (cp = nxtarg ()) == NULL)
200 padvise (NULLCP, "%s unexpected", cp);
206 switch (smatch (cp, parswit)) {
208 ambigsw (cp, parswit);
212 fprintf (stderr, "-%s unknown\n", cp);
217 o = newnexus (ORaction);
219 if (o -> n_R_child = parse ())
221 padvise (NULLCP, "missing disjunctive");
233 static struct nexus *exp1 () {
235 register struct nexus *n,
238 if ((n = exp2 ()) == NULL || (cp = nxtarg ()) == NULL)
242 padvise (NULLCP, "%s unexpected", cp);
248 switch (smatch (cp, parswit)) {
250 ambigsw (cp, parswit);
254 fprintf (stderr, "-%s unknown\n", cp);
259 o = newnexus (ANDaction);
261 if (o -> n_R_child = exp1 ())
263 padvise (NULLCP, "missing conjunctive");
275 static struct nexus *exp2 () {
277 register struct nexus *n;
279 if ((cp = nxtarg ()) == NULL)
289 switch (smatch (cp, parswit)) {
291 ambigsw (cp, parswit);
295 fprintf (stderr, "-%s unknown\n", cp);
300 n = newnexus (NOTaction);
301 if (n -> n_L_child = exp3 ())
303 padvise (NULLCP, "missing negation");
315 static struct nexus *exp3 () {
319 char buffer[BUFSIZ], temp[64];
320 register struct nexus *n;
322 if ((cp = nxtarg ()) == NULL)
326 padvise (NULLCP, "%s unexpected", cp);
334 switch (i = smatch (cp, parswit)) {
336 ambigsw (cp, parswit);
340 fprintf (stderr, "-%s unknown\n", cp);
345 if ((n = parse ()) == NULL) {
346 padvise (NULLCP, "missing group");
349 if ((cp = nxtarg ()) == NULL) {
350 padvise (NULLCP, "missing -rbrace");
353 if (*cp++ == '-' && smatch (cp, parswit) == PRRBR)
355 padvise (NULLCP, "%s unexpected", --cp);
367 strncpy(temp, parswit[i].sw, sizeof(temp));
368 temp[sizeof(temp) - 1] = '\0';
369 dp = *brkstring (temp, " ", NULLCP);
371 if (!(cp = nxtarg ())) {/* allow -xyz arguments */
372 padvise (NULLCP, "missing argument to %s", argp[-2]);
375 n = newnexus (GREPaction);
377 (void) sprintf (buffer, "^%s[ \t]*:.*%s", dp, cp);
382 n = newnexus (GREPaction);
384 if (!(cp = nxtarg ())) {/* allow -xyz arguments */
385 padvise (NULLCP, "missing argument to %s", argp[-2]);
390 if (!gcompile (n, dp)) {
391 padvise (NULLCP, "pattern error in %s %s", argp[-2], cp);
394 n -> n_patbuf = getcpy (dp);
398 padvise (NULLCP, "internal error!");
402 if (!(datesw = nxtarg ()) || *datesw == '-') {
403 padvise (NULLCP, "missing argument to %s", argp[-2]);
410 if (!(cp = nxtarg ())) {/* allow -xyz arguments */
411 padvise (NULLCP, "missing argument to %s", argp[-2]);
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);
426 static struct nexus *newnexus (action)
427 register int (*action) ();
429 register struct nexus *p;
431 if ((p = (struct nexus *) calloc ((unsigned) 1, sizeof *p)) == NULL)
432 adios (NULLCP, "unable to allocate component storage");
434 p -> n_action = action;
440 #define args(a) a, fp, msgnum, start, stop
441 #define params args (n)
443 register struct nexus *n; \
449 int pmatches (fp, msgnum, start, stop)
458 if (!talked++ && pdebug)
461 return (*head -> n_action) (args (head));
466 static void PRaction (n, level)
467 register struct nexus *n;
472 for (i = 0; i < level; i++)
473 fprintf (stderr, "| ");
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);
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);
487 if (n -> n_action == NOTaction) {
488 fprintf (stderr, "NOT\n");
489 PRaction (n -> n_L_child, level + 1);
492 if (n -> n_action == GREPaction) {
493 fprintf (stderr, "PATTERN(%s) %s\n",
494 n -> n_header ? "header" : "body", n -> n_patbuf);
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));
503 fprintf (stderr, "UNKNOWN(0x%x)\n", (*n -> n_action));
508 static int ORaction (params)
511 if ((*n -> n_L_child -> n_action) (args (n -> n_L_child)))
513 return (*n -> n_R_child -> n_action) (args (n -> n_R_child));
517 static int ANDaction (params)
520 if (!(*n -> n_L_child -> n_action) (args (n -> n_L_child)))
522 return (*n -> n_R_child -> n_action) (args (n -> n_R_child));
526 static int NOTaction (params)
529 return (!(*n -> n_L_child -> n_action) (args (n -> n_L_child)));
534 static int gcompile (n, astr)
535 register struct nexus *n;
545 dp = (ep = n -> n_expbuf) + sizeof n -> n_expbuf;
556 if ((c = *sp++) != '*')
583 if ((c = *sp++) == '^') {
590 if (c == '\0' || ep >= dp)
592 } while ((c = *sp++) != ']');
597 if ((c = *sp++) == '\0')
614 static int GREPaction (params)
627 (void) fseek (fp, start, 0);
631 if (body && n -> n_header)
638 if (fgets (ibuf, sizeof ibuf, fp) == NULL
639 || (stop && pos >= stop)) {
644 pos += (long) strlen (ibuf);
646 ebp = ibuf + strlen (ibuf);
650 if (c != ' ' && c != '\t') {
667 if (c && p1 < &linebuf[LBSIZE - 1])
677 if (advance (p1, p2))
685 if (*p1 == c || cc[*p1] == c)
686 if (advance (p1, p2))
693 if (advance (p1, p2))
701 static int advance (alp, aep)
714 if (*ep++ == *lp++ || ep[-1] == cc[lp[-1]])
732 if (cclass (ep, *lp++, 1)) {
739 if (cclass (ep, *lp++, 0)) {
753 while (*lp++ == *ep || cc[lp[-1]] == *ep)
761 while (cclass (ep, *lp++, ep[-1] == (CCL | STAR)))
769 if (advance (lp, ep))
771 } while (lp > curlp);
775 admonish (NULLCP, "advance() botch -- you lose big");
782 static int cclass (aset, ac, af)
803 static int tcompile (ap, tb, isafter)
805 register struct tws *tb;
808 register struct tws *tw;
810 if ((tw = tws_parse (ap, isafter)) == NULL)
819 static struct tws *tws_parse (ap, isafter)
824 register struct tws *tw,
827 if ((tw = tws_special (ap)) != NULL) {
828 tw -> tw_sec = tw -> tw_min = isafter ? 59 : 0;
829 tw -> tw_hour = isafter ? 23 : 0;
832 if ((tw = dparsetime (ap)) != NULL)
835 if ((ts = dtwstime ()) == NULL)
838 (void) sprintf (buffer, "%s %s", ap, dtwszone (ts));
839 if ((tw = dparsetime (buffer)) != NULL)
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)
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)
852 (void) sprintf (buffer, "%02d %s %04d %s %s",
853 ts -> tw_mday, tw_moty[ts -> tw_mon], ts -> tw_year,
855 if ((tw = dparsetime (buffer)) != NULL)
863 static struct tws *tws_special (ap)
868 register struct tws *tw;
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);
877 if (uleq (ap, "Tomorrow")) {
878 clock += (long) (60 * 60 * 24);
879 return dlocaltime (&clock);
882 for (i = 0; tw_ldotw[i]; i++)
883 if (uleq (ap, tw_ldotw[i]))
886 if ((tw = dlocaltime (&clock)) == NULL)
888 if ((i -= tw -> tw_wday) > 0)
894 else /* -ddd days ago */
895 i = atoi (ap); /* we should error check this */
897 clock += (long) ((60 * 60 * 24) * i);
898 return dlocaltime (&clock);
905 static int TWSaction (params)
912 register struct tws *tw;
914 (void) fseek (fp, start, 0);
915 for (state = FLD, bp = NULL;;) {
916 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
921 free (bp), bp = NULL;
922 bp = add (buf, NULLCP);
923 while (state == FLDPLUS) {
924 state = m_getfld (state, name, buf, sizeof buf, fp);
927 if (uleq (name, n -> n_datef))
937 if (state == LENERR || state == FMTERR)
938 advise (NULLCP, "format error in message %d", msgnum);
944 adios (NULLCP, "internal error -- you lose");
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;
955 state = n -> n_after ? (twsort (tw, &n -> n_tws) > 0)
956 : (twsort (tw, &n -> n_tws) < 0);