]> diplodocus.org Git - nmh/blobdiff - uip/picksbr.c
Escape literal leading full stop in man/new.man.
[nmh] / uip / picksbr.c
index 1154f46c50b947a6a1b2d81d635cc253927df312..6faa108ffcef4973ed3b27ae15722000b43d6a01 100644 (file)
@@ -2,8 +2,6 @@
 /*
  * picksbr.c -- routines to help pick along...
  *
- * $Id$
- *
  * This code is Copyright (c) 2002, by the authors of nmh.  See the
  * COPYRIGHT file in the root directory of the nmh distribution for
  * complete copyright information.
 #include <h/picksbr.h>
 #include <h/utils.h>
 
-#ifdef TIME_WITH_SYS_TIME
+#ifdef HAVE_SYS_TIME_H
 # include <sys/time.h>
-# include <time.h>
-#else
-# ifdef TM_IN_SYS_TIME
-#  include <sys/time.h>
-# else
-#  include <time.h>
-# endif
 #endif
-
-static struct swit parswit[] = {
-#define        PRAND                   0
-    { "and", 0 },
-#define        PROR                    1
-    { "or", 0 },
-#define        PRNOT                   2
-    { "not", 0 },
-#define        PRLBR                   3
-    { "lbrace", 0 },
-#define        PRRBR                   4
-    { "rbrace", 0 },
-#define        PRCC                    5
-    { "cc  pattern", 0 },
-#define        PRDATE                  6
-    { "date  pattern", 0 },
-#define        PRFROM                  7
-    { "from  pattern", 0 },
-#define        PRSRCH                  8
-    { "search  pattern", 0 },
-#define        PRSUBJ                  9
-    { "subject  pattern", 0 },
-#define        PRTO                   10
-    { "to  pattern", 0 },
-#define        PROTHR                 11
-    { "-othercomponent  pattern", 15 },
-#define        PRAFTR                 12
-    { "after date", 0 },
-#define        PRBEFR                 13
-    { "before date", 0 },
-#define        PRDATF                 14
-    { "datefield field", 5 },
-    { NULL, 0 }
-};
+#include <time.h>
+
+#define PARSE_SWITCHES \
+    X("and", 0, PRAND) \
+    X("or", 0, PROR) \
+    X("not", 0, PRNOT) \
+    X("lbrace", 0, PRLBR) \
+    X("rbrace", 0, PRRBR) \
+    X("cc  pattern", 0, PRCC) \
+    X("date  pattern", 0, PRDATE) \
+    X("from  pattern", 0, PRFROM) \
+    X("search  pattern", 0, PRSRCH) \
+    X("subject  pattern", 0, PRSUBJ) \
+    X("to  pattern", 0, PRTO) \
+    X("-othercomponent  pattern", 15, PROTHR) \
+    X("after date", 0, PRAFTR) \
+    X("before date", 0, PRBEFR) \
+    X("datefield field", 5, PRDATF) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(PARSE);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(PARSE, parswit);
+#undef X
 
 /* DEFINITIONS FOR PATTERN MATCHING */
 
