Factor trim format function out
[mmh] / sbr / m_convert.c
index ee9ba5b..d187a34 100644 (file)
@@ -1,17 +1,21 @@
 /*
- * m_convert.c -- parse a message range or sequence and set SELECTED
- *
- * 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.
- */
+** m_convert.c -- parse a message range or sequence and set SELECTED
+**
+** 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.
+*/
+
+
+/* FIXME: This code needs rework! Rewrite as a parser? */
 
 #include <h/mh.h>
+#include <ctype.h>
 
 /*
- * error codes for sequence
- * and message range processing
- */
+** error codes for sequence
+** and message range processing
+*/
 #define BADMSG (-2)
 #define BADRNG (-3)
 #define BADNEW (-4)
 #define FIRST 1
 #define LAST 2
 
-#define getnew(mp) (mp->hghmsg + 1)
+#define getbeyond(mp) ((mp)->hghmsg + 1)
 
-static int convdir; /* convert direction */
-static char *delimp;
+static int convdir;  /* convert direction */
+static char *delimp;  /* delimiter pointer */
 
 /*
- * static prototypes
- */
-static int m_conv (struct msgs *, char *, int);
-static int attr (struct msgs *, char *);
-
+** static prototypes
+*/
+static int m_conv(struct msgs *, char *, int);
+static int attr(struct msgs *, char *);
 
 int
