]> diplodocus.org Git - nmh/blobdiff - sbr/m_convert.c
Fix flex 2.6.1's output regarding signed/unsigned comparisons.
[nmh] / sbr / m_convert.c
index 496978ee9fbfdc4b9a7220a4f0e4baad0f7067bc..88ea9da5dea491a6edddc2f2748530162c0246da 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <h/mh.h>
+#include <h/utils.h>
 
 /*
  * error codes for sequence
@@ -22,6 +23,7 @@
 #define        FIRST   1
 #define        LAST    2
 
+
 #define        getnew(mp) (mp->hghmsg + 1)
 
 static int convdir;    /* convert direction */
@@ -37,24 +39,24 @@ static int attr (struct msgs *, char *);
 int
 m_convert (struct msgs *mp, char *name)
 {
-    int first, last, found, range, err;
-    unsigned char *bp;
-    char *cp;
+    int first, last, found, count, is_range, err;
+    char *bp, *cp;
 
     /* check if user defined sequence */
     err = attr (mp, cp = name);
 
     if (err == -1)
        return 0;
-    else if (err < 0)
+    if (err < 0)
        goto badmsg;
-    else if (err > 0)
+    if (err > 0)
        return 1;
     /*
      * else err == 0, so continue
      */
 
     found = 0;
+    is_range = 1;
 
     /*
      * Check for special "new" sequence, which
@@ -63,8 +65,7 @@ m_convert (struct msgs *mp, char *name)
     if ((mp->msgflags & ALLOW_NEW) && !strcmp (cp, "new")) {
        if ((err = first = getnew (mp)) <= 0)
            goto badmsg;
-       else
-           goto single;
+        goto single;
     }
 
     if (!strcmp (cp, "all"))
@@ -74,7 +75,7 @@ m_convert (struct msgs *mp, char *name)
        goto badmsg;
 
     cp = delimp;
-    if (*cp != '\0' && *cp != '-' && *cp != ':') {
+    if (*cp != '\0' && *cp != '-' && *cp != ':' && *cp != '=') {
 badelim:
        advise (NULL, "illegal argument delimiter: `%c'(0%o)", *delimp, *delimp);
        return 0;
@@ -128,20 +129,25 @@ rangerr:
        if (first < mp->lowmsg)
            first = mp->lowmsg;
 
-    } else if (*cp == ':') {
+    } else if (*cp == ':' || *cp == '=') {
+
+       if (*cp == '=')
+           is_range = 0;
+
        cp++;
+
        if (*cp == '-') {
+           /* foo:-3 or foo=-3 */
            convdir = -1;
            cp++;
-       } else {
-           if (*cp == '+') {
-               convdir = 1;
-               cp++;
-           }
+       } else if (*cp == '+') {
+           /* foo:+3 or foo=+3 is same as foo:3 or foo=3 */
+           convdir = 1;
+           cp++;
        }
-       if ((range = atoi (bp = cp)) == 0)
+       if ((count = atoi (bp = cp)) == 0)
            goto badlist;
-       while (isdigit (*bp))
+       while (isdigit ((unsigned char) *bp))
            bp++;
        if (*bp)
            goto badelim;
@@ -159,16 +165,24 @@ rangerr:
             last >= mp->lowmsg && last <= mp->hghmsg;
             last += convdir)
            if (does_exist (mp, last))
-               if (--range <= 0)
+               if (--count <= 0)
                    break;
