sbr/snprintb.c sbr/ssequal.c \
sbr/strindex.c sbr/trimcpy.c sbr/uprf.c sbr/vfgets.c \
sbr/fmt_def.c sbr/mf.c sbr/utils.c sbr/ctype-checked.c \
- sbr/m_mktemp.c sbr/getansreadline.c config/config.c \
- config/version.c
+ sbr/m_mktemp.c sbr/getansreadline.c sbr/vector.c \
+ config/config.c config/version.c
##
## Because these files use the definitions in the libmh rule below,
SEQUENCES
---------
-* Change so you can have more than 26 sequences. Unfortunately,
- given the way that the bit flags for sequences work, this is
- not easy.
* Maybe add option gracefully handle empty sequences (-force).
ENVIRONMENT/PROFILE
- Added support for Content-Disposition header (RFC 2183) to mhstore(1)
and mhn(1) when used with -auto.
- All nmh commands now support transactional locking for sequence files.
-- The per-folder maximum number of sequences is now 59 on LP64 systems.
+- There is no longer a per-folder maximum number of sequences.
----------------------------
OBSOLETE/DEPRECATED FEATURES
#define FBITS "\020\01READONLY\02SEQMOD\03ALLOW_NEW\04OTHERS\05MODIFIED"
-/*
- * type for holding the sequence set of a message
- */
-typedef unsigned long seqset_t;
-
/*
* first free slot for user defined sequences
* and attributes
*/
#define FFATTRSLOT 5
-/*
- * Determine the number of user defined sequences we
- * can have. The first FFATTRSLOT sequence flags are for
- * internal nmh message flags.
- */
-#define NUMATTRS ((sizeof(seqset_t) * Nbby) - FFATTRSLOT)
-
/*
* internal messages attributes (sequences)
*/
-#define EXISTS (1<<0) /* exists */
-#define DELETED (1<<1) /* deleted */
-#define SELECTED (1<<2) /* selected for use */
-#define SELECT_EMPTY (1<<3) /* "new" message */
-#define SELECT_UNSEEN (1<<4) /* inc/show "unseen" */
+#define EXISTS (0) /* exists */
+#define DELETED (1) /* deleted */
+#define SELECTED (2) /* selected for use */
+#define SELECT_EMPTY (3) /* "new" message */
+#define SELECT_UNSEEN (4) /* inc/show "unseen" */
#define MBITS "\020\01EXISTS\02DELETED\03SELECTED\04NEW\05UNSEEN"
+/*
+ * type for holding the sequence set of a message
+ */
+typedef struct bvector *bvector_t;
+
+bvector_t bvector_create (size_t /* initial size in bits, can be 0 */);
+void bvector_copy (bvector_t, bvector_t);
+void bvector_free (bvector_t);
+void bvector_clear (bvector_t, size_t);
+void bvector_clear_all (bvector_t);
+void bvector_set (bvector_t, size_t);
+unsigned int bvector_at (bvector_t, size_t);
+const unsigned long *bvector_bits (bvector_t);
+size_t bvector_maxsize (bvector_t);
+
+struct svector;
+typedef struct svector *svector_t;
+
+svector_t svector_create (size_t);
+void svector_free (svector_t);
+char *svector_push_back (svector_t, char *);
+char *svector_at (svector_t, size_t);
+char **svector_strs (svector_t);
+size_t svector_size (svector_t);
+
+struct ivector;
+typedef struct ivector *ivector_t;
+
+ivector_t ivector_create (size_t);
+void ivector_free (ivector_t);
+int ivector_push_back (ivector_t, int);
+int ivector_at (ivector_t, size_t);
+int *ivector_atp (ivector_t, size_t);
+size_t ivector_size (ivector_t);
+
/*
* Primary structure of folder/message information
*/
char *foldpath; /* Pathname of folder */
/*
- * Name of sequences in this folder. We add an
- * extra slot, so we can NULL terminate the list.
+ * Name of sequences in this folder.
*/
- char *msgattrs[NUMATTRS + 1];
+ svector_t msgattrs;
/*
* bit flags for whether sequence
* is public (0), or private (1)
*/
- seqset_t attrstats;
+ bvector_t attrstats;
/*
* These represent the lowest and highest possible
int hghoff;
/*
- * This is an array of seqset_t which we allocate dynamically.
- * Each seqset_t is a set of bits flags for a particular message.
+ * This is an array of bvector_t which we allocate dynamically.
+ * Each bvector_t is a set of bits flags for a particular message.
* These bit flags represent general attributes such as
* EXISTS, SELECTED, etc. as well as track if message is
* in a particular sequence.
*/
- seqset_t *msgstats; /* msg status */
+ size_t num_msgstats;
+ bvector_t *msgstats; /* msg status */
/*
* A FILE handle containing an open filehandle for the sequence file
/*
* Amount of space to allocate for msgstats. Allocate
- * the array to have space for messages numbers lo to hi.
+ * the array to have space for messages numbered lo to hi.
+ * Use MSGSTATNUM to load mp->num_msgstats first.
*/
-#define MSGSTATSIZE(mp,lo,hi) ((size_t) (((hi) - (lo) + 1) * sizeof(*(mp)->msgstats)))
+#define MSGSTATNUM(lo, hi) ((size_t) ((hi) - (lo) + 1))
+#define MSGSTATSIZE(mp) ((mp)->num_msgstats * sizeof *(mp)->msgstats)
/*
* macros for message and sequence manipulation
*/
-#define clear_msg_flags(mp,msgnum) ((mp)->msgstats[(msgnum) - mp->lowoff] = 0)
-#define copy_msg_flags(mp,i,j) \
- ((mp)->msgstats[(i) - mp->lowoff] = (mp)->msgstats[(j) - mp->lowoff])
-#define get_msg_flags(mp,ptr,msgnum) (*(ptr) = (mp)->msgstats[(msgnum) - mp->lowoff])
-#define set_msg_flags(mp,ptr,msgnum) ((mp)->msgstats[(msgnum) - mp->lowoff] = *(ptr))
-
-#define does_exist(mp,msgnum) ((mp)->msgstats[(msgnum) - mp->lowoff] & EXISTS)
-#define unset_exists(mp,msgnum) ((mp)->msgstats[(msgnum) - mp->lowoff] &= ~EXISTS)
-#define set_exists(mp,msgnum) ((mp)->msgstats[(msgnum) - mp->lowoff] |= EXISTS)
-
-#define is_selected(mp,msgnum) ((mp)->msgstats[(msgnum) - mp->lowoff] & SELECTED)
-#define unset_selected(mp,msgnum) ((mp)->msgstats[(msgnum) - mp->lowoff] &= ~SELECTED)
-#define set_selected(mp,msgnum) ((mp)->msgstats[(msgnum) - mp->lowoff] |= SELECTED)
-
-#define is_select_empty(mp,msgnum) ((mp)->msgstats[(msgnum) - mp->lowoff] & SELECT_EMPTY)
+#define msgstat(mp,n) (mp)->msgstats[(n) - mp->lowoff]
+#define clear_msg_flags(mp,msgnum) bvector_clear_all (msgstat(mp, msgnum))
+#define copy_msg_flags(mp,i,j) bvector_copy (msgstat(mp,i), msgstat(mp,j))
+#define get_msg_flags(mp,ptr,msgnum) bvector_copy (ptr, msgstat(mp, msgnum))
+#define set_msg_flags(mp,ptr,msgnum) bvector_copy (msgstat(mp, msgnum), ptr)
+
+#define does_exist(mp,msgnum) bvector_at (msgstat(mp, msgnum), EXISTS)
+#define unset_exists(mp,msgnum) bvector_clear (msgstat(mp, msgnum), EXISTS)
+#define set_exists(mp,msgnum) bvector_set (msgstat(mp, msgnum), EXISTS)
+
+#define is_selected(mp,msgnum) bvector_at (msgstat(mp, msgnum), SELECTED)
+#define unset_selected(mp,msgnum) bvector_clear (msgstat(mp, msgnum), SELECTED)
+#define set_selected(mp,msgnum) bvector_set (msgstat(mp, msgnum), SELECTED)
+
+#define is_select_empty(mp,msgnum) \
+ bvector_at (msgstat(mp, msgnum), SELECT_EMPTY)
#define set_select_empty(mp,msgnum) \
- ((mp)->msgstats[(msgnum) - mp->lowoff] |= SELECT_EMPTY)
+ bvector_set (msgstat(mp, msgnum), SELECT_EMPTY)
-#define is_unseen(mp,msgnum) ((mp)->msgstats[(msgnum) - mp->lowoff] & SELECT_UNSEEN)
-#define unset_unseen(mp,msgnum) ((mp)->msgstats[(msgnum) - mp->lowoff] &= ~SELECT_UNSEEN)
-#define set_unseen(mp,msgnum) ((mp)->msgstats[(msgnum) - mp->lowoff] |= SELECT_UNSEEN)
+#define is_unseen(mp,msgnum) \
+ bvector_at (msgstat(mp, msgnum), SELECT_UNSEEN)
+#define unset_unseen(mp,msgnum) \
+ bvector_clear (msgstat(mp, msgnum), SELECT_UNSEEN)
+#define set_unseen(mp,msgnum) \
+ bvector_set (msgstat(mp, msgnum), SELECT_UNSEEN)
/* for msh only */
-#define set_deleted(mp,msgnum) ((mp)->msgstats[(msgnum) - mp->lowoff] |= DELETED)
+#define set_deleted(mp,msgnum) bvector_set (msgstat(mp, msgnum), DELETED)
#define in_sequence(mp,seqnum,msgnum) \
- ((mp)->msgstats[(msgnum) - mp->lowoff] & ((seqset_t)1 << (FFATTRSLOT + seqnum)))
+ bvector_at (msgstat(mp, msgnum), FFATTRSLOT + seqnum)
#define clear_sequence(mp,seqnum,msgnum) \
- ((mp)->msgstats[(msgnum) - mp->lowoff] &= ~((seqset_t)1 << (FFATTRSLOT + seqnum)))
+ bvector_clear (msgstat(mp, msgnum), FFATTRSLOT + seqnum)
#define add_sequence(mp,seqnum,msgnum) \
- ((mp)->msgstats[(msgnum) - mp->lowoff] |= ((seqset_t)1 << (FFATTRSLOT + seqnum)))
+ bvector_set (msgstat(mp, msgnum), FFATTRSLOT + seqnum)
#define is_seq_private(mp,seqnum) \
- ((mp)->attrstats & ((seqset_t)1 << (FFATTRSLOT + seqnum)))
+ bvector_at (mp->attrstats, FFATTRSLOT + seqnum)
#define make_seq_public(mp,seqnum) \
- ((mp)->attrstats &= ~((seqset_t)1 << (FFATTRSLOT + seqnum)))
+ bvector_clear (mp->attrstats, FFATTRSLOT + seqnum)
#define make_seq_private(mp,seqnum) \
- ((mp)->attrstats |= ((seqset_t)1 << (FFATTRSLOT + seqnum)))
+ bvector_set (mp->attrstats, FFATTRSLOT + seqnum)
#define make_all_public(mp) \
- ((mp)->attrstats = 0)
+ mp->attrstats = bvector_create(0); bvector_clear_all (mp->attrstats)
/*
* macros for folder attributes
#define MHNCHK 0x0001 /* did nontext check */
#define MHNYES 0x0002 /* .. and known to be non-text */
-#define CUR ((seqset_t)1 << (FFATTRSLOT + NUMATTRS - 1))
+/*
+ * Determine the number of user defined sequences we
+ * can have. The first FFATTRSLOT sequence flags are for
+ * internal nmh message flags.
+ */
+#define NUMATTRS (27)
+#define CUR (FFATTRSLOT + NUMATTRS - 1)
#ifdef BPOP
# define VIRTUAL SELECT_EMPTY
char *m_scanl;
struct tws m_tb;
short m_flags;
- seqset_t m_stats;
+ bvector_t m_stats;
};
#define m_bboard_id m_drop.d_id
-.TH MARK %manext1% "March 25, 2013" "%nmhversion%"
+.TH MARK %manext1% "March 31, 2013" "%nmhversion%"
.\"
.\" %nmhwarning%
.\"
switch does not affect the operation of
.BR \-list .
.PP
-The current restrictions on sequences are:
+The restrictions on sequences are:
.PP
.IP \(bu 2
The name used to denote a message sequence must consist of an alphabetic
\*(lqlast\*(rq, \*(lqall\*(rq, \*(lqnext\*(rq, or \*(lqprev\*(rq.
.PP
.IP \(bu 2
-Only a certain number of sequences may be defined for a given folder.
-This number is usually limited to 59 (27 on small systems). (The
-internal implementation relies on bitmasks, with some bits set aside
-for internal use.)
-.PP
-.IP \(bu 2
Message ranges with user\-defined sequence names are restricted to the
form \*(lqname:n\*(rq, \*(lqname:+n\*(rq, or \*(lqname:-n\*(rq, and refer
to the first or last `n' messages of the sequence `name', respectively.
void
folder_free (struct msgs *mp)
{
- int i;
+ size_t i;
+ bvector_t *v;
if (!mp)
return;
free (mp->foldpath);
/* free the sequence names */
- for (i = 0; mp->msgattrs[i]; i++)
- free (mp->msgattrs[i]);
+ for (i = 0; i < svector_size (mp->msgattrs); i++)
+ free (svector_at (mp->msgattrs, i));
+ svector_free (mp->msgattrs);
+
+ for (i = 0, v = mp->msgstats; i < mp->num_msgstats; ++i, ++v) {
+ bvector_free (*v);
+ }
+ free (mp->msgstats);
/* Close/free the sequence file if it is open */
if (mp->seqname)
free (mp->seqname);
- free (mp->msgstats); /* free message status area */
+ bvector_free (mp->attrstats);
free (mp); /* free main folder structure */
}
struct stat st;
struct dirent *dp;
DIR *dd;
+ bvector_t *v;
+ size_t i;
name = m_mailpath (name);
if (!(dd = opendir (name))) {
/*
* Allocate space for status of each message.
*/
- mp->msgstats = mh_xmalloc (MSGSTATSIZE(mp, mp->lowoff, mp->hghoff));
+ mp->num_msgstats = MSGSTATNUM (mp->lowoff, mp->hghoff);
+ mp->msgstats = mh_xmalloc (MSGSTATSIZE(mp));
+ for (i = 0, v = mp->msgstats; i < mp->num_msgstats; ++i, ++v) {
+ *v = bvector_create (0);
+ }
+
+ mp->msgattrs = svector_create (0);
/*
* Clear all the flag bits for all the message
return mp;
if (lo == mp->lowoff) {
+ bvector_t *v;
+ size_t old_size = mp->num_msgstats;
+ size_t new_size = hi - lo + 1;
+ size_t i;
+
/*
* We are just extending (or shrinking) the end of message
* status array. So we don't have to move anything and can
* just realloc the message status array.
*/
- mp->msgstats = mh_xrealloc (mp->msgstats, MSGSTATSIZE(mp, lo, hi));
+
+ for (i = old_size, v = &mp->msgstats[old_size-1]; i > new_size;
+ --i, --v) {
+ bvector_free (*v);
+ }
+ mp->num_msgstats = MSGSTATNUM (lo, hi);
+ mp->msgstats =
+ mh_xrealloc (mp->msgstats, MSGSTATSIZE(mp));
+ for (i = old_size, v = &mp->msgstats[old_size]; i < new_size;
+ ++i, ++v) {
+ *v = bvector_create (0);
+ }
} else {
/*
* We are changing the offset of the message status
* array. So we will need to shift everything.
*/
- seqset_t *tmpstats;
+ bvector_t *tmpstats, *t;
+ size_t i;
/* first allocate the new message status space */
- tmpstats = mh_xmalloc (MSGSTATSIZE(mp, lo, hi));
+ mp->num_msgstats = MSGSTATNUM (lo, hi);
+ tmpstats = mh_xmalloc (MSGSTATSIZE(mp));
+ for (i = 0, t = tmpstats; i < mp->num_msgstats; ++i, ++t) {
+ *t = bvector_create (0);
+ }
/* then copy messages status array with shift */
if (mp->nummsg > 0) {
for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++)
- tmpstats[msgnum - lo] = mp->msgstats[msgnum - mp->lowoff];
+ bvector_copy (tmpstats[msgnum - lo], msgstat (mp, msgnum));
}
free(mp->msgstats);
mp->msgstats = tmpstats;
/*
* Get the number for this sequence
*/
- for (i = 0; mp->msgattrs[i]; i++) {
- if (!strcmp (mp->msgattrs[i], cp)) {
+ for (i = 0; i < svector_size (mp->msgattrs); i++) {
+ if (!strcmp (svector_at (mp->msgattrs, i), cp)) {
new_seq = 0;
break;
}
* If this is a new sequence, add a slot for it
*/
if (new_seq) {
- if (i >= NUMATTRS) {
- advise (NULL, "only %d sequences allowed (no room for %s)!", NUMATTRS, cp);
- return 0;
- }
- if (!(mp->msgattrs[i] = strdup (cp))) {
+ if (!(svector_push_back (mp->msgattrs, strdup (cp)))) {
advise (NULL, "strdup failed");
return 0;
}
- mp->msgattrs[i + 1] = NULL;
}
/*
/*
* Get the number for this sequence
*/
- for (i = 0; mp->msgattrs[i]; i++) {
- if (!strcmp (mp->msgattrs[i], cp)) {
+ for (i = 0; i < svector_size (mp->msgattrs); i++) {
+ if (!strcmp (svector_at (mp->msgattrs, i), cp)) {
new_seq = 0;
break;
}
* If this is a new sequence, add a slot for it
*/
if (new_seq) {
- if (i >= NUMATTRS) {
- advise (NULL, "only %d sequences allowed (no room for %s)!", NUMATTRS, cp);
- return 0;
- }
- if (!(mp->msgattrs[i] = strdup (cp))) {
+ if (!(svector_push_back (mp->msgattrs, strdup (cp)))) {
advise (NULL, "strdup failed");
return 0;
}
- mp->msgattrs[i + 1] = NULL;
}
/*
char *
seq_bits (struct msgs *mp)
{
- int i;
+ size_t i;
size_t len;
static char buffer[BUFSIZ];
strncpy (buffer, MBITS, sizeof(buffer));
- for (i = 0; mp->msgattrs[i]; i++) {
+ for (i = 0; i < svector_size (mp->msgattrs); i++) {
len = strlen (buffer);
snprintf (buffer + len, sizeof(buffer) - len,
- "%c%s", FFATTRSLOT + 1 + i, mp->msgattrs[i]);
+ "%c%s", FFATTRSLOT + 1 + (int) i,
+ svector_at (mp->msgattrs, i));
+ /*
+ * seq_bits() is used by seq_printdebug(), which passes an
+ * unsigned int bit vector to snprintb(). So limit the
+ * size of the return value accordingly. Even worse,
+ * snprintb() only uses characters up through ASCII space
+ * as the delimiter (the %c character above). So limit
+ * based on that.
+ */
+ if ((int) i == ' ' - FFATTRSLOT - 1) break;
}
return buffer;
/*
* Get the number for this sequence
*/
- for (i = 0; mp->msgattrs[i]; i++) {
- if (!strcmp (mp->msgattrs[i], cp)) {
+ for (i = 0; i < svector_size (mp->msgattrs); i++) {
+ if (!strcmp (svector_at (mp->msgattrs, i), cp)) {
new_seq = 0;
break;
}
* create the sequence, if necessary
*/
if (new_seq) {
- if (i >= NUMATTRS) {
- advise (NULL, "only %d sequences allowed (no room for %s)!", NUMATTRS, cp);
- return 0;
- }
- if (!(mp->msgattrs[i] = strdup (cp))) {
+ if (!(svector_push_back (mp->msgattrs, strdup (cp)))) {
advise (NULL, "strdup failed");
return 0;
}
- mp->msgattrs[i + 1] = NULL;
}
/*
* now add sequence bit to all existing messages
int
seq_delmsg (struct msgs *mp, char *cp, int msgnum)
{
- int i;
+ size_t i;
if (!seq_nameok (cp))
return 0;
- for (i = 0; mp->msgattrs[i]; i++) {
- if (!strcmp (mp->msgattrs[i], cp)) {
+ for (i = 0; i < svector_size (mp->msgattrs); i++) {
+ if (!strcmp (svector_at (mp->msgattrs, i), cp)) {
clear_sequence (mp, i, msgnum);
mp->msgflags |= SEQMOD;
return 1;
int
seq_getnum (struct msgs *mp, char *seqname)
{
- int i;
+ size_t i;
- for (i = 0; mp->msgattrs[i]; i++)
- if (!strcmp (mp->msgattrs[i], seqname))
+ for (i = 0; i < svector_size (mp->msgattrs); i++)
+ if (!strcmp (svector_at (mp->msgattrs, i), seqname))
return i;
return -1;
void
seq_printall (struct msgs *mp)
{
- int i;
+ size_t i;
char *list;
- for (i = 0; mp->msgattrs[i]; i++) {
- list = seq_list (mp, mp->msgattrs[i]);
- printf ("%s%s: %s\n", mp->msgattrs[i],
+ for (i = 0; i < svector_size (mp->msgattrs); i++) {
+ list = seq_list (mp, svector_at (mp->msgattrs, i));
+ printf ("%s%s: %s\n", svector_at (mp->msgattrs, i),
is_seq_private (mp, i) ? " (private)" : "", empty(list));
}
}
* Initialize the list of sequence names. Go ahead and
* add the "cur" sequence to the list of sequences.
*/
- mp->msgattrs[0] = getcpy (current);
- mp->msgattrs[1] = NULL;
+ svector_push_back (mp->msgattrs, getcpy (current));
make_all_public (mp); /* initially, make all public */
/* If folder is empty, don't scan for sequence information */
* then clear the bit for this sequence from all the
* mesages in this folder.
*/
- for (i = 0; mp->msgattrs[i]; i++) {
- if (!strcmp (mp->msgattrs[i], name)) {
+ for (i = 0; i < svector_size (mp->msgattrs); i++) {
+ if (!strcmp (svector_at (mp->msgattrs, i), name)) {
for (j = mp->lowmsg; j <= mp->hghmsg; j++)
clear_sequence (mp, i, j);
break;
}
}
- /* Return error, if too many sequences */
- if (i >= NUMATTRS) {
- admonish (NULL, "Too many sequences, sequence %s ignored", name);
- free (name);
- free (field);
- return -1;
- }
-
/*
* If we've already seen this sequence name, just free the
* name string. Else add it to the list of sequence names.
*/
- if (mp->msgattrs[i]) {
+ if (svector_at (mp->msgattrs, i)) {
free (name);
} else {
- mp->msgattrs[i] = name;
- mp->msgattrs[i + 1] = NULL;
+ svector_push_back (mp->msgattrs, name);
}
/*
void
seq_save (struct msgs *mp)
{
- int i;
+ size_t i;
char flags, *cp, attr[BUFSIZ], seqfile[PATH_MAX];
FILE *fp;
sigset_t set, oset;
else
snprintf (seqfile, sizeof(seqfile), "%s/%s", mp->foldpath, mh_seq);
- for (i = 0; mp->msgattrs[i]; i++) {
- snprintf (attr, sizeof(attr), "atr-%s-%s", mp->msgattrs[i], mp->foldpath);
+ for (i = 0; i < svector_size (mp->msgattrs); i++) {
+ snprintf (attr, sizeof(attr), "atr-%s-%s",
+ svector_at (mp->msgattrs, i), mp->foldpath);
/* get space separated list of sequence ranges */
- if (!(cp = seq_list(mp, mp->msgattrs[i]))) {
+ if (!(cp = seq_list(mp, svector_at (mp->msgattrs, i)))) {
context_del (attr); /* delete sequence from context */
continue;
}
sigaddset(&set, SIGTERM);
sigprocmask (SIG_BLOCK, &set, &oset);
}
- fprintf (fp, "%s: %s\n", mp->msgattrs[i], cp);
+ fprintf (fp, "%s: %s\n", svector_at (mp->msgattrs, i), cp);
}
}
--- /dev/null
+/*
+ * vector.c -- dynamically sized vectors
+ *
+ * This code is Copyright (c) 2013, by the authors of nmh. See the
+ * COPYRIGHT file in the root directory of the nmh distribution for
+ * complete copyright information.
+ */
+
+/*
+ * This file defines several kinds of vectors:
+ * bvector: bit vector
+ * svector: vector of char arrays
+ * ivector: vector of ints
+ *
+ * The interfaces provide only the capabilities needed by nmh. The
+ * implementations rely on dynamic allocation, so that a vector
+ * can be as large as needed, as long as it fits in (virtual) memory.
+ */
+
+#include <h/mh.h>
+#include <h/utils.h>
+
+#define VEC_INIT_SIZE 256
+
+/*
+ * These try to hide the type of the "bits" member of bvector. But if
+ * that is changed to a type that's wider than unsigned long, the 1ul
+ * constants in the code below must also be changed to a 1 that's at
+ * least as wide as the new type.
+ */
+#ifndef Nbby
+# define Nbby 8
+#endif
+#define BVEC_WORD(vec, max) ((max) / (sizeof *vec->bits * Nbby))
+#define BVEC_OFFSET(vec, max) ((max) % (sizeof *vec->bits * Nbby))
+#define BVEC_BYTES(vec, n) \
+ ((BVEC_WORD (vec, n) + (BVEC_OFFSET (vec, n) == 0 ? 0 : 1)) * \
+ sizeof *vec->bits)
+
+struct bvector {
+ unsigned long *bits;
+ size_t maxsize;
+};
+
+static void bvector_resize (bvector_t, size_t);
+
+bvector_t
+bvector_create (size_t init_size) {
+ bvector_t vec = mh_xmalloc (sizeof *vec);
+ size_t bytes = BVEC_BYTES (vec, init_size ? init_size : VEC_INIT_SIZE);
+
+ vec->bits = mh_xmalloc (bytes);
+ memset (vec->bits, 0, bytes);
+ vec->maxsize = bytes * Nbby;
+
+ return vec;
+}
+
+void
+bvector_copy (bvector_t dest, bvector_t src) {
+ size_t bytes = BVEC_BYTES (dest, src->maxsize);
+
+ free (dest->bits);
+ dest->bits = mh_xmalloc (bytes);
+ memcpy (dest->bits, src->bits, bytes);
+ dest->maxsize = src->maxsize;
+}
+
+void
+bvector_free (bvector_t vec) {
+ free (vec->bits);
+ free (vec);
+}
+
+void
+bvector_clear (bvector_t vec, size_t n) {
+ size_t word = BVEC_WORD (vec,n);
+ size_t offset = BVEC_OFFSET (vec, n);
+
+ if (n >= vec->maxsize) bvector_resize (vec, n);
+
+ assert (sizeof *vec->bits <= sizeof 1ul);
+ vec->bits[word] &= ~(1ul << offset);
+}
+
+
+void
+bvector_clear_all (bvector_t vec) {
+ memset (vec->bits, 0, BVEC_BYTES (vec, vec->maxsize));
+}
+
+
+void
+bvector_set (bvector_t vec, size_t n) {
+ size_t word = BVEC_WORD (vec, n);
+ size_t offset = BVEC_OFFSET (vec, n);
+
+ if (n >= vec->maxsize) bvector_resize (vec, n);
+ assert (sizeof *vec->bits <= sizeof 1ul);
+ vec->bits[word] |= 1ul << offset;
+}
+
+unsigned int
+bvector_at (bvector_t vec, size_t i) {
+ size_t word = BVEC_WORD (vec, i);
+ size_t offset = BVEC_OFFSET (vec, i);
+
+ assert (sizeof *vec->bits <= sizeof 1ul);
+ return i < vec->maxsize
+ ? (vec->bits[word] & (1ul << offset) ? 1 : 0)
+ : 0;
+}
+
+static void
+bvector_resize (bvector_t vec, size_t maxsize) {
+ size_t old_maxsize = vec->maxsize;
+ size_t bytes;
+ size_t i;
+
+ while ((vec->maxsize *= 2) < maxsize) continue;
+ bytes = BVEC_BYTES (vec, vec->maxsize);
+ vec->bits = mh_xrealloc (vec->bits, bytes);
+ for (i = old_maxsize; i < vec->maxsize; ++i) bvector_clear (vec, i);
+}
+
+const unsigned long *
+bvector_bits (bvector_t vec) {
+ return vec->bits;
+}
+
+size_t
+bvector_maxsize (bvector_t vec) {
+ return vec->maxsize;
+}
+
+
+struct svector {
+ char **strs;
+ size_t maxsize;
+ size_t size;
+};
+
+static void svector_resize (svector_t, size_t);
+
+svector_t
+svector_create (size_t init_size) {
+ svector_t vec = mh_xmalloc (sizeof *vec);
+ size_t bytes;
+
+ vec->maxsize = init_size ? init_size : VEC_INIT_SIZE;
+ bytes = vec->maxsize * sizeof (char *);
+ vec->strs = mh_xmalloc (bytes);
+ memset (vec->strs, 0, bytes);
+ vec->size = 0;
+
+ return vec;
+}
+
+void
+svector_free (svector_t vec) {
+ free (vec->strs);
+ free (vec);
+}
+
+char *
+svector_push_back (svector_t vec, char *s) {
+ if (++vec->size >= vec->maxsize) svector_resize (vec, vec->size);
+ return vec->strs[vec->size-1] = s;
+}
+
+char *
+svector_at (svector_t vec, size_t i) {
+ if (i >= vec->maxsize) svector_resize (vec, i);
+ return vec->strs[i];
+}
+
+char **
+svector_strs (svector_t vec) {
+ return vec->strs;
+}
+
+size_t
+svector_size (svector_t vec) {
+ return vec->size;
+}
+
+static void
+svector_resize (svector_t vec, size_t maxsize) {
+ size_t old_maxsize = vec->maxsize;
+ size_t i;
+
+ while ((vec->maxsize *= 2) < maxsize) continue;
+ vec->strs = mh_xrealloc (vec->strs, vec->maxsize * sizeof (char *));
+ for (i = old_maxsize; i < vec->maxsize; ++i) vec->strs[i] = NULL;
+}
+
+
+struct ivector {
+ int *ints;
+ size_t maxsize;
+ size_t size;
+};
+
+static void ivector_resize (ivector_t, size_t);
+
+ivector_t
+ivector_create (size_t init_size) {
+ ivector_t vec = mh_xmalloc (sizeof *vec);
+ size_t bytes;
+
+ vec->maxsize = init_size ? init_size : VEC_INIT_SIZE;
+ bytes = vec->maxsize * sizeof (int);
+ vec->ints = mh_xmalloc (bytes);
+ memset (vec->ints, 0, bytes);
+ vec->size = 0;
+
+ return vec;
+}
+
+void
+ivector_free (ivector_t vec) {
+ free (vec->ints);
+ free (vec);
+}
+
+int
+ivector_push_back (ivector_t vec, int n) {
+ if (++vec->size >= vec->maxsize) ivector_resize (vec, vec->size);
+ return vec->ints[vec->size-1] = n;
+}
+
+int
+ivector_at (ivector_t vec, size_t i) {
+ if (i >= vec->maxsize) ivector_resize (vec, i);
+ return vec->ints[i];
+}
+
+int *
+ivector_atp (ivector_t vec, size_t i) {
+ if (i >= vec->maxsize) ivector_resize (vec, i);
+ return &vec->ints[i];
+}
+
+size_t
+ivector_size (ivector_t vec) {
+ return vec->size;
+}
+
+static void
+ivector_resize (ivector_t vec, size_t maxsize) {
+ size_t old_maxsize = vec->maxsize;
+ size_t i;
+
+ while ((vec->maxsize *= 2) < maxsize) continue;
+ vec->ints = mh_xrealloc (vec->ints, vec->maxsize * sizeof (int));
+ for (i = old_maxsize; i < vec->maxsize; ++i) vec->ints[i] = 0;
+}
# Test private sequence creation.
# Set current message for following tests.
-folder +inbox 1 > /dev/null
+folder +inbox 1 >/dev/null
run_test 'mark 1 -sequence privateseq -add -nopublic' ''
run_test 'mark -list' 'cur: 1
odd: 1 3 5 7 9
run_test 'mark -sequence privateseq -list -public' 'privateseq (private): 1-2'
# Test mark on empty folder.
-folder -create +other > /dev/null
+folder -create +other >/dev/null
run_test 'mark +other -sequence unseen all' 'mark: no messages in other'
# Test removal of indication of cur message.
mark +inbox -sequence cur -delete all
run_test 'pick -nolist cur' 'pick: no cur message'
+# Check large number of sequences.
+for i in 1 2 3 4 5; do
+ for j in 0 1 2 3 4 5 6 7 8 9; do
+ mark $i -seq seq$i${j}0 -seq seq$i${j}1 -seq seq$i${j}2 -seq seq$i${j}3 \
+ -seq seq$i${j}4 -seq seq$i${j}5 -seq seq$i${j}6 -seq seq$i${j}7 \
+ -seq seq$i${j}8 -seq seq$i${j}9
+ run_test "pick seq$i${j}0 seq$i${j}1 seq$i${j}2 seq$i${j}3 seq$i${j}4 \
+ seq$i${j}5 seq$i${j}6 seq$i${j}7 seq$i${j}8 seq$i${j}9" $i
+ done
+done
+
exit $failed
int priority;
int error; /* error == 1 for unreadable folder */
int nMsgs; /* number of messages in folder */
- int nSeq[NUMATTRS]; /* number of messages in each sequence */
- int private[NUMATTRS]; /* is given sequence, public or private */
+ ivector_t nSeq; /* number of messages in each sequence */
+ ivector_t private; /* is given sequence, public or private */
};
static struct Folder *orders = NULL;
static int maxfolders;
/* info on sequences to search for */
-static char *sequencesToDo[NUMATTRS];
-static unsigned int numsequences;
+static svector_t sequencesToDo;
static int all = FALSE; /* scan all folders in top level? */
static int alphaOrder = FALSE; /* want alphabetical order only */
foldersToDo = (char **) mh_xmalloc ((size_t) (maxfolders * sizeof(*foldersToDo)));
/* no sequences yet */
- numsequences = 0;
+ sequencesToDo = svector_create (0);
/* parse arguments */
while ((cp = *argp++)) {
if (!(cp = *argp++) || *cp == '-')
adios (NULL, "missing argument to %s", argp[-2]);
- /* check if too many sequences specified */
- if (numsequences >= NUMATTRS)
- adios (NULL, "too many sequences (more than %d) specified", NUMATTRS);
- sequencesToDo[numsequences++] = cp;
+ svector_push_back (sequencesToDo, cp);
break;
case ALLSW:
/*
* If we didn't specify any sequences, we search
* for the "Unseen-Sequence" profile entry and use
- * all the sequences defined there. We check to
- * make sure that the Unseen-Sequence entry doesn't
- * contain more than NUMATTRS sequences.
+ * all the sequences defined there.
*/
- if (numsequences == 0) {
+ if (svector_size (sequencesToDo) == 0) {
if ((cp = context_find(usequence)) && *cp) {
char **ap, *dp;
dp = getcpy(cp);
ap = brkstring (dp, " ", "\n");
- for (; ap && *ap; ap++) {
- if (numsequences >= NUMATTRS)
- adios (NULL, "too many sequences (more than %d) in %s profile entry",
- NUMATTRS, usequence);
- else
- sequencesToDo[numsequences++] = *ap;
- }
+ for (; ap && *ap; ap++)
+ svector_push_back (sequencesToDo, *ap);
} else {
adios (NULL, "no sequence specified or %s profile entry found", usequence);
}
ScanFolders();
qsort(folders, nFolders, sizeof(struct Folder), (qsort_comp) CompareFolders);
PrintFolders();
+ svector_free (sequencesToDo);
done (0);
return 1;
}
{
unsigned int i;
int msgnum, nonzero;
- int seqnum[NUMATTRS], nSeq[NUMATTRS];
+ ivector_t seqnum = ivector_create (0), nSeq = ivector_create (0);
struct Folder *f;
struct msgs *mp;
+ char *cp;
/* Read folder and create message structure */
if (!(mp = folder_read (name, 0))) {
return 0;
}
- for (i = 0; i < numsequences; i++) {
+ for (i = 0; i < svector_size (sequencesToDo); i++) {
/* Convert sequences to their sequence numbers */
- if (sequencesToDo[i])
- seqnum[i] = seq_getnum(mp, sequencesToDo[i]);
+ if ((cp = svector_at (sequencesToDo, i)))
+ ivector_push_back (seqnum, seq_getnum(mp, cp));
else
- seqnum[i] = -1;
+ ivector_push_back (seqnum, -1);
/* Now count messages in this sequence */
- nSeq[i] = 0;
- if (mp->nummsg > 0 && seqnum[i] != -1) {
+ ivector_push_back (nSeq, 0);
+ if (mp->nummsg > 0 && ivector_at (seqnum, i) != -1) {
for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++) {
- if (in_sequence(mp, seqnum[i], msgnum))
- nSeq[i]++;
+ if (in_sequence(mp, ivector_at (seqnum, i), msgnum))
+ (*ivector_atp (nSeq, i))++;
}
}
}
/* Check if any of the sequence checks were nonzero */
nonzero = 0;
- for (i = 0; i < numsequences; i++) {
- if (nSeq[i] > 0) {
+ for (i = 0; i < svector_size (sequencesToDo); i++) {
+ if (ivector_at (nSeq, i) > 0) {
nonzero = 1;
break;
}
f = &folders[nFolders++];
f->name = getcpy(name);
f->nMsgs = mp->nummsg;
+ f->nSeq = ivector_create (0);
+ f->private = ivector_create (0);
f->error = 0;
f->priority = AssignPriority(f->name);
/* record the sequence information */
- for (i = 0; i < numsequences; i++) {
- f->nSeq[i] = nSeq[i];
- f->private[i] = (seqnum[i] != -1) ? is_seq_private(mp, seqnum[i]) : 0;
+ for (i = 0; i < svector_size (sequencesToDo); i++) {
+ *ivector_atp (f->nSeq, i) = ivector_at (nSeq, i);
+ ivector_push_back (f->private,
+ ivector_at (seqnum, i) != -1
+ ? is_seq_private(mp, ivector_at (seqnum, i))
+ : 0);
}
}
+ ivector_free (nSeq);
+ ivector_free (seqnum);
folder_free (mp); /* free folder/message structure */
return 1;
}
if (folders[i].nMsgs > maxnum)
maxnum = folders[i].nMsgs;
- for (j = 0; j < numsequences; j++) {
+ for (j = 0; j < svector_size (sequencesToDo); j++) {
/* find maximum width of sequence name */
- len = strlen (sequencesToDo[j]);
- if ((folders[i].nSeq[j] > 0 || showzero) && (len > maxseqlen))
+ len = strlen (svector_at (sequencesToDo, j));
+ if ((ivector_at (folders[i].nSeq, j) > 0 || showzero) &&
+ (len > maxseqlen))
maxseqlen = len;
/* find the maximum number of messages in sequence */
- if (folders[i].nSeq[j] > maxseq)
- maxseq = folders[i].nSeq[j];
+ if (ivector_at (folders[i].nSeq, j) > maxseq)
+ maxseq = ivector_at (folders[i].nSeq, j);
/* check if this sequence is private in any of the folders */
- if (folders[i].private[j])
+ if (ivector_at (folders[i].private, j))
has_private = 1;
}
}
/* Now print all the folder/sequence information */
for (i = 0; i < nFolders; i++) {
- for (j = 0; j < numsequences; j++) {
- if (folders[i].nSeq[j] > 0 || showzero) {
+ for (j = 0; j < svector_size (sequencesToDo); j++) {
+ if (ivector_at (folders[i].nSeq, j) > 0 || showzero) {
/* Add `+' to end of name of current folder */
if (strcmp(curfolder, folders[i].name))
snprintf(tmpname, sizeof(tmpname), "%s", folders[i].name);
printf("%-*s has %*d in sequence %-*s%s; out of %*d\n",
maxfolderlen+1, tmpname,
- num_digits(maxseq), folders[i].nSeq[j],
- maxseqlen, sequencesToDo[j],
- !has_private ? "" : folders[i].private[j] ? " (private)" : " ",
+ num_digits(maxseq), ivector_at (folders[i].nSeq, j),
+ maxseqlen, svector_at (sequencesToDo, j),
+ !has_private ? "" : ivector_at (folders[i].private, j)
+ ? " (private)" : " ",
num_digits(maxnum), folders[i].nMsgs);
}
}
int bufsize, int outwidth, int *dat, struct fmt_callbacks *cb)
{
int i, state, msgnum, msgsize = dat[2], num = dat[0], cur = dat[1];
- int num_unseen_seq = 0, seqnum[NUMATTRS];
+ int num_unseen_seq = 0;
+ ivector_t seqnum = ivector_create (0);
char *maildir, *cp, name[NAMESZ], rbuf[BUFSIZ];
struct msgs *mp;
struct comp *c;
dp = getcpy(cp);
ap = brkstring(dp, " ", "\n");
for (i = 0; ap && *ap; i++, ap++)
- seqnum[i] = seq_getnum(mp, *ap);
+ ivector_push_back (seqnum, seq_getnum(mp, *ap));
num_unseen_seq = i;
if (dp)
dat[4] = 0;
for (i = 0; i < num_unseen_seq; i++) {
- if (in_sequence(mp, seqnum[i], msgnum)) {
+ if (in_sequence(mp, ivector_at (seqnum, i), msgnum)) {
dat[4] = 1;
break;
}
}
}
+ ivector_free (seqnum);
folder_free(mp);
return;
}
unsigned int seqp = 0;
char *cp, *maildir, *folder = NULL, buf[BUFSIZ];
char **argp, **arguments;
- char *seqs[NUMATTRS + 1];
+ svector_t seqs = svector_create (0);
struct msgs_array msgs = { 0, 0, NULL };
struct msgs *mp;
if (!(cp = *argp++) || *cp == '-')
adios (NULL, "missing argument to %s", argp[-2]);
- /* check if too many sequences specified */
- if (seqp >= NUMATTRS)
- adios (NULL, "too many sequences (more than %d) specified", NUMATTRS);
- seqs[seqp++] = cp;
+ svector_push_back (seqs, cp);
+ seqp++;
continue;
case PUBLSW:
if (seqp == 0 && (addsw || deletesw))
adios (NULL, "-%s requires at least one -sequence argument",
addsw ? "add" : "delete");
- seqs[seqp] = NULL;
/* Adding messages to sequences */
if (addsw) {
- for (seqp = 0; seqs[seqp]; seqp++)
- if (!seq_addsel (mp, seqs[seqp], publicsw, zerosw))
+ for (seqp = 0; seqp < svector_size (seqs); seqp++)
+ if (!seq_addsel (mp, svector_at (seqs, seqp), publicsw, zerosw))
done (1);
}
/* Deleting messages from sequences */
if (deletesw) {
- for (seqp = 0; seqs[seqp]; seqp++)
- if (!seq_delsel (mp, seqs[seqp], publicsw, zerosw))
+ for (seqp = 0; seqp < svector_size (seqs); seqp++)
+ if (!seq_delsel (mp, svector_at (seqs, seqp), publicsw, zerosw))
done (1);
}
if (listsw) {
if (seqp) {
/* print the sequences given */
- for (seqp = 0; seqs[seqp]; seqp++)
- seq_print (mp, seqs[seqp]);
+ for (seqp = 0; seqp < svector_size (seqs); seqp++)
+ seq_print (mp, svector_at (seqs, seqp));
} else {
/* else print them all */
seq_printall (mp);
seq_printdebug (mp);
}
+ svector_free (seqs);
seq_save (mp); /* synchronize message sequences */
context_replace (pfolder, folder); /* update current folder */
context_save (); /* save the context file */
/*
* Print debugging info about all the SELECTED
* messages and the sequences they are in.
+ * Due limitattions of snprintb(), only a limited
+ * number of sequences will be printed. See the
+ * comments in sbr/seq_bits.c.
*/
static void
seq_printdebug (struct msgs *mp)
{
int msgnum;
- char buf[100];
+ char buf[BUFSIZ];
printf ("\n");
for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
if (is_selected (mp, msgnum))
printf ("%*d: %s\n", DMAXFOLDER, msgnum,
- snprintb (buf, sizeof(buf),
- (unsigned) mp->msgstats[msgnum - mp->lowoff], seq_bits (mp)));
+ snprintb (buf, sizeof buf,
+ (unsigned) *bvector_bits (msgstat (mp, msgnum)),
+ seq_bits (mp)));
}
}
}
m_init ();
- mp->msgattrs[0] = getcpy ("unseen");
- mp->msgattrs[1] = NULL;
+ svector_push_back (mp->msgattrs, getcpy ("unseen"));
scan_detect_mbox_style (fp); /* the MAGIC invocation */
if (fmsh) {
(long) Msgs[msgnum].m_start,
(long) Msgs[msgnum].m_stop,
snprintb (buf, sizeof(buf),
- (unsigned) mp->msgstats[msgnum - mp->lowoff],
- seq_bits (mp)));
+ (unsigned) *bvector_bits (msgstat (mp,
+ msgnum)),
+ seq_bits (mp)));
if (Msgs[msgnum].m_scanl)
printf ("%s", Msgs[msgnum].m_scanl);
}
}
else /* m_scaln is already NULL */
twscopy (&Msgs[msgnum].m_tb, &tb);
- Msgs[msgnum].m_stats = mp->msgstats[msgnum - mp->lowoff];
+ Msgs[msgnum].m_stats = bvector_create (0);
+ bvector_copy (Msgs[msgnum].m_stats, msgstat (mp, msgnum));
if (mp->curmsg == msgnum)
- Msgs[msgnum].m_stats |= CUR;
+ bvector_set (Msgs[msgnum].m_stats, CUR);
}
qsort ((char *) &Msgs[mp->lowsel], mp->hghsel - mp->lowsel + 1,
free (Msgs[msgnum].m_scanl); /* from subjsort */
Msgs[msgnum].m_scanl = NULL;
}
- mp->msgstats[msgnum - mp->lowoff] = Msgs[msgnum].m_stats & ~CUR;
- if (Msgs[msgnum].m_stats & CUR)
+ bvector_clear (Msgs[msgnum].m_stats, CUR);
+ bvector_copy (msgstat (mp, msgnum), Msgs[msgnum].m_stats);
+ if (bvector_at (Msgs[msgnum].m_stats, CUR))
seq_setcur (mp, msgnum);
}
char **ap, *cp, **argp, **arguments;
char help[BUFSIZ];
char *folders = NULL;
- char *sequences[NUMATTRS + 1];
+ svector_t sequences = svector_create (0);
int i = 0;
char *unseen;
struct node *folder;
- sequences[0] = NULL;
- sequences[1] = NULL;
-
#ifdef LOCALE
setlocale(LC_ALL, "");
#endif
}
}
/* have a sequence argument */
- if (!seq_in_list(cp, sequences)) {
- sequences[i++] = cp;
- sequences[i] = NULL;
+ if (!seq_in_list(cp, svector_strs (sequences))) {
+ svector_push_back (sequences, cp);
+ ++i;
}
}
adios(NULL, "must specify sequences or set %s", usequence);
}
for (ap = brkstring(unseen, " ", "\n"); *ap; ap++) {
- sequences[i++] = *ap;
+ svector_push_back (sequences, *ap);
+ ++i;
}
}
- sequences[i] = NULL;
- folder = doit(context_find(pfolder), folders, sequences);
+ folder = doit(context_find(pfolder), folders, svector_strs (sequences));
if (folder == NULL) {
done(0);
return 1;
context_save();
+ svector_free (sequences);
done (0);
return 1;
}
int msgnum;
char *maildir, *folder = NULL, buf[100];
char *cp, **argp, **arguments;
- char *seqs[NUMATTRS + 1], *vec[MAXARGS];
+ svector_t seqs = svector_create (0);
+ char *vec[MAXARGS];
struct msgs_array msgs = { 0, 0, NULL };
struct msgnum_array nums = { 0, 0, NULL };
struct msgs *mp, *mp2;
if (!(cp = *argp++) || *cp == '-')
adios (NULL, "missing argument to %s", argp[-2]);
- /* check if too many sequences specified */
- if (seqp >= NUMATTRS)
- adios (NULL, "too many sequences (more than %d) specified", NUMATTRS);
-
if (!seq_nameok (cp))
done (1);
- seqs[seqp++] = cp;
+ svector_push_back (seqs, cp);
+ seqp++;
continue;
case NSEQSW:
seqp = 0;
if (nums.size >= mp->numsel)
adios (NULL, "no messages match specification");
- seqs[seqp] = NULL;
-
/*
* So, what's happening here?
*
/*
* Add the matching messages to sequences
*/
- for (seqp = 0; seqs[seqp]; seqp++)
- if (!seq_addsel (mp2, seqs[seqp], publicsw, zerosw))
- done (1);
+ if (seqp > 0) {
+ for (seqp = 0; seqp < svector_size (seqs); seqp++)
+ if (!seq_addsel (mp2, svector_at (seqs, seqp), publicsw, zerosw))
+ done (1);
+ }
/*
* Print total matched if not printing each matched message number.
printf ("%d hit%s\n", mp2->numsel, mp2->numsel == 1 ? "" : "s");
}
+ svector_free (seqs);
context_replace (pfolder, folder); /* update current folder */
seq_save (mp2); /* synchronize message sequences */
context_save (); /* save the context file */
int fd, msgnum;
size_t seqp = 0;
char *cp, *maildir, *folder = NULL, buf[BUFSIZ];
- char **argp, **arguments, *seqs[NUMATTRS+1];
+ char **argp, **arguments;
+ svector_t seqs = svector_create (0);
struct msgs *mp;
struct stat st;
if (!(cp = *argp++) || *cp == '-')
adios (NULL, "missing argument name to %s", argp[-2]);
- /* check if too many sequences specified */
- if (seqp >= NUMATTRS)
- adios (NULL, "too many sequences (more than %d) specified", NUMATTRS);
- seqs[seqp++] = cp;
+ svector_push_back (seqs, cp);
+ seqp++;
continue;
case UNSEENSW:
}
}
- seqs[seqp] = NULL; /* NULL terminate list of sequences */
-
if (!context_find ("path"))
free (path ("./", TFOLDER));
* Add the message to any extra sequences
* that have been specified.
*/
- for (seqp = 0; seqs[seqp]; seqp++) {
- if (!seq_addmsg (mp, seqs[seqp], msgnum, publicsw, zerosw))
- done (1);
+ if (seqp) {
+ /* The only reason that seqp was checked to be non-zero is in
+ case a -nosequence switch is added. */
+ for (seqp = 0; seqp < svector_size (seqs); seqp++) {
+ if (!seq_addmsg (mp, svector_at (seqs, seqp), msgnum, publicsw,
+ zerosw))
+ done (1);
+ }
}
+ svector_free (seqs);
seq_setunseen (mp, 0); /* synchronize any Unseen-Sequence's */
seq_save (mp); /* synchronize and save message sequences */
folder_free (mp); /* free folder/message structure */
copy_seqs (struct msgs *oldmp, int oldmsgnum, struct msgs *newmp, int newmsgnum)
{
char **seq;
- int seqnum;
+ size_t seqnum;
- for (seq = oldmp->msgattrs, seqnum = 0; *seq; ++seq, ++seqnum) {
+ for (seq = svector_strs (oldmp->msgattrs), seqnum = 0;
+ *seq && seqnum < svector_size (oldmp->msgattrs);
+ ++seq, ++seqnum) {
if (strcmp (current, *seq)) {
- assert (seqnum == seq_getnum (oldmp, *seq));
+ assert ((int) seqnum == seq_getnum (oldmp, *seq));
if (in_sequence (oldmp, seqnum, oldmsgnum)) {
seq_addmsg (newmp, *seq, newmsgnum,
is_seq_private (oldmp, seqnum) ? 0 : 1, 0);
int clearflag = 0, hdrflag = 0, ontty;
int width = 0, revflag = 0;
int i, state, msgnum;
- int seqnum[NUMATTRS], unseen, num_unseen_seq = 0;
+ ivector_t seqnum = ivector_create (0);
+ int unseen, num_unseen_seq = 0;
char *cp, *maildir, *file = NULL, *folder = NULL;
char *form = NULL, *format = NULL, buf[BUFSIZ];
char **argp, *nfs, **arguments;
dp = getcpy(cp);
ap = brkstring (dp, " ", "\n");
for (i = 0; ap && *ap; i++, ap++)
- seqnum[i] = seq_getnum (mp, *ap);
+ ivector_push_back (seqnum, seq_getnum (mp, *ap));
num_unseen_seq = i;
if (dp)
*/
unseen = 0;
for (i = 0; i < num_unseen_seq; i++) {
- if (in_sequence(mp, seqnum[i], msgnum)) {
+ if (in_sequence(mp, ivector_at (seqnum, i), msgnum)) {
unseen = 1;
break;
}
}
}
+ ivector_free (seqnum);
folder_free (mp); /* free folder/message structure */
if (clearflag)
clear_screen ();
rename_msgs (struct msgs *mp, struct smsg **mlist)
{
int i, j, old, new;
- seqset_t tmpset;
+ bvector_t tmpset = bvector_create (0);
char f1[BUFSIZ], tmpfil[BUFSIZ];
char newbuf[PATH_MAX + 1];
struct smsg *sp;
if (rename (f1, tmpfil) == NOTOK)
adios (tmpfil, "unable to rename %s to ", f1);
- get_msg_flags (mp, &tmpset, old);
+ get_msg_flags (mp, tmpset, old);
rename_chain (mp, mlist, j, i);
if (rename (tmpfil, m_name(new)) == NOTOK)
adios (m_name(new), "unable to rename %s to", tmpfil);
- set_msg_flags (mp, &tmpset, new);
+ set_msg_flags (mp, tmpset, new);
mp->msgflags |= SEQMOD;
}
+
+ bvector_free (tmpset);
}