X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/0bfb53a23531bea3aaeadcd1a6f6c372eef96612..4ac978448:/sbr/m_convert.c?ds=inline diff --git a/sbr/m_convert.c b/sbr/m_convert.c index 496978ee..88ea9da5 100644 --- a/sbr/m_convert.c +++ b/sbr/m_convert.c @@ -8,6 +8,7 @@ */ #include +#include /* * 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;