-       if (last < mp->lowmsg)
-           last = mp->lowmsg;
-       if (last > mp->hghmsg)
-           last = mp->hghmsg;
-       if (last < first) {
-           range = last;
-           last = first;
-           first = range;
+       if (is_range) { /* a range includes any messages that exist */
+           if (last < mp->lowmsg)
+               last = mp->lowmsg;
+           if (last > mp->hghmsg)
+               last = mp->hghmsg;
+           if (last < first) {
+               count = last;
+               last = first;
+               first = count;
+           }
+       } else { /* looking for the nth message.  if not enough, fail. */
+           if (last < mp->lowmsg || last > mp->hghmsg) {
+               advise (NULL, "no such message");
+               return 0;
+           }
+           first = last;
        }
     } else {
 
@@ -250,36 +264,30 @@ single:
 static int
 m_conv (struct msgs *mp, char *str, int call)
 {
-    register int i;
-    register unsigned char *cp, *bp;
-    unsigned char buf[16];
+    int i;
+    char *cp, *bp;
+    char buf[16];
 
     convdir = 1;
     cp = bp = str;
-    if (isdigit (*cp)) {
-       while (isdigit (*bp))
+    if (isdigit ((unsigned char) *cp)) {
+       while (isdigit ((unsigned char) *bp))
            bp++;
        delimp = bp;
        i = atoi (cp);
 
        if (i <= mp->hghmsg)
            return i;
-       else if (*delimp || call == LAST)
+       if (*delimp || call == LAST)
            return mp->hghmsg + 1;
-       else if (mp->msgflags & ALLOW_NEW)
+       if (mp->msgflags & ALLOW_NEW)
            return BADRNG;
-       else
-           return BADNUM;
+        return BADNUM;
     }
 
-#ifdef LOCALE
     /* doesn't enforce lower case */
-    for (bp = buf; (isalpha(*cp) || *cp == '.')
+    for (bp = buf; (isalpha((unsigned char) *cp) || *cp == '.')
            && (bp - buf < (int) sizeof(buf) - 1); )
-#else
-    for (bp = buf; ((*cp >= 'a' && *cp <= 'z') || *cp == '.')
-           && (bp - buf < (int) sizeof(buf) - 1); )
-#endif /* LOCALE */
     {
        *bp++ = *cp++;
     }
@@ -337,19 +345,25 @@ m_conv (struct msgs *mp, char *str, int call)
 static int
 attr (struct msgs *mp, char *cp)
 {
-    register unsigned char *dp;
+    char *dp;
     char *bp = NULL;
-    register int i, j;
+    char *ep;
+    char op;
+    int i, j;
     int found,
        inverted = 0,
-       range = 0,              /* no range */
-       first = 0;
+       count = 0,              /* range given?  else use entire sequence */
+       just_one = 0,           /* want entire sequence or range */
+       first = 0,
+       start = 0;
 
     /* hack for "cur-name", "cur-n", etc. */
     if (!strcmp (cp, "cur"))
        return 0;
-    if (ssequal ("cur:", cp))  /* this code need to be rewritten... */
-       return 0;
+    if (HasPrefix(cp, "cur")) {
+       if (cp[3] == ':' || cp[3] == '=')
+           return 0;
+    }
 
     /* Check for sequence negation */
     if ((dp = context_find (nsequence)) && *dp != '\0' && ssequal (dp, cp)) {
@@ -359,12 +373,12 @@ attr (struct msgs *mp, char *cp)
 
     convdir = 1;       /* convert direction */
 
-    for (dp = cp; *dp && isalnum(*dp); dp++)
+    for (dp = cp; *dp && isalnum((unsigned char) *dp); dp++)
        continue;
 
     if (*dp == ':') {
        bp = dp++;
-       range = 1;
+       count = 1;
 
        /*
         * seq:prev  (or)
@@ -372,86 +386,124 @@ attr (struct msgs *mp, char *cp)
         * seq:first (or)
         * seq:last
         */
-       if (isalpha (*dp)) {
+       if (isalpha ((unsigned char) *dp)) {
            if (!strcmp (dp, "prev")) {
                convdir = -1;
                first = (mp->curmsg > 0) && (mp->curmsg <= mp->hghmsg)
                        ? mp->curmsg - 1
                        : mp->hghmsg;
+               start = first;
            }
            else if (!strcmp (dp, "next")) {
                convdir = 1;
                first = (mp->curmsg >= mp->lowmsg)
                            ? mp->curmsg + 1
                            : mp->lowmsg;
+               start = first;
            }
            else if (!strcmp (dp, "first")) {
                convdir = 1;
+               start = mp->lowmsg;
            }
            else if (!strcmp (dp, "last")) {
                convdir = -1;
+               start = mp->hghmsg;
            }
-           else
+           else {
                return BADLST;
+           }
        } else {
            /*
             * seq:n  (or)
             * seq:+n (or)
             * seq:-n
              */
-           if (*dp == '+')
+           if (*dp == '+') {
+               /* foo:+3 is same as foo:3 */
                dp++;
-           else if (*dp == '-') {
+               convdir = 1;
+               start = mp->lowmsg;
+           } else if (*dp == '-' || *dp == ':') {
+               /* foo:-3 or foo::3 */
                dp++;
                convdir = -1;
+               start = mp->hghmsg;
            }
-           if ((range = atoi(dp)) == 0)
-               return BADLST;
-           while (isdigit (*dp))
-               dp++;
-           if (*dp)
+           count = strtol(dp,&ep,10);
+           if (count == 0 || *ep)     /* 0 illegal */
                return BADLST;
        }
 
+       op = *bp;
+       *bp = '\0';     /* temporarily terminate sequence name */
+    } else if (*dp == '=') {
+
+       bp = dp++;
+
+       if (*dp == '+') {
+           /* foo=+3 is same as foo=3 */
+           dp++;
+           convdir = 1;
+           start = mp->lowmsg;
+       } else if (*dp == '-') {
+           /* foo=-3 */
+           dp++;
+           convdir = -1;
+           start = mp->hghmsg;
+       }
+
+       count = strtol(dp,&ep,10);     /* 0 illegal */
+       if (count == 0 || *ep)
+           return BADLST;
+
+       just_one = 1;
+
+       op = *bp;
        *bp = '\0';     /* temporarily terminate sequence name */
     }
 
     i = seq_getnum (mp, cp);   /* get index of sequence */
 
     if (bp)
-       *bp = ':';              /* restore sequence name */
+       *bp = op;               /* restore sequence name */
     if (i == -1)
        return 0;
 
     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 (!start)
+       start = mp->lowmsg;
+
+    for (j = start; 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;
-           }
            found++;
-
+           /* we want all that we find, or just the last in the +/_ case */
+           if (!just_one || found >= count) {
+               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;
+               }
+           }
            /*
-            * If we have a range, then break out
+            * If we have any sort of limit, then break out
             * once we've found enough.
              */
-           if (range && found >= range)
+           if (count && found >= count)
                break;
+
        }
     }
 
-    if (found > 0)
-       return found;
+    if (mp->numsel > 0)
+       return mp->numsel;
 
-    if (first)
+    if (first || just_one)
        return BADMSG;
     advise (NULL, "sequence %s %s", cp, inverted ? "full" : "empty");
     return -1;