mh: fix msgset parser and some more comp compatibility issues; provide testsuite for comp.
* mh/Makefile.am (bin_PROGRAMS): Add mhseq. * mh/comp.c (main): Rewrite to fix compatibility issues. * mh/mh.h (MH_MSGSET_UID): New define. (mh_msgset_t) <flags,size>: New members. * mh/mh_init.c (mh_draft_message): Bugfix: convert msgset to UIDs. * mh/mh_msgset.c: Rewrite from scratch. * mh/tests/comp.at: New file. * mh/tests/mhseq.at: New file. * mh/tests/Makefile.am (TESTSUITE_AT): Add comp.at, mhseq.at. * mh/tests/testsuite.at: Include comp.at and mhseq.at. * libmailutils/property/mhprop.c (_mh_prop_read_stream): Minor fix. Do remove empty lines. * mh/mh_whatnow.c (_whatnow): Detect EOF. (call_send): Quit after successful send.
Showing
14 changed files
with
1265 additions
and
509 deletions
... | @@ -113,7 +113,7 @@ _mh_prop_read_stream (mu_header_t *phdr, mu_stream_t stream) | ... | @@ -113,7 +113,7 @@ _mh_prop_read_stream (mu_header_t *phdr, mu_stream_t stream) |
113 | argv[1] = "#"; | 113 | argv[1] = "#"; |
114 | argv[2] = "-r"; | 114 | argv[2] = "-r"; |
115 | argv[3] = NULL; | 115 | argv[3] = NULL; |
116 | rc = mu_filter_create_args (&flt, stream, argv[0], 2, argv, | 116 | rc = mu_filter_create_args (&flt, stream, argv[0], 3, argv, |
117 | MU_FILTER_DECODE, MU_STREAM_READ); | 117 | MU_FILTER_DECODE, MU_STREAM_READ); |
118 | if (rc) | 118 | if (rc) |
119 | { | 119 | { | ... | ... |
... | @@ -80,6 +80,7 @@ static int build_only = 0; /* --build flag */ | ... | @@ -80,6 +80,7 @@ static int build_only = 0; /* --build flag */ |
80 | static int use_draft = 0; /* --use flag */ | 80 | static int use_draft = 0; /* --use flag */ |
81 | static char *draftmessage = "new"; | 81 | static char *draftmessage = "new"; |
82 | static const char *draftfolder = NULL; | 82 | static const char *draftfolder = NULL; |
83 | static int folder_set; /* Folder is set on the command line */ | ||
83 | 84 | ||
84 | static error_t | 85 | static error_t |
85 | opt_handler (int key, char *arg, struct argp_state *state) | 86 | opt_handler (int key, char *arg, struct argp_state *state) |
... | @@ -87,8 +88,7 @@ opt_handler (int key, char *arg, struct argp_state *state) | ... | @@ -87,8 +88,7 @@ opt_handler (int key, char *arg, struct argp_state *state) |
87 | switch (key) | 88 | switch (key) |
88 | { | 89 | { |
89 | case ARGP_KEY_INIT: | 90 | case ARGP_KEY_INIT: |
90 | draftfolder = mh_global_profile_get ("Draft-Folder", | 91 | draftfolder = mh_global_profile_get ("Draft-Folder", NULL); |
91 | mu_folder_directory ()); | ||
92 | whatnowproc = mh_global_profile_get ("whatnowproc", NULL); | 92 | whatnowproc = mh_global_profile_get ("whatnowproc", NULL); |
93 | break; | 93 | break; |
94 | 94 | ||
... | @@ -106,6 +106,7 @@ opt_handler (int key, char *arg, struct argp_state *state) | ... | @@ -106,6 +106,7 @@ opt_handler (int key, char *arg, struct argp_state *state) |
106 | 106 | ||
107 | case ARG_FOLDER: | 107 | case ARG_FOLDER: |
108 | mh_set_current_folder (arg); | 108 | mh_set_current_folder (arg); |
109 | folder_set = 1; | ||
109 | break; | 110 | break; |
110 | 111 | ||
111 | case ARG_FORM: | 112 | case ARG_FORM: |
... | @@ -126,7 +127,7 @@ opt_handler (int key, char *arg, struct argp_state *state) | ... | @@ -126,7 +127,7 @@ opt_handler (int key, char *arg, struct argp_state *state) |
126 | break; | 127 | break; |
127 | 128 | ||
128 | case ARG_FILE: | 129 | case ARG_FILE: |
129 | wh_env.draftfile = mh_expand_name (NULL, arg, 0); | 130 | wh_env.file = mh_expand_name (NULL, arg, 0); |
130 | break; | 131 | break; |
131 | 132 | ||
132 | case ARG_NODRAFTFOLDER: | 133 | case ARG_NODRAFTFOLDER: |
... | @@ -197,7 +198,7 @@ main (int argc, char **argv) | ... | @@ -197,7 +198,7 @@ main (int argc, char **argv) |
197 | mh_argp_parse (&argc, &argv, 0, options, mh_option, args_doc, doc, | 198 | mh_argp_parse (&argc, &argv, 0, options, mh_option, args_doc, doc, |
198 | opt_handler, NULL, &index); | 199 | opt_handler, NULL, &index); |
199 | 200 | ||
200 | if (wh_env.draftfile) | 201 | if (wh_env.file) |
201 | { | 202 | { |
202 | if (build_only) | 203 | if (build_only) |
203 | { | 204 | { |
... | @@ -205,68 +206,90 @@ main (int argc, char **argv) | ... | @@ -205,68 +206,90 @@ main (int argc, char **argv) |
205 | exit (1); | 206 | exit (1); |
206 | } | 207 | } |
207 | } | 208 | } |
209 | else if (folder_set) | ||
210 | { | ||
211 | wh_env.file = mh_expand_name (NULL, "draft", 0); | ||
212 | } | ||
208 | else | 213 | else |
209 | { | 214 | { |
210 | if (build_only || !draftfolder) | 215 | if (build_only || !draftfolder) |
211 | wh_env.file = mh_expand_name (NULL, "draft", 0); | 216 | { |
217 | switch (argc - index) | ||
218 | { | ||
219 | case 0: | ||
220 | wh_env.file = mh_expand_name (NULL, "draft", 0); | ||
221 | break; | ||
222 | |||
223 | case 1: | ||
224 | wh_env.file = mh_expand_name (NULL, argv[index], 0); | ||
225 | break; | ||
226 | |||
227 | default: | ||
228 | mu_error (_("only one message at a time!")); | ||
229 | return 1; | ||
230 | } | ||
231 | } | ||
212 | else if (draftfolder) | 232 | else if (draftfolder) |
213 | { | 233 | { |
214 | /* Comp accepts a `file', and it will, if given | 234 | /* Comp accepts a `file', and it will, if given |
215 | `-draftfolder +folder' treat this arguments as `msg'. */ | 235 | `-draftfolder +folder' treat this arguments as `msg'. */ |
216 | if (index < argc) | 236 | if (use_draft || index < argc) |
217 | { | 237 | { |
218 | mh_msgset_t msgset; | 238 | mh_msgset_t msgset; |
219 | mu_mailbox_t mbox; | 239 | mu_mailbox_t mbox; |
220 | 240 | ||
221 | mbox = mh_open_folder (draftfolder, 1); | 241 | mbox = mh_open_folder (draftfolder, 1); |
222 | mh_msgset_parse (mbox, &msgset, argc - index, argv + index, | 242 | mh_msgset_parse (mbox, &msgset, |
223 | "new"); | 243 | argc - index, argv + index, |
244 | use_draft ? "cur" : "new"); | ||
224 | mu_mailbox_destroy (&mbox); | 245 | mu_mailbox_destroy (&mbox); |
225 | if (msgset.count != 1) | 246 | if (msgset.count != 1) |
226 | { | 247 | { |
227 | mu_error (_("only one message at a time!")); | 248 | mu_error (_("only one message at a time!")); |
228 | return 1; | 249 | return 1; |
229 | } | 250 | } |
251 | mh_msgset_uids (mbox, &msgset); | ||
230 | draftmessage = mu_umaxtostr (0, msgset.list[0]); | 252 | draftmessage = mu_umaxtostr (0, msgset.list[0]); |
231 | mh_msgset_free (&msgset); | 253 | mh_msgset_free (&msgset); |
232 | index = argc; | ||
233 | } | 254 | } |
234 | if (mh_draft_message (draftfolder, draftmessage, | 255 | if (mh_draft_message (draftfolder, draftmessage, |
235 | &wh_env.file)) | 256 | &wh_env.file)) |
236 | return 1; | 257 | return 1; |
237 | } | 258 | } |
238 | wh_env.draftfile = wh_env.file; | ||
239 | } | 259 | } |
240 | 260 | wh_env.draftfile = wh_env.file; | |
241 | switch (check_draft_disposition (&wh_env, use_draft)) | ||
242 | { | ||
243 | case DISP_QUIT: | ||
244 | exit (0); | ||
245 | 261 | ||
246 | case DISP_USE: | 262 | if (folder_set && index < argc) |
247 | break; | 263 | { |
248 | 264 | mh_msgset_t msgset; | |
249 | case DISP_REPLACE: | 265 | mu_mailbox_t mbox; |
250 | unlink (wh_env.draftfile); | 266 | |
251 | 267 | mbox = mh_open_folder (mh_current_folder (), 0); | |
252 | if (index < argc) | 268 | mh_msgset_parse (mbox, &msgset, argc - index, argv + index, "cur"); |
269 | if (msgset.count != 1) | ||
253 | { | 270 | { |
254 | mh_msgset_t msgset; | 271 | mu_error (_("only one message at a time!")); |
255 | mu_mailbox_t mbox; | 272 | return 1; |
273 | } | ||
274 | unlink (wh_env.file); | ||
275 | copy_message (mbox, msgset.list[0], wh_env.file); | ||
276 | mu_mailbox_destroy (&mbox); | ||
277 | mh_msgset_free (&msgset); | ||
278 | } | ||
279 | else | ||
280 | { | ||
281 | switch (check_draft_disposition (&wh_env, use_draft)) | ||
282 | { | ||
283 | case DISP_QUIT: | ||
284 | exit (0); | ||
285 | |||
286 | case DISP_USE: | ||
287 | break; | ||
256 | 288 | ||
257 | mbox = mh_open_folder (mh_current_folder (), 0); | 289 | case DISP_REPLACE: |
258 | mh_msgset_parse (mbox, &msgset, argc - index, argv + index, "cur"); | 290 | unlink (wh_env.draftfile); |
259 | if (msgset.count != 1) | 291 | mh_comp_draft (formfile, "components", wh_env.file); |
260 | { | ||
261 | mu_error (_("only one message at a time!")); | ||
262 | return 1; | ||
263 | } | ||
264 | copy_message (mbox, msgset.list[0], wh_env.file); | ||
265 | mu_mailbox_destroy (&mbox); | ||
266 | mh_msgset_free (&msgset); | ||
267 | } | 292 | } |
268 | else | ||
269 | mh_comp_draft (formfile, "components", wh_env.file); | ||
270 | } | 293 | } |
271 | 294 | ||
272 | /* Exit immediately if --build is given */ | 295 | /* Exit immediately if --build is given */ | ... | ... |
... | @@ -195,10 +195,14 @@ typedef struct | ... | @@ -195,10 +195,14 @@ typedef struct |
195 | mu_header_t header; | 195 | mu_header_t header; |
196 | } mh_context_t; | 196 | } mh_context_t; |
197 | 197 | ||
198 | #define MH_MSGSET_UID 0x01 | ||
199 | |||
198 | typedef struct | 200 | typedef struct |
199 | { | 201 | { |
200 | size_t count; | 202 | int flags; |
201 | size_t *list; | 203 | size_t *list; |
204 | size_t count; | ||
205 | size_t size; | ||
202 | } mh_msgset_t; | 206 | } mh_msgset_t; |
203 | 207 | ||
204 | typedef void (*mh_iterator_fp) (mu_mailbox_t mbox, mu_message_t msg, | 208 | typedef void (*mh_iterator_fp) (mu_mailbox_t mbox, mu_message_t msg, |
... | @@ -300,8 +304,8 @@ int mh_message_number (mu_message_t msg, size_t *pnum); | ... | @@ -300,8 +304,8 @@ int mh_message_number (mu_message_t msg, size_t *pnum); |
300 | 304 | ||
301 | mu_mailbox_t mh_open_folder (const char *folder, int create); | 305 | mu_mailbox_t mh_open_folder (const char *folder, int create); |
302 | 306 | ||
303 | int mh_msgset_parse (mu_mailbox_t mbox, mh_msgset_t *msgset, | 307 | void mh_msgset_parse (mu_mailbox_t mbox, mh_msgset_t *msgset, |
304 | int argc, char **argv, char *def); | 308 | int argc, char **argv, char *def); |
305 | int mh_msgset_member (mh_msgset_t *msgset, size_t num); | 309 | int mh_msgset_member (mh_msgset_t *msgset, size_t num); |
306 | void mh_msgset_reverse (mh_msgset_t *msgset); | 310 | void mh_msgset_reverse (mh_msgset_t *msgset); |
307 | void mh_msgset_negate (mu_mailbox_t mbox, mh_msgset_t *msgset); | 311 | void mh_msgset_negate (mu_mailbox_t mbox, mh_msgset_t *msgset); | ... | ... |
... | @@ -998,14 +998,14 @@ mh_draft_message (const char *name, const char *msgspec, char **pname) | ... | @@ -998,14 +998,14 @@ mh_draft_message (const char *name, const char *msgspec, char **pname) |
998 | 998 | ||
999 | argv[0] = (char*) msgspec; | 999 | argv[0] = (char*) msgspec; |
1000 | argv[1] = NULL; | 1000 | argv[1] = NULL; |
1001 | rc = mh_msgset_parse (mbox, &msgset, 1, argv, "cur"); | 1001 | mh_msgset_parse (mbox, &msgset, 1, argv, "cur"); |
1002 | if (rc) | 1002 | if (msgset.count > 1) |
1003 | mu_error (_("invalid message number: %s"), msgspec); | ||
1004 | else if (msgset.count > 1) | ||
1005 | mu_error (_("only one message at a time!")); | 1003 | mu_error (_("only one message at a time!")); |
1006 | else | 1004 | else |
1007 | uid = msgset.list[0]; | 1005 | { |
1008 | 1006 | mh_msgset_uids (mbox, &msgset); | |
1007 | uid = msgset.list[0]; | ||
1008 | } | ||
1009 | mh_msgset_free (&msgset); | 1009 | mh_msgset_free (&msgset); |
1010 | } | 1010 | } |
1011 | 1011 | ... | ... |
... | @@ -19,473 +19,184 @@ | ... | @@ -19,473 +19,184 @@ |
19 | 19 | ||
20 | #include <mh.h> | 20 | #include <mh.h> |
21 | 21 | ||
22 | /* Expand a message set (msgcnt;msglist) to accomodate `inc' more | 22 | int |
23 | elements */ | 23 | mh_uid_to_msgno (mu_mailbox_t mbox, size_t uid, size_t *msgno) |
24 | static void | ||
25 | _expand (size_t *msgcnt, size_t **msglist, size_t inc) | ||
26 | { | 24 | { |
27 | if (!inc) | 25 | size_t num = mh_get_message (mbox, uid, NULL); |
28 | return; | 26 | if (num == 0) |
29 | 27 | return MU_ERR_NOENT; | |
30 | *msgcnt += inc; | 28 | *msgno = num; |
31 | *msglist = realloc (*msglist, (*msgcnt)*sizeof(**msglist)); | 29 | return 0; |
32 | if (!*msglist) | ||
33 | mh_err_memory (1); | ||
34 | } | 30 | } |
35 | 31 | ||
36 | /* Fatal error handler */ | 32 | int |
37 | static void | 33 | mh_msgno_to_uid (mu_mailbox_t mbox, size_t msgno, size_t *uid) |
38 | msgset_abort (const char *arg) | ||
39 | { | 34 | { |
40 | mu_error (_("bad message list `%s'"), arg); | 35 | mu_message_t msg; |
41 | exit (1); | 36 | int rc = mu_mailbox_get_message (mbox, msgno, &msg); |
37 | if (rc) | ||
38 | return rc; | ||
39 | return mu_message_get_uid (msg, uid); | ||
42 | } | 40 | } |
43 | 41 | ||
44 | /* Handlers for expansion of the reserved message names */ | 42 | |
45 | 43 | void | |
46 | static int | 44 | mh_msgset_init (mh_msgset_t *msgset) |
47 | msgset_first (mu_mailbox_t mbox, size_t *pnum) | ||
48 | { | 45 | { |
49 | *pnum = 1; | 46 | memset (msgset, 0, sizeof (*msgset)); |
50 | return 0; | ||
51 | } | 47 | } |
52 | 48 | ||
53 | static int | 49 | void |
54 | msgset_last (mu_mailbox_t mbox, size_t *pnum) | 50 | mh_msgset_expand (mh_msgset_t *msgset, size_t count) |
55 | { | 51 | { |
56 | int rc; | 52 | size_t rest = msgset->size - msgset->count; |
57 | size_t count = 0; | ||
58 | 53 | ||
59 | rc = mu_mailbox_messages_count (mbox, &count); | 54 | if (rest < count) |
60 | if (rc) | ||
61 | { | 55 | { |
62 | mu_error (_("cannot get last message: %s"), mu_strerror (rc)); | 56 | msgset->size += count; |
63 | exit (1); | 57 | msgset->list = xrealloc (msgset->list, |
58 | msgset->size * sizeof (msgset->list[0])); | ||
64 | } | 59 | } |
65 | *pnum = count; | ||
66 | return 0; | ||
67 | } | 60 | } |
68 | 61 | ||
69 | static int | 62 | void |
70 | msgset_cur (mu_mailbox_t mbox, size_t *pnum) | 63 | mh_msgset_add (mh_msgset_t *msgset, size_t n) |
71 | { | 64 | { |
72 | size_t i, count = 0; | 65 | mh_msgset_expand (msgset, 1); |
73 | static int cached_n = 0; | 66 | msgset->list[msgset->count++] = n; |
74 | size_t cur; | ||
75 | |||
76 | mh_mailbox_get_cur (mbox, &cur); | ||
77 | |||
78 | if (cached_n) | ||
79 | { | ||
80 | *pnum = cached_n; | ||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | mu_mailbox_messages_count (mbox, &count); | ||
85 | for (i = 1; i <= count; i++) | ||
86 | { | ||
87 | mu_message_t msg = NULL; | ||
88 | size_t uid = 0; | ||
89 | |||
90 | mu_mailbox_get_message (mbox, i, &msg); | ||
91 | mh_message_number (msg, &uid); | ||
92 | if (uid == cur) | ||
93 | { | ||
94 | *pnum = cached_n = i; | ||
95 | return 0; | ||
96 | } | ||
97 | } | ||
98 | mu_error (_("no cur message")); | ||
99 | exit (1); | ||
100 | } | 67 | } |
101 | 68 | ||
102 | static int | 69 | static int |
103 | msgset_prev (mu_mailbox_t mbox, size_t *pnum) | 70 | comp_mesg (const void *a, const void *b) |
104 | { | 71 | { |
105 | size_t cur_n = 0; | 72 | size_t an = *(size_t*)a; |
106 | msgset_cur (mbox, &cur_n); | 73 | size_t bn = *(size_t*)b; |
107 | if (cur_n < 1) | 74 | if (an > bn) |
108 | { | 75 | return 1; |
109 | mu_error (_("no prev message")); | 76 | else if (an < bn) |
110 | exit (1); | 77 | return -1; |
111 | } | ||
112 | *pnum = cur_n - 1; | ||
113 | return 0; | 78 | return 0; |
114 | } | 79 | } |
115 | 80 | ||
116 | static int | 81 | void |
117 | msgset_next (mu_mailbox_t mbox, size_t *pnum) | 82 | mh_msgset_optimize (mh_msgset_t *msgset) |
118 | { | 83 | { |
119 | size_t cur_n = 0, total = 0; | 84 | size_t i, msgno; |
120 | msgset_cur (mbox, &cur_n); | 85 | size_t msgcnt = msgset->count; |
121 | mu_mailbox_messages_count (mbox, &total); | 86 | size_t *msglist = msgset->list; |
122 | if (cur_n + 1 > total) | 87 | |
123 | { | 88 | /* Sort the resulting message set */ |
124 | mu_error (_("no next message")); | 89 | qsort (msglist, msgcnt, sizeof (*msgset->list), comp_mesg); |
125 | exit (1); | ||
126 | } | ||
127 | *pnum = cur_n + 1; | ||
128 | return 0; | ||
129 | } | ||
130 | 90 | ||
131 | static struct msgset_keyword { | 91 | /* Remove duplicates. */ |
132 | char *name; | 92 | for (i = 0, msgno = 1; i < msgset->count; i++) |
133 | int (*handler) (mu_mailbox_t mbox, size_t *pnum); | 93 | if (msglist[msgno-1] != msglist[i]) |
134 | } keywords[] = { | 94 | msglist[msgno++] = msglist[i]; |
135 | { "first", msgset_first }, | 95 | msgset->count = msgno; |
136 | { "last", msgset_last }, | 96 | } |
137 | { "prev", msgset_prev }, | ||
138 | { "next", msgset_next }, | ||
139 | { "cur", msgset_cur }, | ||
140 | { NULL }, | ||
141 | }; | ||
142 | 97 | ||
143 | /* Preprocess a part of a complex message designation. Returns | 98 | /* Check if message with ordinal number `num' is contained in the |
144 | a pointer to the allocated memory containing expanded part of | 99 | message set. */ |
145 | the designation. Pointer to the beginning of the not expanded | 100 | int |
146 | part (in arg) is placed into *rest */ | 101 | mh_msgset_member (mh_msgset_t *msgset, size_t num) |
147 | static char * | ||
148 | msgset_preproc_part (mu_mailbox_t mbox, char *arg, char **rest) | ||
149 | { | 102 | { |
150 | struct msgset_keyword *p; | 103 | size_t i; |
151 | char *cp; | ||
152 | |||
153 | for (p = keywords; p->name; p++) | ||
154 | if (strncmp (arg, p->name, strlen (p->name)) == 0) | ||
155 | { | ||
156 | int rc; | ||
157 | size_t uid, num; | ||
158 | mu_message_t msg; | ||
159 | |||
160 | if (p->handler (mbox, &num)) | ||
161 | msgset_abort (arg); | ||
162 | rc = mu_mailbox_get_message (mbox, num, &msg); | ||
163 | if (rc) | ||
164 | { | ||
165 | mu_error (_("cannot get message %lu: %s"), | ||
166 | (unsigned long) num, mu_strerror (rc)); | ||
167 | exit (1); | ||
168 | } | ||
169 | *rest = arg + strlen (p->name); | ||
170 | mu_message_get_uid (msg, &uid); | ||
171 | return xstrdup (mu_umaxtostr (0, uid)); | ||
172 | } | ||
173 | cp = strchr (arg, '-'); | ||
174 | if (cp) | ||
175 | { | ||
176 | char *ret; | ||
177 | |||
178 | *rest = cp; | ||
179 | ret = xmalloc (cp - arg + 1); | ||
180 | memcpy (ret, arg, cp - arg); | ||
181 | ret[cp - arg] = 0; | ||
182 | return ret; | ||
183 | } | ||
184 | 104 | ||
185 | *rest = arg + strlen (arg); | 105 | for (i = 0; i < msgset->count; i++) |
186 | return strdup (arg); | 106 | if (msgset->list[i] == num) |
107 | return i + 1; | ||
108 | return 0; | ||
187 | } | 109 | } |
188 | 110 | ||
189 | /* Preprocess (expand) a single message designation */ | 111 | /* Reverse the order of messages in the message set */ |
190 | static char * | 112 | void |
191 | msgset_preproc (mu_mailbox_t mbox, char *arg) | 113 | mh_msgset_reverse (mh_msgset_t *msgset) |
192 | { | 114 | { |
193 | char *buf, *tail; | 115 | int head, tail; |
194 | |||
195 | if (strcmp (arg, "all") == 0 || strcmp (arg, ".") == 0) | ||
196 | { | ||
197 | /* Special case */ | ||
198 | arg = "first-last"; | ||
199 | } | ||
200 | 116 | ||
201 | buf = msgset_preproc_part (mbox, arg, &tail); | 117 | for (head = 0, tail = msgset->count-1; head < tail; head++, tail--) |
202 | if (tail[0] == '-') | ||
203 | { | ||
204 | char *rest = msgset_preproc_part (mbox, tail+1, &tail); | ||
205 | char *p = NULL; | ||
206 | mu_asprintf (&p, "%s-%s", buf, rest); | ||
207 | free (rest); | ||
208 | free (buf); | ||
209 | buf = p; | ||
210 | } | ||
211 | |||
212 | if (tail[0]) | ||
213 | { | 118 | { |
214 | char *p = NULL; | 119 | size_t val = msgset->list[head]; |
215 | mu_asprintf (&p, "%s%s", buf, tail); | 120 | msgset->list[head] = msgset->list[tail]; |
216 | free (buf); | 121 | msgset->list[tail] = val; |
217 | buf = p; | ||
218 | } | 122 | } |
219 | return buf; | ||
220 | } | 123 | } |
221 | 124 | ||
222 | static int | 125 | /* Set the current message to that contained at position `index' |
223 | comp_mesg (const void *a, const void *b) | 126 | in the given message set */ |
224 | { | 127 | void |
225 | if (*(size_t*)a > *(size_t*)b) | 128 | mh_msgset_current (mu_mailbox_t mbox, mh_msgset_t *msgset, int index) |
226 | return 1; | ||
227 | else if (*(size_t*)a < *(size_t*)b) | ||
228 | return -1; | ||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static int _mh_msgset_parse (mu_mailbox_t mbox, mh_msgset_t *msgset, | ||
233 | int argc, char **argv); | ||
234 | |||
235 | /* Treat arg as a name of user-defined sequence and attempt to | ||
236 | expand it. Return 0 if succeeded, non-zero otherwise. */ | ||
237 | int | ||
238 | expand_user_seq (mu_mailbox_t mbox, mh_msgset_t *msgset, char *arg) | ||
239 | { | 129 | { |
240 | struct mu_wordsplit ws; | 130 | mu_message_t msg = NULL; |
241 | char *p; | 131 | int rc; |
242 | const char *listp; | 132 | size_t cur; |
243 | int rc = 1; | ||
244 | int negate = 0; | ||
245 | |||
246 | p = strchr (arg, ':'); | ||
247 | if (p) | ||
248 | *p++ = 0; | ||
249 | listp = mh_global_sequences_get (mbox, arg, NULL); | ||
250 | if (!listp) | ||
251 | { | ||
252 | int len; | ||
253 | const char *neg = mh_global_profile_get ("Sequence-Negation", NULL); | ||
254 | if (!neg) | ||
255 | return 1; | ||
256 | len = strlen (neg); | ||
257 | if (strncmp (arg, neg, len)) | ||
258 | return 1; | ||
259 | negate = 1; | ||
260 | listp = mh_global_sequences_get (mbox, arg + len, NULL); | ||
261 | if (!listp) | ||
262 | return 1; | ||
263 | } | ||
264 | |||
265 | if (mu_wordsplit (listp, &ws, MU_WRDSF_DEFFLAGS)) | ||
266 | { | ||
267 | mu_error (_("cannot split line `%s': %s"), listp, | ||
268 | mu_wordsplit_strerror (&ws)); | ||
269 | } | ||
270 | else | ||
271 | { | ||
272 | rc = _mh_msgset_parse (mbox, msgset, ws.ws_wordc, ws.ws_wordv); | ||
273 | mu_wordsplit_free (&ws); | ||
274 | } | ||
275 | 133 | ||
134 | rc = mu_mailbox_get_message (mbox, msgset->list[index], &msg); | ||
276 | if (rc) | 135 | if (rc) |
277 | return rc; | ||
278 | |||
279 | if (negate) | ||
280 | mh_msgset_negate (mbox, msgset); | ||
281 | |||
282 | if (p) | ||
283 | { | 136 | { |
284 | int first, num; | 137 | mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_get_message", NULL, rc); |
285 | 138 | exit (1); | |
286 | num = strtoul (p, &p, 0); | ||
287 | if (*p) | ||
288 | { | ||
289 | mh_msgset_free (msgset); | ||
290 | return 1; | ||
291 | } | ||
292 | if (num < 0) | ||
293 | { | ||
294 | first = num + msgset->count; | ||
295 | num = - num; | ||
296 | } | ||
297 | else | ||
298 | first = 0; | ||
299 | if (num > msgset->count) | ||
300 | { | ||
301 | mh_msgset_free (msgset); | ||
302 | return 1; | ||
303 | } | ||
304 | |||
305 | if (first > 0) | ||
306 | memmove (msgset->list, &msgset->list[first], | ||
307 | sizeof (msgset->list[0]) * num); | ||
308 | msgset->count = num; | ||
309 | } | 139 | } |
310 | 140 | mh_message_number (msg, &cur); | |
311 | return rc; | 141 | mh_mailbox_set_cur (mbox, cur); |
312 | } | 142 | } |
313 | 143 | ||
314 | /* Parse a message specification from (argc;argv). Returned msgset is | 144 | /* Free memory allocated for the message set. Note, that the msgset |
315 | not sorted nor optimised */ | 145 | itself is supposed to reside in the statically allocated memory and |
316 | int | 146 | therefore is not freed */ |
317 | _mh_msgset_parse (mu_mailbox_t mbox, mh_msgset_t *msgset, int argc, char **argv) | 147 | void |
148 | mh_msgset_free (mh_msgset_t *msgset) | ||
318 | { | 149 | { |
319 | size_t msgcnt; | 150 | if (msgset->count) |
320 | size_t *msglist; | 151 | free (msgset->list); |
321 | size_t i, msgno; | ||
322 | |||
323 | if (argc == 0) | ||
324 | return 1; | ||
325 | |||
326 | msgcnt = argc; | ||
327 | msglist = calloc (msgcnt, sizeof(*msglist)); | ||
328 | for (i = 0, msgno = 0; i < argc; i++) | ||
329 | { | ||
330 | char *p = NULL, *q; | ||
331 | size_t start, end; | ||
332 | size_t msg_first, n; | ||
333 | long num; | ||
334 | char *arg = msgset_preproc (mbox, argv[i]); | ||
335 | |||
336 | if (!mu_isdigit (arg[0])) | ||
337 | { | ||
338 | int j; | ||
339 | mh_msgset_t m; | ||
340 | |||
341 | if (expand_user_seq (mbox, &m, arg)) | ||
342 | { | ||
343 | mu_error (_("message set %s does not exist"), arg); | ||
344 | exit (1); | ||
345 | } | ||
346 | _expand (&msgcnt, &msglist, m.count); | ||
347 | for (j = 0; j < m.count; j++) | ||
348 | msglist[msgno++] = m.list[j]; | ||
349 | mh_msgset_free (&m); | ||
350 | } | ||
351 | else | ||
352 | { | ||
353 | start = strtoul (arg, &p, 0); | ||
354 | switch (*p) | ||
355 | { | ||
356 | case 0: | ||
357 | n = mh_get_message (mbox, start, NULL); | ||
358 | if (!n) | ||
359 | { | ||
360 | mu_error (_("message %lu does not exist"), | ||
361 | (unsigned long) start); | ||
362 | exit (1); | ||
363 | } | ||
364 | msglist[msgno++] = n; | ||
365 | break; | ||
366 | |||
367 | case '-': | ||
368 | end = strtoul (p+1, &p, 0); | ||
369 | if (*p) | ||
370 | msgset_abort (argv[i]); | ||
371 | if (end < start) | ||
372 | { | ||
373 | size_t t = start; | ||
374 | start = end; | ||
375 | end = t; | ||
376 | } | ||
377 | _expand (&msgcnt, &msglist, end - start); | ||
378 | msg_first = msgno; | ||
379 | for (; start <= end; start++) | ||
380 | { | ||
381 | n = mh_get_message (mbox, start, NULL); | ||
382 | if (n) | ||
383 | msglist[msgno++] = n; | ||
384 | } | ||
385 | if (msgno == msg_first) | ||
386 | { | ||
387 | mu_error (_("no messages in range %s"), argv[i]); | ||
388 | exit (1); | ||
389 | } | ||
390 | break; | ||
391 | |||
392 | case ':': | ||
393 | num = strtoul (p+1, &q, 0); | ||
394 | if (*q) | ||
395 | msgset_abort (argv[i]); | ||
396 | if (p[1] != '+' && p[1] != '-') | ||
397 | { | ||
398 | if (strncmp (argv[i], "last:", 5) == 0 | ||
399 | || strncmp (argv[i], "prev:", 5) == 0) | ||
400 | num = -num; | ||
401 | } | ||
402 | end = start + num; | ||
403 | if (end < start) | ||
404 | { | ||
405 | size_t t = start; | ||
406 | start = end + 1; | ||
407 | end = t; | ||
408 | } | ||
409 | else | ||
410 | end--; | ||
411 | _expand (&msgcnt, &msglist, end - start); | ||
412 | msg_first = msgno; | ||
413 | for (; start <= end; start++) | ||
414 | { | ||
415 | n = mh_get_message (mbox, start, NULL); | ||
416 | if (n) | ||
417 | msglist[msgno++] = n; | ||
418 | } | ||
419 | if (msgno == msg_first) | ||
420 | { | ||
421 | mu_error (_("no messages in range %s"), argv[i]); | ||
422 | exit (1); | ||
423 | } | ||
424 | break; | ||
425 | |||
426 | default: | ||
427 | msgset_abort (argv[i]); | ||
428 | } | ||
429 | } | ||
430 | free (arg); | ||
431 | } | ||
432 | |||
433 | msgset->count = msgno; | ||
434 | msgset->list = msglist; | ||
435 | return 0; | ||
436 | } | 152 | } |
437 | 153 | ||
438 | /* Parse a message specification from (argc;argv). Returned msgset is | 154 | /* Negate the message set: on return `msgset' consists of the messages |
439 | sorted and optimised (i.e. it does not contain duplicate message | 155 | _not contained_ in the input message set. Any memory associated with |
440 | numbers) */ | 156 | the input message set is freed */ |
441 | int | 157 | void |
442 | mh_msgset_parse (mu_mailbox_t mbox, mh_msgset_t *msgset, | 158 | mh_msgset_negate (mu_mailbox_t mbox, mh_msgset_t *msgset) |
443 | int argc, char **argv, char *def) | ||
444 | { | 159 | { |
445 | char *xargv[2]; | 160 | size_t i, total = 0, msgno; |
446 | int rc; | 161 | size_t *list; |
447 | 162 | ||
448 | if (argc == 0) | 163 | mu_mailbox_messages_count (mbox, &total); |
164 | list = calloc (total, sizeof (list[0])); | ||
165 | if (!list) | ||
166 | mh_err_memory (1); | ||
167 | for (i = 1, msgno = 0; i <= total; i++) | ||
449 | { | 168 | { |
450 | argc = 1; | 169 | if (!mh_msgset_member (msgset, i)) |
451 | argv = xargv; | 170 | list[msgno++] = i; |
452 | argv[0] = def ? def : "cur"; | ||
453 | argv[1] = NULL; | ||
454 | } | 171 | } |
455 | |||
456 | rc = _mh_msgset_parse (mbox, msgset, argc, argv); | ||
457 | 172 | ||
458 | if (rc == 0) | 173 | list = realloc (list, sizeof (list[0]) * msgno); |
174 | if (!list) | ||
459 | { | 175 | { |
460 | size_t i, msgno; | 176 | mu_error (_("not enough memory")); |
461 | size_t msgcnt = msgset->count; | 177 | abort (); |
462 | size_t *msglist = msgset->list; | ||
463 | |||
464 | /* Sort the resulting message set */ | ||
465 | qsort (msglist, msgcnt, sizeof (*msgset->list), comp_mesg); | ||
466 | |||
467 | /* Remove duplicates. */ | ||
468 | for (i = 0, msgno = 1; i < msgset->count; i++) | ||
469 | if (msglist[msgno-1] != msglist[i]) | ||
470 | msglist[msgno++] = msglist[i]; | ||
471 | msgset->count = msgno; | ||
472 | } | 178 | } |
473 | return rc; | 179 | mh_msgset_free (msgset); |
180 | msgset->count = msgno; | ||
181 | msgset->list = list; | ||
474 | } | 182 | } |
475 | 183 | ||
476 | /* Check if message with ordinal number `num' is contained in the | 184 | void |
477 | message set. */ | 185 | mh_msgset_uids (mu_mailbox_t mbox, mh_msgset_t *msgset) |
478 | int | ||
479 | mh_msgset_member (mh_msgset_t *msgset, size_t num) | ||
480 | { | 186 | { |
481 | size_t i; | 187 | size_t i; |
482 | 188 | ||
189 | if (msgset->flags & MH_MSGSET_UID) | ||
190 | return; | ||
483 | for (i = 0; i < msgset->count; i++) | 191 | for (i = 0; i < msgset->count; i++) |
484 | if (msgset->list[i] == num) | 192 | { |
485 | return i + 1; | 193 | mu_message_t msg; |
486 | return 0; | 194 | mu_mailbox_get_message (mbox, msgset->list[i], &msg); |
195 | mh_message_number (msg, &msgset->list[i]); | ||
196 | } | ||
197 | msgset->flags |= MH_MSGSET_UID; | ||
487 | } | 198 | } |
488 | 199 | ||
489 | /* Auxiliary function. Performs binary search for a message with the | 200 | /* Auxiliary function. Performs binary search for a message with the |
490 | given sequence number */ | 201 | given sequence number */ |
491 | static size_t | 202 | static size_t |
... | @@ -555,87 +266,457 @@ mh_get_message (mu_mailbox_t mbox, size_t seqno, mu_message_t *mesg) | ... | @@ -555,87 +266,457 @@ mh_get_message (mu_mailbox_t mbox, size_t seqno, mu_message_t *mesg) |
555 | return mh_search_message (mbox, 1, count, seqno, mesg); | 266 | return mh_search_message (mbox, 1, count, seqno, mesg); |
556 | } | 267 | } |
557 | 268 | ||
558 | /* Reverse the order of messages in the message set */ | 269 | |
559 | void | 270 | struct msgset_parser |
560 | mh_msgset_reverse (mh_msgset_t *msgset) | ||
561 | { | 271 | { |
562 | int head, tail; | 272 | mu_mailbox_t mbox; |
273 | mh_msgset_t *msgset; | ||
274 | char *curp; | ||
275 | int argc; | ||
276 | char **argv; | ||
277 | |||
278 | int sign; | ||
279 | size_t number; | ||
280 | int validuid; | ||
281 | }; | ||
563 | 282 | ||
564 | for (head = 0, tail = msgset->count-1; head < tail; head++, tail--) | 283 | static void |
284 | msgset_parser_init (struct msgset_parser *parser, mu_mailbox_t mbox, | ||
285 | mh_msgset_t *msgset, int argc, char **argv) | ||
286 | { | ||
287 | parser->mbox = mbox; | ||
288 | parser->msgset = msgset; | ||
289 | parser->argc = argc; | ||
290 | parser->argv = argv; | ||
291 | parser->curp = ""; | ||
292 | |||
293 | parser->sign = 0; | ||
294 | parser->number = 0; | ||
295 | } | ||
296 | |||
297 | static void | ||
298 | msgset_abort (const char *arg) | ||
299 | { | ||
300 | mu_error (_("bad message list `%s'"), arg); | ||
301 | exit (1); | ||
302 | } | ||
303 | |||
304 | static void | ||
305 | emptyrange_abort (const char *range) | ||
306 | { | ||
307 | mu_error (_("no messages in range %s"), range); | ||
308 | exit (1); | ||
309 | } | ||
310 | |||
311 | /* Advance parser to the next argument */ | ||
312 | static int | ||
313 | nextarg (struct msgset_parser *parser) | ||
314 | { | ||
315 | if (parser->argc == 0) | ||
316 | return 0; | ||
317 | parser->argc--; | ||
318 | parser->curp = *parser->argv++; | ||
319 | return 1; | ||
320 | } | ||
321 | |||
322 | static void msgset_parser_run (struct msgset_parser *parser); | ||
323 | |||
324 | static int | ||
325 | _expand_sequence (struct msgset_parser *parser, char *term) | ||
326 | { | ||
327 | struct mu_wordsplit ws; | ||
328 | const char *listp; | ||
329 | int negate = 0; | ||
330 | |||
331 | listp = mh_global_sequences_get (parser->mbox, term, NULL); | ||
332 | if (!listp) | ||
565 | { | 333 | { |
566 | size_t val = msgset->list[head]; | 334 | int len; |
567 | msgset->list[head] = msgset->list[tail]; | 335 | const char *neg = mh_global_profile_get ("Sequence-Negation", NULL); |
568 | msgset->list[tail] = val; | 336 | if (!neg) |
337 | return 1; | ||
338 | len = strlen (neg); | ||
339 | if (strncmp (term, neg, len)) | ||
340 | return 1; | ||
341 | negate = 1; | ||
342 | listp = mh_global_sequences_get (parser->mbox, term + len, NULL); | ||
343 | if (!listp) | ||
344 | return 1; | ||
345 | } | ||
346 | |||
347 | if (mu_wordsplit (listp, &ws, MU_WRDSF_DEFFLAGS)) | ||
348 | { | ||
349 | mu_error (_("cannot split line `%s': %s"), listp, | ||
350 | mu_wordsplit_strerror (&ws)); | ||
351 | exit (1); | ||
352 | } | ||
353 | else | ||
354 | { | ||
355 | struct msgset_parser clone; | ||
356 | |||
357 | msgset_parser_init (&clone, parser->mbox, parser->msgset, | ||
358 | ws.ws_wordc, ws.ws_wordv); | ||
359 | msgset_parser_run (&clone); | ||
360 | mu_wordsplit_free (&ws); | ||
569 | } | 361 | } |
362 | |||
363 | if (negate) | ||
364 | mh_msgset_negate (parser->mbox, parser->msgset); | ||
365 | return 0; | ||
570 | } | 366 | } |
571 | 367 | ||
572 | /* Set the current message to that contained at position `index' | 368 | static int |
573 | in the given message set */ | 369 | parse_count (struct msgset_parser *parser) |
574 | void | 370 | { |
575 | mh_msgset_current (mu_mailbox_t mbox, mh_msgset_t *msgset, int index) | 371 | char *endp; |
372 | if (!*parser->curp && nextarg (parser) == 0) | ||
373 | return 0; | ||
374 | if (*parser->curp == '-') | ||
375 | { | ||
376 | parser->sign = 1; | ||
377 | parser->curp++; | ||
378 | } | ||
379 | else if (*parser->curp == '+') | ||
380 | { | ||
381 | parser->sign = 0; | ||
382 | parser->curp++; | ||
383 | } | ||
384 | parser->number = strtoul (parser->curp, &endp, 10); | ||
385 | if (*endp) | ||
386 | msgset_abort (parser->curp); | ||
387 | parser->curp = endp; | ||
388 | return 1; | ||
389 | } | ||
390 | |||
391 | |||
392 | static int | ||
393 | msgset_first (mu_mailbox_t mbox, size_t *pnum) | ||
394 | { | ||
395 | *pnum = 1; | ||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | static int | ||
400 | msgset_last (mu_mailbox_t mbox, size_t *pnum) | ||
576 | { | 401 | { |
577 | mu_message_t msg = NULL; | ||
578 | int rc; | 402 | int rc; |
579 | size_t cur; | 403 | |
580 | 404 | rc = mu_mailbox_messages_count (mbox, pnum); | |
581 | rc = mu_mailbox_get_message (mbox, msgset->list[index], &msg); | ||
582 | if (rc) | 405 | if (rc) |
583 | { | 406 | { |
584 | mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_get_message", NULL, rc); | 407 | mu_error (_("cannot get last message: %s"), mu_strerror (rc)); |
585 | exit (1); | 408 | exit (1); |
586 | } | 409 | } |
587 | mh_message_number (msg, &cur); | 410 | return 0; |
588 | mh_mailbox_set_cur (mbox, cur); | ||
589 | } | 411 | } |
590 | 412 | ||
591 | /* Free memory allocated for the message set. Note, that the msgset | 413 | static int |
592 | itself is supposed to reside in the statically allocated memory and | 414 | msgset_cur (mu_mailbox_t mbox, size_t *pnum) |
593 | therefore is not freed */ | ||
594 | void | ||
595 | mh_msgset_free (mh_msgset_t *msgset) | ||
596 | { | 415 | { |
597 | if (msgset->count) | 416 | size_t num; |
598 | free (msgset->list); | 417 | mh_mailbox_get_cur (mbox, &num); |
418 | return mh_uid_to_msgno (mbox, num, pnum); | ||
599 | } | 419 | } |
600 | 420 | ||
601 | /* Negate the message set: on return `msgset' consists of the messages | 421 | static int |
602 | _not contained_ in the input message set. Any memory associated with | 422 | msgset_prev (mu_mailbox_t mbox, size_t *pnum) |
603 | the input message set is freed */ | ||
604 | void | ||
605 | mh_msgset_negate (mu_mailbox_t mbox, mh_msgset_t *msgset) | ||
606 | { | 423 | { |
607 | size_t i, total = 0, msgno; | 424 | size_t cur_n = 0; |
608 | size_t *list; | 425 | msgset_cur (mbox, &cur_n); |
426 | if (cur_n < 1) | ||
427 | { | ||
428 | mu_error (_("no prev message")); | ||
429 | exit (1); | ||
430 | } | ||
431 | *pnum = cur_n - 1; | ||
432 | return 0; | ||
433 | } | ||
609 | 434 | ||
435 | static int | ||
436 | msgset_next (mu_mailbox_t mbox, size_t *pnum) | ||
437 | { | ||
438 | size_t cur_n = 0, total = 0; | ||
439 | msgset_cur (mbox, &cur_n); | ||
610 | mu_mailbox_messages_count (mbox, &total); | 440 | mu_mailbox_messages_count (mbox, &total); |
611 | list = calloc (total, sizeof (list[0])); | 441 | if (cur_n + 1 > total) |
612 | if (!list) | ||
613 | mh_err_memory (1); | ||
614 | for (i = 1, msgno = 0; i <= total; i++) | ||
615 | { | 442 | { |
616 | if (!mh_msgset_member (msgset, i)) | 443 | mu_error (_("no next message")); |
617 | list[msgno++] = i; | 444 | exit (1); |
618 | } | 445 | } |
446 | *pnum = cur_n + 1; | ||
447 | return 0; | ||
448 | } | ||
619 | 449 | ||
620 | list = realloc (list, sizeof (list[0]) * msgno); | 450 | struct msgset_keyword |
621 | if (!list) | 451 | { |
452 | char *name; | ||
453 | size_t len; | ||
454 | int (*handler) (mu_mailbox_t mbox, size_t *pnum); | ||
455 | int sign; | ||
456 | }; | ||
457 | |||
458 | static struct msgset_keyword keywords[] = { | ||
459 | #define S(s) #s, sizeof (#s) - 1 | ||
460 | { S(first), msgset_first, 0 }, | ||
461 | { S(last), msgset_last, 1 }, | ||
462 | { S(prev), msgset_prev, 1 }, | ||
463 | { S(next), msgset_next, 0 }, | ||
464 | { S(cur), msgset_cur, 0 }, | ||
465 | { NULL } | ||
466 | }; | ||
467 | |||
468 | #define PARSE_EOF 0 | ||
469 | #define PARSE_MORE 1 | ||
470 | #define PARSE_SUCCESS 2 | ||
471 | |||
472 | /* term : NUMBER | ||
473 | | "first" | ||
474 | | "last" | ||
475 | | "cur" | ||
476 | | "prev" | ||
477 | | "next" | ||
478 | ; | ||
479 | */ | ||
480 | static int | ||
481 | parse_term (struct msgset_parser *parser, int seq) | ||
482 | { | ||
483 | size_t tlen; | ||
484 | char *term; | ||
485 | |||
486 | if (!*parser->curp && nextarg (parser) == 0) | ||
487 | return PARSE_EOF; | ||
488 | |||
489 | term = parser->curp; | ||
490 | parser->curp = mu_str_skip_class (term, MU_CTYPE_ALPHA|MU_CTYPE_DIGIT); | ||
491 | tlen = parser->curp - term; | ||
492 | if (mu_isalpha (*term)) | ||
622 | { | 493 | { |
623 | mu_error (_("not enough memory")); | 494 | struct msgset_keyword *p; |
624 | abort (); | 495 | |
496 | for (p = keywords; p->name; p++) | ||
497 | if (tlen == p->len && memcmp (p->name, term, tlen) == 0) | ||
498 | { | ||
499 | if (p->handler (parser->mbox, &parser->number)) | ||
500 | msgset_abort (term); | ||
501 | parser->sign = p->sign; | ||
502 | parser->validuid = 1; | ||
503 | return PARSE_MORE; | ||
504 | } | ||
505 | |||
506 | if (*parser->curp == 0 && seq) | ||
507 | { | ||
508 | /* See if it is a user-defined sequence */ | ||
509 | if (_expand_sequence (parser, term) == 0) | ||
510 | return PARSE_SUCCESS; | ||
511 | } | ||
512 | msgset_abort (term); | ||
625 | } | 513 | } |
626 | mh_msgset_free (msgset); | 514 | else if (mu_isdigit (*term)) |
627 | msgset->count = msgno; | 515 | { |
628 | msgset->list = list; | 516 | char *endp; |
517 | size_t num = strtoul (term, &endp, 10); | ||
518 | if (endp != parser->curp) | ||
519 | msgset_abort (term); | ||
520 | |||
521 | if (mh_uid_to_msgno (parser->mbox, num, &parser->number)) | ||
522 | { | ||
523 | parser->validuid = 0; | ||
524 | parser->number = num; | ||
525 | } | ||
526 | else | ||
527 | parser->validuid = 1; | ||
528 | parser->sign = 0; | ||
529 | } | ||
530 | else | ||
531 | msgset_abort (term); | ||
532 | return PARSE_MORE; | ||
629 | } | 533 | } |
630 | 534 | ||
631 | void | 535 | static void |
632 | mh_msgset_uids (mu_mailbox_t mbox, mh_msgset_t *msgset) | 536 | add_messages (struct msgset_parser *parser, size_t start, size_t count, |
537 | int sign) | ||
633 | { | 538 | { |
634 | size_t i; | 539 | size_t i; |
635 | for (i = 0; i < msgset->count; i++) | 540 | |
541 | if (start == 0) | ||
542 | start = 1; | ||
543 | mh_msgset_expand (parser->msgset, count); | ||
544 | if (sign) | ||
636 | { | 545 | { |
637 | mu_message_t msg; | 546 | if (count > start) |
638 | mu_mailbox_get_message (mbox, msgset->list[i], &msg); | 547 | count = start; |
639 | mh_message_number (msg, &msgset->list[i]); | 548 | for (i = 0; i < count; i++, start--) |
549 | parser->msgset->list[parser->msgset->count++] = start; | ||
550 | } | ||
551 | else | ||
552 | { | ||
553 | size_t total; | ||
554 | |||
555 | mu_mailbox_messages_count (parser->mbox, &total); | ||
556 | if (start + count > total) | ||
557 | count = total - start + 1; | ||
558 | for (i = 0; i < count; i++, start++) | ||
559 | parser->msgset->list[parser->msgset->count++] = start; | ||
560 | } | ||
561 | if (count == 0) | ||
562 | emptyrange_abort (parser->argv[-1]); | ||
563 | } | ||
564 | |||
565 | static void | ||
566 | add_message_range (struct msgset_parser *parser, size_t start, size_t end) | ||
567 | { | ||
568 | if (end == start) | ||
569 | emptyrange_abort (parser->argv[-1]); | ||
570 | |||
571 | if (end < start) | ||
572 | { | ||
573 | size_t t = start; | ||
574 | start = end; | ||
575 | end = t; | ||
576 | } | ||
577 | mh_msgset_expand (parser->msgset, end - start + 1); | ||
578 | |||
579 | for (; start <= end; start++) | ||
580 | parser->msgset->list[parser->msgset->count++] = start; | ||
581 | } | ||
582 | |||
583 | /* range: term '-' term | ||
584 | | term ':' count | ||
585 | ; | ||
586 | count: NUMBER | ||
587 | | '+' NUMBER | ||
588 | | '-' NUMBER | ||
589 | ; | ||
590 | */ | ||
591 | static int | ||
592 | parse_range (struct msgset_parser *parser) | ||
593 | { | ||
594 | size_t start; | ||
595 | |||
596 | switch (parse_term (parser, 1)) | ||
597 | { | ||
598 | case PARSE_EOF: | ||
599 | return 0; | ||
600 | |||
601 | case PARSE_SUCCESS: | ||
602 | return 1; | ||
603 | |||
604 | case PARSE_MORE: | ||
605 | break; | ||
606 | } | ||
607 | |||
608 | start = parser->number; | ||
609 | |||
610 | if (*parser->curp == ':') | ||
611 | { | ||
612 | int validuid = parser->validuid; | ||
613 | parser->curp++; | ||
614 | if (parse_count (parser) == 0) | ||
615 | return 0; | ||
616 | if (!validuid) | ||
617 | { | ||
618 | size_t total, lastuid; | ||
619 | msgset_last (parser->mbox, &total); | ||
620 | mh_msgno_to_uid (parser->mbox, total, &lastuid); | ||
621 | if (start > lastuid) | ||
622 | { | ||
623 | if (!parser->sign) | ||
624 | emptyrange_abort (parser->argv[-1]); | ||
625 | start = total; | ||
626 | } | ||
627 | else | ||
628 | { | ||
629 | if (parser->sign) | ||
630 | emptyrange_abort (parser->argv[-1]); | ||
631 | start = 1; | ||
632 | } | ||
633 | } | ||
634 | add_messages (parser, start, parser->number, parser->sign); | ||
635 | return 1; | ||
636 | } | ||
637 | else if (*parser->curp == '-') | ||
638 | { | ||
639 | size_t lastuid = 0; | ||
640 | int validuid = parser->validuid; | ||
641 | |||
642 | parser->curp++; | ||
643 | if (parse_term (parser, 0) == PARSE_EOF) | ||
644 | return 0; | ||
645 | if (!parser->validuid) | ||
646 | { | ||
647 | size_t total; | ||
648 | |||
649 | msgset_last (parser->mbox, &total); | ||
650 | mh_msgno_to_uid (parser->mbox, total, &lastuid); | ||
651 | if (parser->number > lastuid) | ||
652 | parser->number = total; | ||
653 | else if (!validuid) | ||
654 | emptyrange_abort (parser->argv[-1]); | ||
655 | } | ||
656 | if (!validuid) | ||
657 | { | ||
658 | if (!lastuid) | ||
659 | { | ||
660 | size_t total; | ||
661 | msgset_last (parser->mbox, &total); | ||
662 | mh_msgno_to_uid (parser->mbox, total, &lastuid); | ||
663 | } | ||
664 | if (start > lastuid && !parser->validuid) | ||
665 | emptyrange_abort (parser->argv[-1]); | ||
666 | start = 1; | ||
667 | } | ||
668 | add_message_range (parser, start, parser->number); | ||
640 | } | 669 | } |
670 | else if (!parser->validuid) | ||
671 | { | ||
672 | mu_error (_("message %s does not exist"), parser->argv[-1]); | ||
673 | exit (1); | ||
674 | } | ||
675 | else | ||
676 | mh_msgset_add (parser->msgset, start); | ||
677 | return 1; | ||
678 | } | ||
679 | |||
680 | |||
681 | /* Parse a message specification. The composed msgset is | ||
682 | not sorted nor optimised */ | ||
683 | static void | ||
684 | msgset_parser_run (struct msgset_parser *parser) | ||
685 | { | ||
686 | while (parse_range (parser)) | ||
687 | ; | ||
688 | } | ||
689 | |||
690 | /* Parse a message specification from (argc;argv). Returned msgset is | ||
691 | sorted and optimised (i.e. it does not contain duplicate message | ||
692 | numbers) */ | ||
693 | void | ||
694 | mh_msgset_parse (mu_mailbox_t mbox, mh_msgset_t *msgset, | ||
695 | int argc, char **argv, char *def) | ||
696 | { | ||
697 | struct msgset_parser parser; | ||
698 | char *xargv[2]; | ||
699 | |||
700 | if (argc == 0) | ||
701 | { | ||
702 | argc = 1; | ||
703 | argv = xargv; | ||
704 | argv[0] = def ? def : "cur"; | ||
705 | argv[1] = NULL; | ||
706 | } | ||
707 | |||
708 | if (argc == 1 && | ||
709 | (strcmp (argv[0], "all") == 0 || strcmp (argv[0], ".") == 0)) | ||
710 | { | ||
711 | argc = 1; | ||
712 | argv = xargv; | ||
713 | argv[0] = "first-last"; | ||
714 | argv[1] = NULL; | ||
715 | } | ||
716 | |||
717 | mh_msgset_init (msgset); | ||
718 | msgset_parser_init (&parser, mbox, msgset, argc, argv); | ||
719 | msgset_parser_run (&parser); | ||
720 | |||
721 | mh_msgset_optimize (msgset); | ||
641 | } | 722 | } | ... | ... |
... | @@ -346,18 +346,21 @@ _whatnow (struct mh_whatnow_env *wh, struct action_tab *tab) | ... | @@ -346,18 +346,21 @@ _whatnow (struct mh_whatnow_env *wh, struct action_tab *tab) |
346 | 346 | ||
347 | do | 347 | do |
348 | { | 348 | { |
349 | size_t n; | ||
349 | handler_fp fun; | 350 | handler_fp fun; |
350 | 351 | ||
351 | printf ("%s ", wh->prompt); | 352 | printf ("%s ", wh->prompt); |
352 | fflush (stdout); | 353 | fflush (stdout); |
353 | rc = mu_stream_getline (in, &line, &size, NULL); | 354 | rc = mu_stream_getline (in, &line, &size, &n); |
354 | if (rc) | 355 | if (rc) |
355 | { | 356 | { |
356 | mu_error (_("cannot read input stream: %s"), mu_strerror (rc)); | 357 | mu_error (_("cannot read input stream: %s"), mu_strerror (rc)); |
357 | status = 1; | 358 | status = 1; |
358 | break; | 359 | break; |
359 | } | 360 | } |
360 | 361 | if (n == 0) | |
362 | break; | ||
363 | |||
361 | ws.ws_comment = "#"; | 364 | ws.ws_comment = "#"; |
362 | rc = mu_wordsplit (line, &ws, wsflags); | 365 | rc = mu_wordsplit (line, &ws, wsflags); |
363 | if (rc) | 366 | if (rc) |
... | @@ -462,7 +465,10 @@ static int | ... | @@ -462,7 +465,10 @@ static int |
462 | call_send (struct mh_whatnow_env *wh, int argc, char **argv, int *status) | 465 | call_send (struct mh_whatnow_env *wh, int argc, char **argv, int *status) |
463 | { | 466 | { |
464 | if (invoke ("sendproc", MHBINDIR "/send", argc, argv, wh->file, NULL) == 0) | 467 | if (invoke ("sendproc", MHBINDIR "/send", argc, argv, wh->file, NULL) == 0) |
465 | annotate (wh); | 468 | { |
469 | annotate (wh); | ||
470 | return 1; | ||
471 | } | ||
466 | return 0; | 472 | return 0; |
467 | } | 473 | } |
468 | 474 | ... | ... |
mh/mhseq.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2010 Free Software Foundation, Inc. | ||
3 | |||
4 | GNU Mailutils is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | GNU Mailutils is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | /* MH mhparam command */ | ||
18 | |||
19 | #include <mh.h> | ||
20 | |||
21 | static char doc[] = N_("GNU MH mhseq")"\v" | ||
22 | N_("Use -help to obtain the list of traditional MH options."); | ||
23 | static char args_doc[] = N_("[SEQUENCE]"); | ||
24 | |||
25 | static struct argp_option options[] = { | ||
26 | {"folder", ARG_FOLDER, N_("FOLDER"), 0, | ||
27 | N_("specify the folder to use")}, | ||
28 | { "uids", 'u', NULL, 0, | ||
29 | N_("show message UIDs (default)")}, | ||
30 | { "numbers", 'n', NULL, 0, | ||
31 | N_("show message numbers") }, | ||
32 | { NULL } | ||
33 | }; | ||
34 | |||
35 | /* Traditional MH options */ | ||
36 | struct mh_option mh_option[] = { | ||
37 | { "uid" }, | ||
38 | { NULL } | ||
39 | }; | ||
40 | |||
41 | static int uid_option = 1; | ||
42 | |||
43 | static error_t | ||
44 | opt_handler (int key, char *arg, struct argp_state *state) | ||
45 | { | ||
46 | switch (key) | ||
47 | { | ||
48 | case ARG_FOLDER: | ||
49 | mh_set_current_folder (arg); | ||
50 | break; | ||
51 | |||
52 | case 'n': | ||
53 | uid_option = 0; | ||
54 | break; | ||
55 | |||
56 | case 'u': | ||
57 | uid_option = 1; | ||
58 | break; | ||
59 | |||
60 | default: | ||
61 | return ARGP_ERR_UNKNOWN; | ||
62 | } | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | int | ||
67 | main (int argc, char **argv) | ||
68 | { | ||
69 | int index; | ||
70 | mu_mailbox_t mbox; | ||
71 | mh_msgset_t msgset; | ||
72 | size_t i; | ||
73 | |||
74 | /* Native Language Support */ | ||
75 | MU_APP_INIT_NLS (); | ||
76 | |||
77 | mh_argp_init (); | ||
78 | mh_argp_parse (&argc, &argv, 0, options, mh_option, args_doc, doc, | ||
79 | opt_handler, NULL, &index); | ||
80 | |||
81 | argc -= index; | ||
82 | argv += index; | ||
83 | mbox = mh_open_folder (mh_current_folder (), 0); | ||
84 | |||
85 | mh_msgset_parse (mbox, &msgset, argc, argv, "cur"); | ||
86 | if (uid_option) | ||
87 | mh_msgset_uids (mbox, &msgset); | ||
88 | |||
89 | for (i = 0; i < msgset.count; i++) | ||
90 | printf ("%lu\n", (unsigned long) msgset.list[i]); | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 |
... | @@ -42,6 +42,7 @@ TESTSUITE_AT = \ | ... | @@ -42,6 +42,7 @@ TESTSUITE_AT = \ |
42 | ali.at\ | 42 | ali.at\ |
43 | anno.at\ | 43 | anno.at\ |
44 | burst.at\ | 44 | burst.at\ |
45 | comp.at\ | ||
45 | folder.at\ | 46 | folder.at\ |
46 | inc.at\ | 47 | inc.at\ |
47 | install-mh.at\ | 48 | install-mh.at\ |
... | @@ -49,6 +50,7 @@ TESTSUITE_AT = \ | ... | @@ -49,6 +50,7 @@ TESTSUITE_AT = \ |
49 | mhl.at\ | 50 | mhl.at\ |
50 | mhparam.at\ | 51 | mhparam.at\ |
51 | mhpath.at\ | 52 | mhpath.at\ |
53 | mhseq.at\ | ||
52 | pick.at\ | 54 | pick.at\ |
53 | scan.at\ | 55 | scan.at\ |
54 | refile.at\ | 56 | refile.at\ | ... | ... |
mh/tests/comp.at
0 → 100644
1 | # This file is part of GNU Mailutils. -*- Autotest -*- | ||
2 | # Copyright (C) 2010 Free Software Foundation, Inc. | ||
3 | # | ||
4 | # GNU Mailutils is free software; you can redistribute it and/or | ||
5 | # modify it under the terms of the GNU General Public License as | ||
6 | # published by the Free Software Foundation; either version 3, or (at | ||
7 | # your option) any later version. | ||
8 | # | ||
9 | # GNU Mailutils is distributed in the hope that it will be useful, but | ||
10 | # WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | # General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. | ||
16 | |||
17 | m4_pushdef([MH_KEYWORDS],[comp]) | ||
18 | m4_pushdef([compcmd],[comp dnl | ||
19 | -form $abs_top_srcdir/mh/components dnl | ||
20 | -editor $abs_top_srcdir/mh/tests/mhed]) | ||
21 | |||
22 | MH_CHECK([comp -file],[comp00 comp-file],[ | ||
23 | dir=`pwd` | ||
24 | echo quit | compcmd -file ./infile | sed "s|$dir/*||;s| *$||" | ||
25 | cat infile | ||
26 | ], | ||
27 | [0], | ||
28 | [-- Editor invocation: ./infile | ||
29 | -- Input file: | ||
30 | To: | ||
31 | cc: | ||
32 | Subject: | ||
33 | -------- | ||
34 | -- Input file end | ||
35 | What now? draft left on "./infile". | ||
36 | To: | ||
37 | cc: | ||
38 | Subject: | ||
39 | -------- | ||
40 | Seen by mhed | ||
41 | ]) | ||
42 | |||
43 | MH_CHECK([comp -file (del)],[comp01 comp-file_del],[ | ||
44 | dir=`pwd` | ||
45 | echo 'quit -delete' | compcmd -file ./infile | sed "s|$dir/*||;s| *$||" | ||
46 | ], | ||
47 | [0], | ||
48 | [-- Editor invocation: ./infile | ||
49 | -- Input file: | ||
50 | To: | ||
51 | cc: | ||
52 | Subject: | ||
53 | -------- | ||
54 | -- Input file end | ||
55 | What now?]) | ||
56 | |||
57 | MH_CHECK([comp file],[comp02 comp_file],[ | ||
58 | echo 'quit' | compcmd file | sed "s|$dir/*||;s| *$||" | ||
59 | cat Mail/file | ||
60 | ], | ||
61 | [0], | ||
62 | [-- Editor invocation: Mail/file | ||
63 | -- Input file: | ||
64 | To: | ||
65 | cc: | ||
66 | Subject: | ||
67 | -------- | ||
68 | -- Input file end | ||
69 | What now? draft left on "Mail/file". | ||
70 | To: | ||
71 | cc: | ||
72 | Subject: | ||
73 | -------- | ||
74 | Seen by mhed | ||
75 | ]) | ||
76 | |||
77 | MH_CHECK([comp -use file],[comp03 comp-use_file],[ | ||
78 | AT_DATA([Mail/file],[From: gray | ||
79 | To: root | ||
80 | Subject: test input | ||
81 | |||
82 | message body | ||
83 | ]) | ||
84 | |||
85 | echo 'quit' | compcmd -use file | sed "s|$dir/*||;s| *$||" | ||
86 | cat Mail/file | ||
87 | ], | ||
88 | [0], | ||
89 | [-- Editor invocation: Mail/file | ||
90 | -- Input file: | ||
91 | From: gray | ||
92 | To: root | ||
93 | Subject: test input | ||
94 | |||
95 | message body | ||
96 | -- Input file end | ||
97 | What now? draft left on "Mail/file". | ||
98 | From: gray | ||
99 | To: root | ||
100 | Subject: test input | ||
101 | |||
102 | message body | ||
103 | Seen by mhed | ||
104 | ]) | ||
105 | |||
106 | MH_CHECK([comp +folder msg],[comp04 comp+folder_msg],[ | ||
107 | mkdir Mail/inbox | ||
108 | AT_DATA([Mail/inbox/1],[From: gray | ||
109 | To: root | ||
110 | Subject: test input | ||
111 | |||
112 | message body | ||
113 | ]) | ||
114 | |||
115 | echo 'quit' | compcmd +inbox 1 | sed "s|$dir/*||;s| *$||" | ||
116 | echo Mail/draft | ||
117 | cat Mail/draft | ||
118 | echo Message | ||
119 | cat Mail/inbox/1 | ||
120 | ], | ||
121 | [0], | ||
122 | [-- Editor invocation: Mail/draft | ||
123 | -- Input file: | ||
124 | From: gray | ||
125 | To: root | ||
126 | Subject: test input | ||
127 | |||
128 | message body | ||
129 | -- Input file end | ||
130 | What now? draft left on "Mail/draft". | ||
131 | Mail/draft | ||
132 | From: gray | ||
133 | To: root | ||
134 | Subject: test input | ||
135 | |||
136 | message body | ||
137 | Seen by mhed | ||
138 | Message | ||
139 | From: gray | ||
140 | To: root | ||
141 | Subject: test input | ||
142 | |||
143 | message body | ||
144 | ]) | ||
145 | |||
146 | m4_popdef([compcmd]) | ||
147 | m4_popdef([MH_KEYWORDS]) | ||
148 |
mh/tests/mhed
0 → 100755
mh/tests/mhseq.at
0 → 100644
1 | # This file is part of GNU Mailutils. -*- Autotest -*- | ||
2 | # Copyright (C) 2010 Free Software Foundation, Inc. | ||
3 | # | ||
4 | # GNU Mailutils is free software; you can redistribute it and/or | ||
5 | # modify it under the terms of the GNU General Public License as | ||
6 | # published by the Free Software Foundation; either version 3, or (at | ||
7 | # your option) any later version. | ||
8 | # | ||
9 | # GNU Mailutils is distributed in the hope that it will be useful, but | ||
10 | # WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | # General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. | ||
16 | |||
17 | m4_pushdef([MH_KEYWORDS],[mhseq mh-sequences]) | ||
18 | |||
19 | dnl --------------------------------------------------------------- | ||
20 | |||
21 | MH_CHECK([mhseq: existing message number],[mhseq00],[ | ||
22 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
23 | mhseq 1 | ||
24 | ], | ||
25 | [0], | ||
26 | [1 | ||
27 | ]) | ||
28 | |||
29 | MH_CHECK([mhseq: not existing message number],[mhseq01],[ | ||
30 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
31 | mhseq 100 | ||
32 | ], | ||
33 | [1], | ||
34 | [], | ||
35 | dnl FIXME: See FIXME 3 in mhpath.at | ||
36 | [mhseq: message 100 does not exist | ||
37 | ]) | ||
38 | |||
39 | MH_CHECK([mhseq: contiguous message range],[mhseq02],[ | ||
40 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
41 | mhseq 2-5 | ||
42 | ], | ||
43 | [0], | ||
44 | [2 | ||
45 | 3 | ||
46 | 4 | ||
47 | 5 | ||
48 | ]) | ||
49 | |||
50 | MH_CHECK([mhseq: reversed contiguous message range],[mhseq03],[ | ||
51 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
52 | mhseq 5-2 | ||
53 | ], | ||
54 | [0], | ||
55 | [2 | ||
56 | 3 | ||
57 | 4 | ||
58 | 5 | ||
59 | ]) | ||
60 | |||
61 | MH_CHECK([mhseq: reversed non-contiguous message range],[mhseq04],[ | ||
62 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
63 | rm Mail/inbox/3 Mail/inbox/4 | ||
64 | mhseq 5-2 | ||
65 | ], | ||
66 | [0], | ||
67 | [2 | ||
68 | 5 | ||
69 | ]) | ||
70 | |||
71 | MH_CHECK([mhseq: message range (left fixup)],[mhseq05],[ | ||
72 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
73 | rm Mail/inbox/1 Mail/inbox/2 | ||
74 | mhseq 1-5 | ||
75 | ], | ||
76 | [0], | ||
77 | [3 | ||
78 | 4 | ||
79 | 5 | ||
80 | ]) | ||
81 | |||
82 | MH_CHECK([mhseq: message range (right fixup)],[mhseq06],[ | ||
83 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
84 | rm Mail/inbox/4 Mail/inbox/5 | ||
85 | mhseq 1-5 | ||
86 | ], | ||
87 | [0], | ||
88 | [1 | ||
89 | 2 | ||
90 | 3 | ||
91 | ]) | ||
92 | |||
93 | MH_CHECK([mhseq: message range (both fixups)],[mhseq07],[ | ||
94 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
95 | rm Mail/inbox/1 Mail/inbox/5 | ||
96 | mhseq 1-5 | ||
97 | ], | ||
98 | [0], | ||
99 | [2 | ||
100 | 3 | ||
101 | 4 | ||
102 | ]) | ||
103 | |||
104 | MH_CHECK([mhseq: non-existent message range (left)],[mhseq08],[ | ||
105 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
106 | rm Mail/inbox/1 Mail/inbox/2 Mail/inbox/3 | ||
107 | mhseq 1-2 | ||
108 | ], | ||
109 | [1], | ||
110 | [], | ||
111 | [mhseq: no messages in range 1-2 | ||
112 | ]) | ||
113 | |||
114 | MH_CHECK([mhseq: non-existent message range (right)],[mhseq09],[ | ||
115 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
116 | mhseq 6-10 | ||
117 | ], | ||
118 | [1], | ||
119 | [], | ||
120 | [mhseq: no messages in range 6-10 | ||
121 | ]) | ||
122 | |||
123 | MH_CHECK([mhseq: message set addition],[mhseq10],[ | ||
124 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/teaparty,[Mail/inbox]) | ||
125 | mhseq 5 8-10 15-20 | ||
126 | ], | ||
127 | [0], | ||
128 | [5 | ||
129 | 8 | ||
130 | 9 | ||
131 | 10 | ||
132 | 15 | ||
133 | 16 | ||
134 | 17 | ||
135 | 18 | ||
136 | 19 | ||
137 | 20 | ||
138 | ]) | ||
139 | |||
140 | MH_CHECK([mhseq: message set optimization],[mhseq11],[ | ||
141 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/teaparty,[Mail/inbox]) | ||
142 | rm Mail/inbox/17 Mail/inbox/19 | ||
143 | mhseq 5 1-10 15-20 | ||
144 | ], | ||
145 | [0], | ||
146 | [1 | ||
147 | 2 | ||
148 | 3 | ||
149 | 4 | ||
150 | 5 | ||
151 | 6 | ||
152 | 7 | ||
153 | 8 | ||
154 | 9 | ||
155 | 10 | ||
156 | 15 | ||
157 | 16 | ||
158 | 18 | ||
159 | 20 | ||
160 | ]) | ||
161 | |||
162 | MH_CHECK([mhseq: counted range (positive)],[mhseq12],[ | ||
163 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/teaparty,[Mail/inbox]) | ||
164 | mhseq 10:4 | ||
165 | ], | ||
166 | [0], | ||
167 | [10 | ||
168 | 11 | ||
169 | 12 | ||
170 | 13 | ||
171 | ]) | ||
172 | |||
173 | MH_CHECK([mhseq: non-contiguous counted range (positive)],[mhseq13],[ | ||
174 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/teaparty,[Mail/inbox]) | ||
175 | rm Mail/inbox/12 Mail/inbox/14 | ||
176 | mhseq 10:4 | ||
177 | ], | ||
178 | [0], | ||
179 | [10 | ||
180 | 11 | ||
181 | 13 | ||
182 | 15 | ||
183 | ]) | ||
184 | |||
185 | MH_CHECK([mhseq: counted range (positive, left fixup)],[mhseq14],[ | ||
186 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
187 | rm Mail/inbox/1 Mail/inbox/2 | ||
188 | mhseq 1:3 | ||
189 | ], | ||
190 | [0], | ||
191 | [3 | ||
192 | 4 | ||
193 | 5 | ||
194 | ]) | ||
195 | |||
196 | MH_CHECK([mhseq: counted range (positive, right fixup)],[mhseq15],[ | ||
197 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
198 | mhseq 2:10 | ||
199 | ], | ||
200 | [0], | ||
201 | [2 | ||
202 | 3 | ||
203 | 4 | ||
204 | 5 | ||
205 | ]) | ||
206 | |||
207 | MH_CHECK([mhseq: invalid counted range (negative)],[mhseq16],[ | ||
208 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
209 | rm Mail/inbox/1 Mail/inbox/2 | ||
210 | mhseq 10:2 | ||
211 | ], | ||
212 | [1], | ||
213 | [], | ||
214 | [mhseq: no messages in range 10:2 | ||
215 | ]) | ||
216 | |||
217 | MH_CHECK([mhseq: counted range (negative)],[mhseq17],[ | ||
218 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/teaparty,[Mail/inbox]) | ||
219 | mhseq 10:-4 | ||
220 | ], | ||
221 | [0], | ||
222 | [7 | ||
223 | 8 | ||
224 | 9 | ||
225 | 10 | ||
226 | ]) | ||
227 | |||
228 | MH_CHECK([mhseq: non-contiguous counted range (negative)],[mhseq18],[ | ||
229 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/teaparty,[Mail/inbox]) | ||
230 | rm Mail/inbox/8 Mail/inbox/6 | ||
231 | mhseq 10:-4 | ||
232 | ], | ||
233 | [0], | ||
234 | [5 | ||
235 | 7 | ||
236 | 9 | ||
237 | 10 | ||
238 | ]) | ||
239 | |||
240 | MH_CHECK([mhseq: counted range (negative, left fixup)],[mhseq19],[ | ||
241 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
242 | rm Mail/inbox/1 Mail/inbox/2 | ||
243 | mhseq 4:-30 | ||
244 | ], | ||
245 | [0], | ||
246 | [3 | ||
247 | 4 | ||
248 | ]) | ||
249 | |||
250 | MH_CHECK([mhseq: counted range (negative, right fixup)],[mhseq20],[ | ||
251 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
252 | rm Mail/inbox/1 Mail/inbox/2 | ||
253 | mhseq 4:30 | ||
254 | ], | ||
255 | [0], | ||
256 | [4 | ||
257 | 5 | ||
258 | ]) | ||
259 | |||
260 | MH_CHECK([mhseq: invalid counted range (negative)],[mhseq21],[ | ||
261 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
262 | rm Mail/inbox/1 Mail/inbox/2 | ||
263 | mhseq 1:-30 | ||
264 | ], | ||
265 | [1], | ||
266 | [], | ||
267 | [mhseq: no messages in range 1:-30 | ||
268 | ]) | ||
269 | |||
270 | MH_CHECK([mhseq: cur],[mhseq22 cur],[ | ||
271 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
272 | echo "cur: 3" > Mail/inbox/.mh_sequences | ||
273 | mhseq cur | ||
274 | ], | ||
275 | [0], | ||
276 | [3 | ||
277 | ]) | ||
278 | |||
279 | MH_CHECK([mhseq: cur:n -- default direction],[mhseq23 cur:n],[ | ||
280 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
281 | echo "cur: 3" > Mail/inbox/.mh_sequences | ||
282 | mhseq cur:2 | ||
283 | ], | ||
284 | [0], | ||
285 | [3 | ||
286 | 4 | ||
287 | ]) | ||
288 | |||
289 | MH_CHECK([mhseq: cur:n -- explicit dir (negative)],[mhseq24 cur:n cur:n-],[ | ||
290 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
291 | echo "cur: 3" > Mail/inbox/.mh_sequences | ||
292 | mhseq cur:-2 | ||
293 | ], | ||
294 | [0], | ||
295 | [2 | ||
296 | 3 | ||
297 | ]) | ||
298 | |||
299 | MH_CHECK([mhseq: cur:n -- explicit dir (positive)],[mhseq25 cur:n cur:n+],[ | ||
300 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
301 | echo "cur: 3" > Mail/inbox/.mh_sequences | ||
302 | mhseq cur:+2 | ||
303 | ], | ||
304 | [0], | ||
305 | [3 | ||
306 | 4 | ||
307 | ]) | ||
308 | |||
309 | MH_CHECK([mhseq: next],[mhseq26 next],[ | ||
310 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
311 | echo "cur: 3" > Mail/inbox/.mh_sequences | ||
312 | rm Mail/inbox/4 | ||
313 | mhseq next | ||
314 | ], | ||
315 | [0], | ||
316 | [5 | ||
317 | ]) | ||
318 | |||
319 | MH_CHECK([mhseq: next:n -- default direction],[mhseq27 next:n],[ | ||
320 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
321 | echo "cur: 3" > Mail/inbox/.mh_sequences | ||
322 | mhseq next:2 | ||
323 | ], | ||
324 | [0], | ||
325 | [4 | ||
326 | 5 | ||
327 | ]) | ||
328 | |||
329 | MH_CHECK([mhseq: prev],[mhseq28 prev],[ | ||
330 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
331 | echo "cur: 3" > Mail/inbox/.mh_sequences | ||
332 | rm Mail/inbox/2 | ||
333 | mhseq prev | ||
334 | ], | ||
335 | [0], | ||
336 | [1 | ||
337 | ]) | ||
338 | |||
339 | MH_CHECK([mhseq: prev:n -- default direction],[mhseq29 prev:n],[ | ||
340 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
341 | echo "cur: 3" > Mail/inbox/.mh_sequences | ||
342 | mhseq prev:2 | ||
343 | ], | ||
344 | [0], | ||
345 | [1 | ||
346 | 2 | ||
347 | ]) | ||
348 | |||
349 | MH_CHECK([mhseq: first],[mhseq30 first],[ | ||
350 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
351 | rm Mail/inbox/1 | ||
352 | mhseq first | ||
353 | ], | ||
354 | [0], | ||
355 | [2 | ||
356 | ]) | ||
357 | |||
358 | MH_CHECK([mhseq: first:n -- default direction],[mhseq31 first:n],[ | ||
359 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
360 | rm Mail/inbox/1 | ||
361 | mhseq first:2 | ||
362 | ], | ||
363 | [0], | ||
364 | [2 | ||
365 | 3 | ||
366 | ]) | ||
367 | |||
368 | MH_CHECK([mhseq: last],[mhseq32 last],[ | ||
369 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
370 | mhseq last | ||
371 | ], | ||
372 | [0], | ||
373 | [5 | ||
374 | ]) | ||
375 | |||
376 | MH_CHECK([mhseq: last:n -- default direction],[mhseq33 last:n],[ | ||
377 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/mbox1,[Mail/inbox]) | ||
378 | mhseq last:2 | ||
379 | ], | ||
380 | [0], | ||
381 | [4 | ||
382 | 5 | ||
383 | ]) | ||
384 | |||
385 | m4_popdef([MH_KEYWORDS]) | ||
386 | # End of mhseq.at | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
... | @@ -42,6 +42,7 @@ AT_CLEANUP | ... | @@ -42,6 +42,7 @@ AT_CLEANUP |
42 | AT_INIT | 42 | AT_INIT |
43 | 43 | ||
44 | m4_include([install-mh.at]) | 44 | m4_include([install-mh.at]) |
45 | m4_include([mhseq.at]) | ||
45 | m4_include([ali.at]) | 46 | m4_include([ali.at]) |
46 | m4_include([folder.at]) | 47 | m4_include([folder.at]) |
47 | m4_include([inc.at]) | 48 | m4_include([inc.at]) |
... | @@ -56,3 +57,4 @@ m4_include([mhl.at]) | ... | @@ -56,3 +57,4 @@ m4_include([mhl.at]) |
56 | m4_include([anno.at]) | 57 | m4_include([anno.at]) |
57 | m4_include([pick.at]) | 58 | m4_include([pick.at]) |
58 | m4_include([burst.at]) | 59 | m4_include([burst.at]) |
60 | m4_include([comp.at]) | ... | ... |
-
Please register or sign in to post a comment