-m_convert (struct msgs *mp, char *name)
+m_convert(struct msgs *mp, char *name)
 {
        int first, last, found, range, err;
        unsigned char *bp;
        char *cp;
 
        /* check if user defined sequence */
-       err = attr (mp, cp = name);
-
+       err = attr(mp, cp = name);
        if (err == -1)
                return 0;
        else if (err < 0)
                goto badmsg;
-       else if (err > 0)
+       else if (err > 0) {
+               /* it had been a user-defined sequence: we're finished */
                return 1;
+       }
        /*
-        * else err == 0, so continue
-        */
-
-       found = 0;
+       ** else err == 0, so continue
+       ** here we know: it is no user-defined seq
+       */
 
        /*
-        * Check for special "new" sequence, which
-        * is valid only if ALLOW_NEW is set.
-        */
-       if ((mp->msgflags & ALLOW_NEW) && !strcmp (cp, "new")) {
-               if ((err = first = getnew (mp)) <= 0)
-                       goto badmsg;
-               else
-                       goto single;
+       ** Handle the special beyond sequence, which is valid only if
+       ** ALLOW_BEYOND is set, and can appear only on its own.
+       ** Also, it is available in any folder.
+       */
+       if ((mp->msgflags & ALLOW_BEYOND) && strcmp(cp, seq_beyond)==0) {
+               set_selected(mp, getbeyond(mp));
+               return 1;
        }
 
-       if (!strcmp (cp, "all"))
-               cp = "first-last";
+       /*
+       ** Handle the special all sequence: replace `a' with `f-l'
+       */
+       if (strcmp(cp, seq_all)==0) {
+               cp = concat(seq_first, "-", seq_last, NULL);
+       }
 
-       if ((err = first = m_conv (mp, cp, FIRST)) <= 0)
+       if ((err = first = m_conv(mp, cp, FIRST)) <= 0)
                goto badmsg;
 
        cp = delimp;
-       if (*cp != '\0' && *cp != '-' && *cp != ':') {
-badelim:
-               advise (NULL, "illegal argument delimiter: `%c'(0%o)", *delimp, *delimp);
-               return 0;
-       }
-
-       if (*cp == '-') {
+       switch (*cp) {
+       case '-':
+               /* global range */
                cp++;
-               if ((err = last = m_conv (mp, cp, LAST)) <= 0) {
+               if ((err = last = m_conv(mp, cp, LAST)) <= 0) {
 badmsg:
                        switch (err) {
                        case BADMSG:
-                               advise (NULL, "no %s message", cp);
+                               advise(NULL, "no %s message", cp);
                                break;
 
                        case BADNUM:
-                               advise (NULL, "message %s doesn't exist", cp);
+                               advise(NULL, "message %s doesn't exist", cp);
                                break;
 
                        case BADRNG:
-                               advise (NULL, "message %s out of range 1-%d", cp, mp->hghmsg);
+                               advise(NULL, "message %s out of range 1-%d",
+                                               cp, mp->hghmsg);
                                break;
 
                        case BADLST:
 badlist:
-                               advise (NULL, "bad message list %s", name);
+                               advise(NULL, "bad message list %s", name);
                                break;
 
                        case BADNEW:
-                               advise (NULL, "folder full, no %s message", name);
+                               advise(NULL, "folder full, no %s message",
+                                               name);
                                break;
 
                        default:
-                               advise (NULL, "no messages match specification");
+                               advise(NULL, "no messages match specification");
                        }
                        return 0;
                }
@@ -117,7 +121,7 @@ badlist:
                        goto badelim;
                if (first > mp->hghmsg || last < mp->lowmsg) {
 rangerr:
-                       advise (NULL, "no messages in range %s", name);
+                       advise(NULL, "no messages in range %s", name);
                        return 0;
                }
 
@@ -126,8 +130,10 @@ rangerr:
                        last = mp->hghmsg;
                if (first < mp->lowmsg)
                        first = mp->lowmsg;
+               break;
 
-       } else if (*cp == ':') {
+       case ':':
+               /* anchored range */
                cp++;
                if (*cp == '-') {
                        convdir = -1;
@@ -136,14 +142,14 @@ rangerr:
                        convdir = 1;
                        cp++;
                }
-               if ((range = atoi (bp = cp)) == 0)
+               if ((range = atoi(bp = cp)) == 0)
                        goto badlist;
-               while (isdigit (*bp))
+               while (isdigit(*bp))
                        bp++;
                if (*bp)
                        goto badelim;
                if ((convdir > 0 && first > mp->hghmsg)
-                       || (convdir < 0 && first < mp->lowmsg))
+                               || (convdir < 0 && first < mp->lowmsg))
                        goto rangerr;
 
                /* tighten the range to search */
@@ -153,10 +159,9 @@ rangerr:
                        first = mp->hghmsg;
 
                for (last = first; last >= mp->lowmsg && last <= mp->hghmsg;
-                       last += convdir)
-                       if (does_exist (mp, last))
-                               if (--range <= 0)
-                                       break;
+                               last += convdir)
+                       if (does_exist(mp, last) && (--range <= 0))
+                               break;
                if (last < mp->lowmsg)
                        last = mp->lowmsg;
                if (last > mp->hghmsg)
@@ -166,52 +171,48 @@ rangerr:
                        last = first;
                        first = range;
                }
-       } else {
+               break;
 
-single:
+       case '\0':
+               /* single name */
                /*
-                * Single Message
-                *
-                * If ALLOW_NEW is set, then allow selecting of an
-                * empty slot.  If ALLOW_NEW is not set, then we
-                * check if message is in-range and exists.
-                */
-               if (mp->msgflags & ALLOW_NEW) {
-                       set_select_empty (mp, first);
-               } else {
-                       if (first > mp->hghmsg
-                               || first < mp->lowmsg
-                               || !(does_exist (mp, first))) {
-                               if (!strcmp (name, "cur") || !strcmp (name, "."))
-                                       advise (NULL, "no %s message", name);
-                               else
-                                       advise (NULL, "message %d doesn't exist", first);
-                               return 0;
-                       }
+               ** AFAICS, the only cases to reach here are:
+               **     f, l, p, n, c, b
+               ** But I'm not sure.  --meillo
+               */
+               /*
+               ** Single Message
+               **
+               ** Check if message is in-range and exists.
+               */
+               if (first > mp->hghmsg || first < mp->lowmsg ||
+                               !does_exist(mp, first)) {
+                       if (strcmp(name, seq_cur)==0)
+                               advise(NULL, "no current message");
+                       else
+                               /* this case seems to never be reached */
+                               advise(NULL, "message %d doesn't exist",
+                                               first);
+                       return 0;
                }
                last = first;  /* range of 1 */
+               break;
+
+       default:
+badelim:
+               advise(NULL, "illegal argument delimiter: `%c'(0%o)",
+                               *delimp, *delimp);
+               return 0;
+               break;
        }
 
-       /*
-        * Cycle through the range and select the messages
-        * that exist.  If ALLOW_NEW is set, then we also check
-        * if we are selecting an empty slot.
-        */
-       for (; first <= last; first++) {
-               if (does_exist (mp, first) ||
-                       ((mp->msgflags & ALLOW_NEW) && is_select_empty (mp, first))) {
-                       if (!is_selected (mp, first)) {
-                               set_selected (mp, first);
-                               mp->numsel++;
-                               if (mp->lowsel == 0 || first < mp->lowsel)
-                                       mp->lowsel = first;
-                               if (first > mp->hghsel)
-                                       mp->hghsel = first;
-                       }
+       /* Cycle through the range and select the messages that exist. */
+       for (found=0; first <= last; first++) {
+               if (does_exist(mp, first)) {
+                       set_selected(mp, first);
                        found++;
                }
        }
-
        if (!found)
                goto rangerr;
 
@@ -219,126 +220,127 @@ single:
 }
 
 /*
- * Convert the various message names to
- * their numeric values.
- *
- * n  (integer)
- * prev
- * next
- * first
- * last
- * cur
- * .  (same as cur)
- */
-
+** Convert the various message names to their numeric values.
+**
+** 42  (any integer)
+** p
+** n
+** f
+** l
+** c
+*/
 static int
-m_conv (struct msgs *mp, char *str, int call)
+m_conv(struct msgs *mp, char *str, int call)
 {
-       register int i;
-       register unsigned char *cp, *bp;
-       unsigned char buf[16];
+       int i;
+       unsigned char *cp, *bp;
+       unsigned char buf[16];  /* for reserved sequence name */
 
        convdir = 1;
        cp = bp = str;
-       if (isdigit (*cp)) {
-               while (isdigit (*bp))
+
+       /* Handle an integer */
+       if (isdigit(*cp)) {
+               while (isdigit(*bp))
                        bp++;
                delimp = bp;
-               i = atoi (cp);
+               i = atoi(cp);
 
                if (i <= mp->hghmsg)
                        return i;
                else if (*delimp || call == LAST)
                        return mp->hghmsg + 1;
-               else if (mp->msgflags & ALLOW_NEW)
+               else if (mp->msgflags & ALLOW_BEYOND)
                        return BADRNG;
                else
                        return BADNUM;
        }
 
-#ifdef LOCALE
-       /* doesn't enforce lower case */
-       for (bp = buf; (isalpha(*cp) || *cp == '.')
-                               && (bp - buf < sizeof(buf) - 1); )
-#else
-       for (bp = buf; ((*cp >= 'a' && *cp <= 'z') || *cp == '.')
-                               && (bp - buf < sizeof(buf) - 1); )
-#endif /* LOCALE */
-       {
+       for (bp = buf; isalpha(*cp) && (bp - buf < (int)sizeof(buf) - 1); ) {
                *bp++ = *cp++;
        }
        *bp++ = '\0';
        delimp = cp;
 
-       if (!strcmp (buf, "first"))
-               return (mp->hghmsg || !(mp->msgflags & ALLOW_NEW)
-                               ? mp->lowmsg : BADMSG);
+       /* Which one of the reserved names is it? */
+       if (strcmp(buf, seq_first)==0) {
+               return (mp->hghmsg || !(mp->msgflags & ALLOW_BEYOND) ?
+                               mp->lowmsg : BADMSG);
 
-       if (!strcmp (buf, "last")) {
+       } else if (strcmp(buf, seq_last)==0) {
                convdir = -1;
-               return (mp->hghmsg || !(mp->msgflags & ALLOW_NEW) ? mp->hghmsg : BADMSG);
-       }
+               return (mp->hghmsg || !(mp->msgflags & ALLOW_BEYOND) ?
+                               mp->hghmsg : BADMSG);
 
-       if (!strcmp (buf, "cur") || !strcmp (buf, "."))
+       } else if (strcmp(buf, seq_cur)==0) {
                return (mp->curmsg > 0 ? mp->curmsg : BADMSG);
 
-       if (!strcmp (buf, "prev")) {
+       } else if (strcmp(buf, seq_prev)==0) {
                convdir = -1;
-               for (i = (mp->curmsg <= mp->hghmsg) ? mp->curmsg - 1 : mp->hghmsg;
-                       i >= mp->lowmsg; i--) {
-                       if (does_exist (mp, i))
+               for (i = (mp->curmsg <= mp->hghmsg) ?
+                               mp->curmsg - 1 : mp->hghmsg;
+                               i >= mp->lowmsg; i--) {
+                       if (does_exist(mp, i))
                                return i;
                }
                return BADMSG;
-       }
 
-       if (!strcmp (buf, "next")) {
-               for (i = (mp->curmsg >= mp->lowmsg) ? mp->curmsg + 1 : mp->lowmsg;
-                       i <= mp->hghmsg; i++) {
-                       if (does_exist (mp, i))
+       } else if (strcmp(buf, seq_next)==0) {
+               for (i = (mp->curmsg >= mp->lowmsg) ?
+                               mp->curmsg + 1 : mp->lowmsg;
+                               i <= mp->hghmsg; i++) {
+                       if (does_exist(mp, i))
                                return i;
                }
                return BADMSG;
-       }
 
-       return BADLST;
+       } else {
+               return BADLST;
+       }
 }
 
 /*
- * Handle user defined sequences.
- * They can take the following forms:
- *
- * seq
- * seq:prev
- * seq:next
- * seq:first
- * seq:last
- * seq:+n
- * seq:-n
- * seq:n
- */
-
+** Handle user defined sequences.
+** They can take the following forms:
+**
+** seq
+** seq:p
+** seq:n
+** seq:f
+** seq:l
+** seq:+42
+** seq:-42
+** seq:42
+**
+** (`42' being an arbitrary integer)
+*/
 static int
-attr (struct msgs *mp, char *cp)
+attr(struct msgs *mp, char *cp)
 {
-       register unsigned char *dp;
+       unsigned char *dp;
        char *bp = NULL;
-       register int i, j;
+       int i, j;
        int found;
        int inverted = 0;
        int range = 0;  /* no range */
        int first = 0;
 
-       /* hack for "cur-name", "cur-n", etc. */
-       if (!strcmp (cp, "cur"))
+       /* hack for "c-..." */
+       if (strcmp(cp, seq_cur)==0)
                return 0;
-       if (ssequal ("cur:", cp))  /* this code need to be rewritten... */
+       /* "c:..." -- this code need to be rewritten... */
+       if (strncmp(seq_cur, cp, strlen(seq_cur))==0 &&
+                       cp[strlen(seq_cur)] == ':') {
                return 0;
+       }
 
        /* Check for sequence negation */
-       if ((dp = context_find (nsequence)) && *dp != '\0' && ssequal (dp, cp)) {
+       if (!(dp = context_find(nsequence))) {
+               dp = seq_neg;  /* use default */
+       }
+       if (*dp && strncmp(cp, dp, strlen(dp))==0) {
                inverted = 1;
-               cp += strlen (dp);
+               cp += strlen(dp);
        }
 
        convdir = 1;  /* convert direction */
@@ -351,32 +353,32 @@ attr (struct msgs *mp, char *cp)
                range = 1;
 
                /*
-                * seq:prev  (or)
-                * seq:next  (or)
-                * seq:first (or)
-                * seq:last
-                */
-               if (isalpha (*dp)) {
-                       if (!strcmp (dp, "prev")) {
+               ** seq:p  (or)
+               ** seq:n  (or)
+               ** seq:f  (or)
+               ** seq:l
+               */
+               if (isalpha(*dp)) {
+                       if (strcmp(dp, seq_prev)==0) {
                                convdir = -1;
                                first = (mp->curmsg > 0) && (mp->curmsg <= mp->hghmsg)
                                        ? mp->curmsg - 1 : mp->hghmsg;
-                       } else if (!strcmp (dp, "next")) {
+                       } else if (strcmp(dp, seq_next)==0) {
                                convdir = 1;
                                first = (mp->curmsg >= mp->lowmsg)
                                        ? mp->curmsg + 1 : mp->lowmsg;
-                       } else if (!strcmp (dp, "first")) {
+                       } else if (strcmp(dp, seq_first)==0) {
                                convdir = 1;
-                       } else if (!strcmp (dp, "last")) {
+                       } else if (strcmp(dp, seq_last)==0) {
                                convdir = -1;
                        } else
                                return BADLST;
                } else {
                        /*
-                        * seq:n  (or)
-                        * seq:+n (or)
-                        * seq:-n
-                        */
+                       ** seq:42  (or)
+                       ** seq:+42 (or)
+                       ** seq:-42
+                       */
                        if (*dp == '+')
                                dp++;
                        else if (*dp == '-') {
@@ -385,7 +387,7 @@ attr (struct msgs *mp, char *cp)
                        }
                        if ((range = atoi(dp)) == 0)
                                return BADLST;
-                       while (isdigit (*dp))
+                       while (isdigit(*dp))
                                dp++;
                        if (*dp)
                                return BADLST;
@@ -394,7 +396,7 @@ attr (struct msgs *mp, char *cp)
                *bp = '\0';  /* temporarily terminate sequence name */
        }
 
-       i = seq_getnum (mp, cp);  /* get index of sequence */
+       i = seq_getnum(mp, cp);  /* get index of sequence */
 
        if (bp)
                *bp = ':';  /* restore sequence name */
@@ -404,33 +406,27 @@ attr (struct msgs *mp, char *cp)
        found = 0;  /* count the number we select for this argument */
 
        for (j = first ? first : (convdir > 0) ? mp->lowmsg : mp->hghmsg;
-               j >= mp->lowmsg && j <= mp->hghmsg; j += convdir) {
-               if (does_exist (mp, j)
-                       && inverted ? !in_sequence (mp, i, j) : in_sequence (mp, i, j)) {
-                       if (!is_selected (mp, j)) {
-                               set_selected (mp, j);
-                               mp->numsel++;
-                               if (mp->lowsel == 0 || j < mp->lowsel)
-                                       mp->lowsel = j;
-                               if (j > mp->hghsel)
-                                       mp->hghsel = j;
-                       }
+                       j >= mp->lowmsg && j <= mp->hghmsg; j += convdir) {
+               if (does_exist(mp, j)
+                               && inverted ? !in_sequence(mp, i, j) :
+                               in_sequence(mp, i, j)) {
+                       set_selected(mp, j);
                        found++;
 
                        /*
-                        * If we have a range, then break out
-                        * once we've found enough.
-                        */
+                       ** If we have a range, then break out
+                       ** once we've found enough.
+                       */
                        if (range && found >= range)
                                break;
                }
        }
 
-       if (found > 0)
+       if (found)
                return found;
 
        if (first)
                return BADMSG;
-       advise (NULL, "sequence %s %s", cp, inverted ? "full" : "empty");
+       advise(NULL, "sequence %s %s", cp, inverted ? "full" : "empty");
        return -1;
 }