@@ -82,13 +65,14 @@ static struct swit parswit[] = {
 #define        STAR    01
 
 #define LBSIZE  1024
-#define        ESIZE   256
+#define        ESIZE   1024
 
 
 static char linebuf[LBSIZE + 1];
+static char decoded_linebuf[LBSIZE + 1];
 
 /* the magic array for case-independence */
-static char cc[] = {
+static unsigned char cc[] = {
        0000,0001,0002,0003,0004,0005,0006,0007,
        0010,0011,0012,0013,0014,0015,0016,0017,
        0020,0021,0022,0023,0024,0025,0026,0027,
@@ -105,6 +89,23 @@ static char cc[] = {
        0150,0151,0152,0153,0154,0155,0156,0157,
        0160,0161,0162,0163,0164,0165,0166,0167,
        0170,0171,0172,0173,0174,0175,0176,0177,
+
+       0200,0201,0202,0203,0204,0205,0206,0207,
+       0210,0211,0212,0213,0214,0215,0216,0217,
+       0220,0221,0222,0223,0224,0225,0226,0227,
+       0230,0231,0232,0233,0234,0235,0236,0237,
+       0240,0241,0242,0243,0244,0245,0246,0247,
+       0250,0251,0252,0253,0254,0255,0256,0257,
+       0260,0261,0262,0263,0264,0265,0266,0267,
+       0270,0271,0272,0273,0274,0275,0276,0277,
+       0300,0301,0302,0303,0304,0305,0306,0307,
+       0310,0311,0312,0313,0314,0315,0316,0317,
+       0320,0321,0322,0323,0324,0325,0326,0327,
+       0330,0331,0332,0333,0334,0335,0336,0337,
+       0340,0341,0342,0343,0344,0345,0346,0347,
+       0350,0351,0352,0353,0354,0355,0356,0357,
+       0360,0361,0362,0363,0364,0365,0366,0367,
+       0370,0371,0372,0373,0374,0375,0376,0377,
 };
 
 /*
@@ -156,7 +157,6 @@ struct nexus {
 #define        n_tws    un.st3.un_tws
 
 static int talked;
-static int pdebug = 0;
 
 static char *datesw;
 static char **argp;
@@ -166,23 +166,23 @@ static struct nexus *head;
 /*
  * prototypes for date routines
  */
-static struct tws *tws_parse();
-static struct tws *tws_special();
+static struct tws *tws_parse(char *, int);
+static struct tws *tws_special(char *);
 
 /*
  * static prototypes
  */
-static void PRaction();
-static int gcompile();
-static int advance();
-static int cclass();
-static int tcompile();
-
-static struct nexus *parse();
-static struct nexus *exp1();
-static struct nexus *exp2();
-static struct nexus *exp3();
-static struct nexus *newnexus();
+static void PRaction(struct nexus *, int);
+static int gcompile(struct nexus *, char *);
+static int advance(char *, char *);
+static int cclass(unsigned char *, int, int);
+static int tcompile(char *, struct tws *, int);
+
+static struct nexus *parse(void);
+static struct nexus *nexp1(void);
+static struct nexus *nexp2(void);
+static struct nexus *nexp3(void);
+static struct nexus *newnexus(int (*)());
 
 static int ORaction();
 static int ANDaction();
@@ -194,11 +194,6 @@ static int TWSaction();
 int
 pcompile (char **vec, char *date)
 {
-    register char *cp;
-
-    if ((cp = getenv ("MHPDEBUG")) && *cp)
-       pdebug++;
-
     argp = vec;
     if ((datesw = date) == NULL)
        datesw = "date";
@@ -219,10 +214,10 @@ pcompile (char **vec, char *date)
 static struct nexus *
 parse (void)
 {
-    register char  *cp;
-    register struct nexus *n, *o;
+    char  *cp;
+    struct nexus *n, *o;
 
-    if ((n = exp1 ()) == NULL || (cp = nxtarg ()) == NULL)
+    if ((n = nexp1 ()) == NULL || (cp = nxtarg ()) == NULL)
        return n;
 
     if (*cp != '-') {
@@ -248,6 +243,7 @@ parse (void)
            if ((o->n_R_child = parse ()))
                return o;
            padvise (NULL, "missing disjunctive");
+           free (o);
            return NULL;
 
 header: ;
@@ -258,16 +254,17 @@ header: ;
 }
 
 static struct nexus *
-exp1 (void)
+nexp1 (void)
 {
-    register char *cp;
-    register struct nexus *n, *o;
+    char *cp;
+    struct nexus *n, *o;
 
-    if ((n = exp2 ()) == NULL || (cp = nxtarg ()) == NULL)
+    if ((n = nexp2 ()) == NULL || (cp = nxtarg ()) == NULL)
        return n;
 
     if (*cp != '-') {
        padvise (NULL, "%s unexpected", cp);
+       free (n);
        return NULL;
     }
 
@@ -277,18 +274,21 @@ exp1 (void)
        case AMBIGSW: 
            ambigsw (cp, parswit);
            talked++;
+           free (n);
            return NULL;
        case UNKWNSW: 
            fprintf (stderr, "-%s unknown\n", cp);
            talked++;
+           free (n);
            return NULL;
 
        case PRAND: 
            o = newnexus (ANDaction);
            o->n_L_child = n;
-           if ((o->n_R_child = exp1 ()))
+           if ((o->n_R_child = nexp1 ()))
                return o;
            padvise (NULL, "missing conjunctive");
+           free (o);
            return NULL;
 
 header: ;
@@ -300,17 +300,17 @@ header: ;
 
 
 static struct nexus *
-exp2 (void)
+nexp2 (void)
 {
-    register char *cp;
-    register struct nexus *n;
+    char *cp;
+    struct nexus *n;
 
     if ((cp = nxtarg ()) == NULL)
        return NULL;
 
     if (*cp != '-') {
        prvarg ();
-       return exp3 ();
+       return nexp3 ();
     }
 
     if (*++cp == '-')
@@ -327,25 +327,26 @@ exp2 (void)
 
        case PRNOT: 
            n = newnexus (NOTaction);
-           if ((n->n_L_child = exp3 ()))
+           if ((n->n_L_child = nexp3 ()))
                return n;
            padvise (NULL, "missing negation");
+           free (n);
            return NULL;
 
 header: ;
        default: 
            prvarg ();
-           return exp3 ();
+           return nexp3 ();
     }
 }
 
 static struct nexus *
-exp3 (void)
+nexp3 (void)
 {
     int i;
-    register char *cp, *dp;
+    char *cp, *dp;
     char buffer[BUFSIZ], temp[64];
-    register struct nexus *n;
+    struct nexus *n;
 
     if ((cp = nxtarg ()) == NULL)
        return NULL;
@@ -411,15 +412,17 @@ exp3 (void)
            n->n_header = 0;
            if (!(cp = nxtarg ())) {/* allow -xyz arguments */
                padvise (NULL, "missing argument to %s", argp[-2]);
+               free (n);
                return NULL;
            }
            dp = cp;
     pattern: ;
            if (!gcompile (n, dp)) {
                padvise (NULL, "pattern error in %s %s", argp[-2], cp);
+               free (n);
                return NULL;
            }
-           n->n_patbuf = getcpy (dp);
+           n->n_patbuf = mh_xstrdup(dp);
            return n;
 
        case PROTHR: 
@@ -431,7 +434,7 @@ exp3 (void)
                padvise (NULL, "missing argument to %s", argp[-2]);
                return NULL;
            }
-           return exp3 ();
+           return nexp3 ();
 
        case PRAFTR: 
        case PRBEFR: 
@@ -443,6 +446,7 @@ exp3 (void)
            n->n_datef = datesw;
            if (!tcompile (cp, &n->n_tws, n->n_after = i == PRAFTR)) {
                padvise (NULL, "unable to parse %s %s", argp[-2], cp);
+               free (n);
                return NULL;
            }
            return n;
@@ -453,11 +457,9 @@ exp3 (void)
 static struct nexus *
 newnexus (int (*action)())
 {
-    register struct nexus *p;
-
-    if ((p = (struct nexus *) calloc ((size_t) 1, sizeof *p)) == NULL)
-       adios (NULL, "unable to allocate component storage");
+    struct nexus *p;
 
+    NEW0(p);
     p->n_action = action;
     return p;
 }
@@ -466,19 +468,19 @@ newnexus (int (*action)())
 #define        args(a) a, fp, msgnum, start, stop
 #define        params  args (n)
 #define        plist   \
-           register struct nexus  *n; \
-           register FILE *fp; \
+           struct nexus  *n; \
+           FILE *fp; \
            int msgnum; \
            long    start, \
                    stop;
 
 int
-pmatches (FILE *fp, int msgnum, long start, long stop)
+pmatches (FILE *fp, int msgnum, long start, long stop, int debug)
 {
     if (!head)
        return 1;
 
-    if (!talked++ && pdebug)
+    if (!talked++ && debug)
        PRaction (head, 0);
 
     return (*head->n_action) (args (head));
@@ -488,7 +490,7 @@ pmatches (FILE *fp, int msgnum, long start, long stop)
 static void
 PRaction (struct nexus *n, int level)
 {
-    register int i;
+    int i;
 
     for (i = 0; i < level; i++)
        fprintf (stderr, "| ");
@@ -521,7 +523,8 @@ PRaction (struct nexus *n, int level)
                dasctime (&n->n_tws, TW_NULL));
        return;
     }
-    fprintf (stderr, "UNKNOWN(0x%x)\n", (unsigned int) (*n->n_action));
+    fprintf (stderr, "UNKNOWN(0x%x)\n",
+            (unsigned int)(unsigned long) (*n->n_action));
 }
 
 
@@ -556,12 +559,12 @@ plist
 static int
 gcompile (struct nexus *n, char *astr)
 {
-    register int c;
+    int c;
     int cclcnt;
-    register char *ep, *dp, *sp, *lastep;
+    unsigned char *ep, *dp, *sp, *lastep = 0;
 
-    dp = (ep = n->n_expbuf) + sizeof n->n_expbuf;
-    sp = astr;
+    dp = (ep = (unsigned char *) n->n_expbuf) + sizeof n->n_expbuf;
+    sp = (unsigned char *) astr;
     if (*sp == '^') {
        n->n_circf = 1;
        sp++;
@@ -597,23 +600,40 @@ gcompile (struct nexus *n, char *astr)
            case '[': 
                *ep++ = CCL;
                *ep++ = 0;
-               cclcnt = 1;
+               cclcnt = 0;
                if ((c = *sp++) == '^') {
                    c = *sp++;
                    ep[-2] = NCCL;
                }
-               do {
+               if (c == '-') {
                    *ep++ = c;
                    cclcnt++;
-                   if (c == '\0' || ep >= dp)
-                       goto cerror;
+                   c = *sp++;
+               }
+               do {
+                   if (c == '-' && *sp != '\0' && *sp != ']') {
+                       for (c = ep[-1]+1; c < *sp; c++) {
+                           *ep++ = c;
+                           cclcnt++;
+                           if (c == '\0' || ep >= dp)
+                               goto cerror;
+                       }
+                   } else {
+                       *ep++ = c;
+                       cclcnt++;
+                       if (c == '\0' || ep >= dp)
+                           goto cerror;
+                   }
                } while ((c = *sp++) != ']');
+               if (cclcnt > 255)
+                   goto cerror;
                lastep[1] = cclcnt;
                continue;
 
            case '\\': 
                if ((c = *sp++) == '\0')
                    goto cerror;
+               /* FALLTHRU */
        defchar: 
            default: 
                *ep++ = CCHR;
@@ -632,8 +652,9 @@ plist
 {
     int c, body, lf;
     long pos = start;
-    register char *p1, *p2, *ebp, *cbp;
+    char *p1, *p2, *ebp, *cbp;
     char ibuf[BUFSIZ];
+    NMH_UNUSED (msgnum);
 
     fseek (fp, start, SEEK_SET);
     body = 0;
@@ -674,7 +695,8 @@ plist
                        break;
                    }
                    lf++;
-                   c = ' ';
+                   /* Unfold by skipping the newline. */
+                   c = 0;
                }
            }
            if (c && p1 < &linebuf[LBSIZE - 1])
@@ -686,6 +708,13 @@ plist
        p1 = linebuf;
        p2 = n->n_expbuf;
 
+       /* Attempt to decode as a MIME header.  If it's the last header,
+          body will be 1 and lf will be at least 1. */
+       if ((body == 0 || lf > 0)  &&
+           decode_rfc2047 (linebuf, decoded_linebuf, sizeof decoded_linebuf)) {
+           p1 = decoded_linebuf;
+       }
+
        if (n->n_circf) {
            if (advance (p1, p2))
                return 1;
@@ -713,14 +742,14 @@ plist
 static int
 advance (char *alp, char *aep)
 {
-    register char *lp, *ep, *curlp;
+    unsigned char *lp, *ep, *curlp;
 
-    lp = alp;
-    ep = aep;
+    lp = (unsigned char *)alp;
+    ep = (unsigned char *)aep;
     for (;;)
        switch (*ep++) {
            case CCHR: 
-               if (*ep++ == *lp++ || ep[-1] == cc[(unsigned char)lp[-1]])
+               if (*ep++ == *lp++ || ep[-1] == cc[lp[-1]])
                    continue;
                return 0;
 
@@ -739,14 +768,14 @@ advance (char *alp, char *aep)
 
            case CCL: 
                if (cclass (ep, *lp++, 1)) {
-                   ep += *ep;
+                   ep += *ep + 1;
                    continue;
                }
                return 0;
 
            case NCCL: 
                if (cclass (ep, *lp++, 0)) {
-                   ep += *ep;
+                   ep += *ep + 1;
                    continue;
                }
                return 0;
@@ -759,7 +788,7 @@ advance (char *alp, char *aep)
 
            case CCHR | STAR: 
                curlp = lp;
-               while (*lp++ == *ep || cc[(unsigned char)lp[-1]] == *ep)
+               while (*lp++ == *ep || cc[lp[-1]] == *ep)
                    continue;
                ep++;
                goto star;
@@ -769,13 +798,13 @@ advance (char *alp, char *aep)
                curlp = lp;
                while (cclass (ep, *lp++, ep[-1] == (CCL | STAR)))
                    continue;
-               ep += *ep;
+               ep += *ep + 1;
                goto star;
 
        star: 
                do {
                    lp--;
-                   if (advance (lp, ep))
+                   if (advance ((char *) lp, (char *) ep))
                        return (1);
                } while (lp > curlp);
                return 0;
@@ -788,19 +817,18 @@ advance (char *alp, char *aep)
 
 
 static int
-cclass (char *aset, int ac, int af)
+cclass (unsigned char *aset, int ac, int af)
 {
-    register int    n;
-    register char   c,
-                   *set;
+    unsigned int    n;
+    unsigned char   c, *set;
 
     set = aset;
     if ((c = ac) == 0)
        return (0);
 
     n = *set++;
-    while (--n)
-       if (*set++ == c)
+    while (n--)
+       if (*set++ == c || set[-1] == cc[c])
            return (af);
 
     return (!af);
@@ -810,7 +838,7 @@ cclass (char *aset, int ac, int af)
 static int
 tcompile (char *ap, struct tws *tb, int isafter)
 {
-    register struct tws *tw;
+    struct tws *tw;
 
     if ((tw = tws_parse (ap, isafter)) == NULL)
        return 0;
@@ -824,7 +852,7 @@ static struct tws *
 tws_parse (char *ap, int isafter)
 {
     char buffer[BUFSIZ];
-    register struct tws *tw, *ts;
+    struct tws *tw, *ts;
 
     if ((tw = tws_special (ap)) != NULL) {
        tw->tw_sec = tw->tw_min = isafter ? 59 : 0;
@@ -866,7 +894,7 @@ tws_special (char *ap)
 {
     int i;
     time_t clock;
-    register struct tws *tw;
+    struct tws *tw;
 
     time (&clock);
     if (!strcasecmp (ap, "today"))
@@ -889,11 +917,12 @@ tws_special (char *ap)
        if ((i -= tw->tw_wday) > 0)
            i -= 7;
     }
-    else
+    else {
        if (*ap != '-')
            return NULL;
-       else                    /* -ddd days ago */
-           i = atoi (ap);      /* we should error check this */
+       /* -ddd days ago */
+       i = atoi (ap);  /* we should error check this */
+    }
 
     clock += (long) ((60 * 60 * 24) * i);
     return dlocaltime (&clock);
@@ -905,37 +934,36 @@ TWSaction (params)
 plist
 {
     int state;
-    register char *bp;
+    char *bp;
     char buf[BUFSIZ], name[NAMESZ];
-    register struct tws *tw;
+    struct tws *tw;
+    m_getfld_state_t gstate = 0;
+    NMH_UNUSED (stop);
 
     fseek (fp, start, SEEK_SET);
-    for (state = FLD, bp = NULL;;) {
-       switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
+    for (bp = NULL;;) {
+       int bufsz = sizeof buf;
+       switch (state = m_getfld (&gstate, name, buf, &bufsz, fp)) {
            case FLD: 
-           case FLDEOF: 
            case FLDPLUS: 
-               if (bp != NULL)
-                   free (bp), bp = NULL;
-               bp = add (buf, NULL);
+                mh_xfree(bp);
+               bp = mh_xstrdup(buf);
                while (state == FLDPLUS) {
-                   state = m_getfld (state, name, buf, sizeof buf, fp);
+                   bufsz = sizeof buf;
+                   state = m_getfld (&gstate, name, buf, &bufsz, fp);
                    bp = add (buf, bp);
                }
                if (!strcasecmp (name, n->n_datef))
                    break;
-               if (state != FLDEOF)
-                   continue;
+               continue;
 
            case BODY: 
-           case BODYEOF: 
            case FILEEOF: 
            case LENERR: 
            case FMTERR: 
                if (state == LENERR || state == FMTERR)
                    advise (NULL, "format error in message %d", msgnum);
-               if (bp != NULL)
-                   free (bp);
+                mh_xfree(bp);
                return 0;
 
            default: 
@@ -943,6 +971,7 @@ plist
        }
        break;
     }
+    m_getfld_state_destroy (&gstate);
 
     if ((tw = dparsetime (bp)) == NULL)
        advise (NULL, "unable to parse %s field in message %d, matching...",
@@ -951,7 +980,6 @@ plist
        state = n->n_after ? (twsort (tw, &n->n_tws) > 0)
            : (twsort (tw, &n->n_tws) < 0);
 
-    if (bp != NULL)
-       free (bp);
+    mh_xfree(bp);
     return state;
 }