/[mailutils]/mailutils/mh/pick.c
ViewVC logotype

Diff of /mailutils/mh/pick.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1 by gray, Fri Feb 14 16:10:10 2003 UTC revision 1.2 by gray, Sun Feb 16 11:26:55 2003 UTC
# Line 19  Line 19 
19    
20  #include <mh.h>  #include <mh.h>
21  #include <regex.h>  #include <regex.h>
22    #include <pick.h>
23    #include <pick-gram.h>
24    #define obstack_chunk_alloc malloc
25    #define obstack_chunk_free free
26    #include <obstack.h>
27    
28  const char *argp_program_version = "pick (" PACKAGE_STRING ")";  const char *argp_program_version = "pick (" PACKAGE_STRING ")";
29  static char doc[] = N_("GNU MH pick\v"  static char doc[] = N_("GNU MH pick\v"
# Line 37  static struct argp_option options[] = { Line 42  static struct argp_option options[] = {
42    {"pattern", ARG_PATTERN, N_("STRING"), 0,    {"pattern", ARG_PATTERN, N_("STRING"), 0,
43     N_("A pattern to look for"), 1},     N_("A pattern to look for"), 1},
44    {"search",  0, NULL, OPTION_ALIAS, NULL, 1},    {"search",  0, NULL, OPTION_ALIAS, NULL, 1},
45      {"cflags",  ARG_CFLAGS,  N_("STRING"), 0,
46       N_("Flags controlling the type of regular expressions. STRING must consist of one or more of the following letters: B=basic, E=extended, I=ignore case, C=case sensitive. Default is \"EI\". The flags remain in effect until the next occurrence of --cflags option. The option must occur right before --pattern or --component option (or its alias).") },
47    {"cc",      ARG_CC,      N_("STRING"), 0,    {"cc",      ARG_CC,      N_("STRING"), 0,
48     N_("Same as --component cc --pattern STRING"), 1},     N_("Same as --component cc --pattern STRING"), 1},
49    {"date",    ARG_DATE,    N_("STRING"), 0,    {"date",    ARG_DATE,    N_("STRING"), 0,
# Line 50  static struct argp_option options[] = { Line 57  static struct argp_option options[] = {
57    
58    {N_("Date constraint operations:"), 0,  NULL, OPTION_DOC, NULL, 1},    {N_("Date constraint operations:"), 0,  NULL, OPTION_DOC, NULL, 1},
59    {"datefield",ARG_DATEFIELD, N_("STRING"), 0,    {"datefield",ARG_DATEFIELD, N_("STRING"), 0,
60     N_("Search in the named date header field (default is `Date:')"), 2},     N_("* Search in the named date header field (default is `Date:')"), 2},
61    {"after",    ARG_AFTER,     N_("DATE"), 0,    {"after",    ARG_AFTER,     N_("DATE"), 0,
62     N_("Match messages after the given date"), 2},     N_("* Match messages after the given date"), 2},
63    {"before",   ARG_BEFORE,    N_("DATE"), 0,    {"before",   ARG_BEFORE,    N_("DATE"), 0,
64     N_("Match messages before the given date"), 2},     N_("* Match messages before the given date"), 2},
65    
66    {N_("Logical operations and grouping:"), 0, NULL, OPTION_DOC, NULL, 2},    {N_("Logical operations and grouping:"), 0, NULL, OPTION_DOC, NULL, 2},
67    {"and",     ARG_AND,    NULL, 0,    {"and",     ARG_AND,    NULL, 0,
# Line 111  struct mh_option mh_option[] = { Line 118  struct mh_option mh_option[] = {
118    {NULL}    {NULL}
119  };  };
120    
121  static int list;  static int list = 1;
122  static int mode_public = 1;  static int seq_flags = 0; /* Create public sequences;
123  static int mode_zero = 0;                               Do not zero the sequence before addition */
124    static list_t seq_list;  /* List of sequence names to operate upon */
125    
126    static list_t lexlist;   /* List of input tokens */
127    
128    static struct obstack msgno_stk; /* Stack of selected message numbers */
129    static size_t msgno_count;       /* Number of items on the stack */
130    
131    static void
132    add_sequence (char *name)
133    {
134      if (!seq_list && list_create (&seq_list))
135        {
136          mh_error (_("can't create sequence list"));
137          exit (1);
138        }
139      list_append (seq_list, name);
140    }
141    
142  static int  static int
143  opt_handler (int key, char *arg, void *unused)  opt_handler (int key, char *arg, void *unused, struct argp_state *state)
144  {  {
145      char *s, *p;
146      
147    switch (key)    switch (key)
148      {      {
149      case '+':      case '+':
# Line 126  opt_handler (int key, char *arg, void *u Line 152  opt_handler (int key, char *arg, void *u
152        break;        break;
153    
154      case ARG_SEQUENCE:      case ARG_SEQUENCE:
155        /*  add_sequence (arg); */        add_sequence (arg);
156          list = 0;
157        break;        break;
158    
159      case ARG_LIST:      case ARG_LIST:
# Line 137  opt_handler (int key, char *arg, void *u Line 164  opt_handler (int key, char *arg, void *u
164        list = 0;        list = 0;
165        break;        break;
166    
167      case ARG_COMPONENT:            case ARG_COMPONENT:
168      case ARG_PATTERN:                pick_add_token (&lexlist, T_COMP, arg);
169      case ARG_CC:                      break;
170          
171        case ARG_PATTERN:
172          pick_add_token (&lexlist, T_STRING, arg);
173          break;
174          
175        case ARG_CC:
176          pick_add_token (&lexlist, T_COMP, "cc");
177          pick_add_token (&lexlist, T_STRING, arg);
178          break;
179          
180      case ARG_DATE:                case ARG_DATE:          
181          pick_add_token (&lexlist, T_COMP, "date");
182          pick_add_token (&lexlist, T_STRING, arg);
183          break;
184          
185      case ARG_FROM:                case ARG_FROM:          
186          pick_add_token (&lexlist, T_COMP, "from");
187          pick_add_token (&lexlist, T_STRING, arg);
188          break;
189          
190      case ARG_SUBJECT:              case ARG_SUBJECT:        
191      case ARG_TO:                    pick_add_token (&lexlist, T_COMP, "subject");
192          pick_add_token (&lexlist, T_STRING, arg);
193          break;
194          
195        case ARG_TO:
196          pick_add_token (&lexlist, T_COMP, "to");
197          pick_add_token (&lexlist, T_STRING, arg);
198          break;
199          
200      case ARG_DATEFIELD:      case ARG_DATEFIELD:
201          pick_add_token (&lexlist, T_DATEFIELD, arg);
202          break;
203          
204      case ARG_AFTER:      case ARG_AFTER:
205          pick_add_token (&lexlist, T_AFTER, NULL);
206          pick_add_token (&lexlist, T_STRING, arg);
207          break;
208          
209      case ARG_BEFORE:      case ARG_BEFORE:
210          pick_add_token (&lexlist, T_BEFORE, NULL);
211          pick_add_token (&lexlist, T_STRING, arg);
212          break;
213            
214      case ARG_AND:      case ARG_AND:
215          pick_add_token (&lexlist, T_AND, NULL);
216          break;
217          
218      case ARG_OR:      case ARG_OR:
219          pick_add_token (&lexlist, T_OR, NULL);
220          break;
221          
222      case ARG_NOT:      case ARG_NOT:
223          pick_add_token (&lexlist, T_NOT, NULL);
224          break;
225    
226      case ARG_LBRACE:      case ARG_LBRACE:
227          pick_add_token (&lexlist, T_LBRACE, NULL);
228          break;
229          
230      case ARG_RBRACE:      case ARG_RBRACE:
231          pick_add_token (&lexlist, T_RBRACE, NULL);
232          break;
233    
234        case ARG_CFLAGS:
235          pick_add_token (&lexlist, T_CFLAGS, arg);
236        break;        break;
237                
238      case ARG_PUBLIC:      case ARG_PUBLIC:
239        mode_public = is_true (arg);        if (is_true (arg))
240            seq_flags &= ~SEQ_PRIVATE;
241          else
242            seq_flags |= SEQ_PRIVATE;
243        break;        break;
244                
245      case ARG_NOPUBLIC:      case ARG_NOPUBLIC:
246        mode_public = 0;        seq_flags |= SEQ_PRIVATE;
247        break;        break;
248                
249      case ARG_ZERO:      case ARG_ZERO:
250        mode_zero = is_true (arg);        if (is_true (arg))
251            seq_flags |= SEQ_ZERO;
252          else
253            seq_flags &= ~SEQ_ZERO;
254        break;        break;
255    
256      case ARG_NOZERO:      case ARG_NOZERO:
257        mode_zero = 0;        seq_flags &= ~SEQ_ZERO;
258          break;
259            
260        case ARGP_KEY_ERROR:
261          s = state->argv[state->next - 1];
262          if (memcmp (s, "--", 2))
263            {
264              argp_error (state, _("invalid option -- %s"), s);
265              exit (1);
266            }
267          p = strchr (s, '=');
268          if (p)
269            *p++ = 0;
270            
271          pick_add_token (&lexlist, T_COMP, s + 2);
272    
273          if (!p)
274            {
275              if (state->next == state->argc)
276                {
277                  mh_error (_("invalid option -- %s"), s);
278                  exit (1);
279                }
280              p = state->argv[state->next++];
281            }
282          
283          pick_add_token (&lexlist, T_STRING, p);
284        break;        break;
285    
286      default:      default:
287        return 1;        return 1;
288      }      }
289    
290      return 0;
291    }
292    
293    void
294    pick_message (mailbox_t mbox, message_t msg, size_t num, void *data)
295    {
296      if (pick_eval (msg))
297        {
298          mh_message_number (msg, &num);
299          if (list)
300            printf ("%lu\n", (unsigned long) num);
301          if (seq_list)
302            {
303              obstack_grow (&msgno_stk, &num, sizeof (num));
304              msgno_count++;
305            }
306        }
307    }
308    
309    static int
310    action_add (void *item, void *data)
311    {
312      mh_seq_add ((char *)item, (mh_msgset_t *)data, seq_flags);
313    return 0;    return 0;
314  }  }
315    
316    /* NOTICE: For the compatibility with the RAND MH we have to support
317       the following command line syntax:
318    
319           --FIELD STRING
320    
321       where `FIELD' may be any string and which is equivalent to
322       `--field FIELD --pattern STRING'. Obviously this is in conflict
323       with the usual GNU long options paradigm which requires that any
324       unrecognized long option produce an error. Unfortunately, mh-pick.el
325       relies heavily on this syntax, so it can't be simply removed.
326       The approach taken here allows to properly recognize such syntax,
327       however it has an undesirable side effect: due to the specifics of
328       the underlying arpg library the --help and --usage options get
329       disabled. To make them work as well, the following approach is
330       taken: the mh-compatible syntax gets enabled only if the file
331       descriptor of stdin is not connected to a terminal, which is true
332       when invoked from mh-pick.el module. Otherwise, it is disabled
333       and the standard GNU long option syntax is in force. */
334  int  int
335  main (int argc, char **argv)  main (int argc, char **argv)
336  {  {
337      int status;
338    int index;    int index;
339      mailbox_t mbox;
340      mh_msgset_t msgset;
341      int flags;
342    
343      flags = isatty (0) ? 0 : ARGP_NO_ERRS;
344    mu_init_nls ();    mu_init_nls ();
345    mh_argp_parse (argc, argv, options, mh_option, args_doc, doc,    mh_argp_parse (argc, argv, flags, options, mh_option,
346                   opt_handler, NULL, &index);                   args_doc, doc, opt_handler, NULL, &index);
347      if (pick_parse (lexlist))
348        return 1;
349    
350      mbox = mh_open_folder (current_folder, 0);
351    
352      argc -= index;
353      argv += index;
354    
355      if (seq_list)
356        obstack_init (&msgno_stk);
357      
358      mh_msgset_parse (mbox, &msgset, argc, argv, "all");
359      status = mh_iterate (mbox, &msgset, pick_message, NULL);
360    
361      if (seq_list)
362        {
363          mh_msgset_t msgset;
364          msgset.count = msgno_count;
365          msgset.list = obstack_finish (&msgno_stk);
366          list_do (seq_list, action_add, (void*) &msgset);
367        }
368    
369      mh_global_save_state ();
370      return status;
371  }  }
372        

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26