* New upstream release.
[debian/mimetic.git] / examples / cmdline.cxx
1 #include <getopt.h>
2 #include <iostream>
3 #include "mm.h"
4 #include "cmdline.h"
5
6 using namespace std;
7
8 command_line::command_line()
9 {
10     for(int i = 0; i < p_last_item; ++i)
11         m_is_opt_set[i] = 0;
12 }
13
14 command_line::iterator command_line::begin(const string& key)
15 {
16     if(key.length())
17         return m_map.lower_bound(key);
18     else
19         return m_map.begin();
20 }
21
22 command_line::iterator command_line::end(const string& key)
23 {
24     if(key.length())
25         return m_map.upper_bound(key);
26     else
27         return m_map.end();
28 }
29
30 command_line::const_iterator command_line::begin(const string& key) const
31 {
32     if(key.length())
33         return m_map.lower_bound(key);
34     else
35         return m_map.begin();
36 }
37
38 command_line::const_iterator command_line::end(const string& key) const
39 {
40     if(key.length())
41         return m_map.upper_bound(key);
42     else
43         return m_map.end();
44 }
45
46
47
48 string& command_line::operator[](const string& key)
49 {
50     iterator it = m_map.find(key);
51     if(it == m_map.end())
52         it = m_map.insert(command_line_switch(key,""));
53     return it->second;
54 }
55
56 bool command_line::is_set(int i) const
57 {
58     return m_is_opt_set[i];
59 }
60
61 bool command_line::is_set(const string& switch_name) const
62 {
63     return m_map.find(switch_name) != m_map.end();
64 }
65
66 void command_line::die_if_not_valid() const
67 {
68     die_if(is_set(p_match_shell) && is_set(p_match_regex),
69         "just one of --match-shell and --match-regex can be specified");
70     die_if(is_set(p_match_shell) && is_set(p_perl_regex),
71         "--match-shell and --perl-regex are not compatible");
72     die_if(is_set(p_print_msg) && is_set(p_print_part),
73         "just one of --print-message and --print-part can be specified");
74     die_if(is_set(p_delete_msg) && is_set(p_delete_part),
75         "just one of --delete-msg and --delete-part can be specified");
76 }
77
78 void command_line::add_switch(const string& name, const string& arg)
79 {
80     m_map.insert(command_line_switch(name,arg));
81 }
82
83 bool command_line::parse_cmd_line(int argc, char **argv)
84 {
85     #define CMDLINE_ARG( name, desc, arg ) { name "\000" desc, arg, 0, 0 }
86     #define CMDLINE_ARG_VAL( name, desc, arg, val ) { name "\000" desc, arg, 0, val }
87     enum { NO_ARG, REQ_ARG, OPT_ARG };
88     int opt_idx = 0;
89     static struct option long_options[] = {
90     // "name", has-arg, flag, val
91         CMDLINE_ARG_VAL("attachment-filename",
92             "filename of the attachment", 
93         REQ_ARG, p_attachment_filename),
94         CMDLINE_ARG_VAL("has-binary-attach", 
95             "match if the message has attachments", 
96         NO_ARG,p_has_binary_attach), 
97         CMDLINE_ARG_VAL("has-field","",OPT_ARG,p_has_field), 
98         CMDLINE_ARG_VAL("field", "",OPT_ARG,p_field), 
99         CMDLINE_ARG_VAL("ifield","",OPT_ARG,p_ifield), 
100         CMDLINE_ARG_VAL("from", "",OPT_ARG,    p_std_field), 
101         CMDLINE_ARG_VAL("sender", "", OPT_ARG,p_std_field), 
102         CMDLINE_ARG_VAL("to", "", OPT_ARG,p_std_field), 
103         CMDLINE_ARG_VAL("subject", "", OPT_ARG,p_std_field), 
104         CMDLINE_ARG_VAL("cc", "", OPT_ARG,p_std_field), 
105         CMDLINE_ARG_VAL("bcc", "", OPT_ARG,p_std_field), 
106         CMDLINE_ARG_VAL("user-agent", "", OPT_ARG,p_std_field), 
107         CMDLINE_ARG_VAL("date", "", OPT_ARG,p_std_field), 
108         CMDLINE_ARG_VAL("content-type", "", OPT_ARG,p_std_field), 
109         CMDLINE_ARG_VAL("content-transfer-encoding","",OPT_ARG,p_std_field),
110         CMDLINE_ARG_VAL("content-disposition", "", OPT_ARG,p_std_field), 
111         CMDLINE_ARG_VAL("content-description", "", OPT_ARG,p_std_field), 
112
113         CMDLINE_ARG_VAL("add-header", "", REQ_ARG, p_add_header), 
114         CMDLINE_ARG_VAL("del-header", "", REQ_ARG, p_del_header), 
115         CMDLINE_ARG_VAL("mod-header", "", REQ_ARG, p_mod_header), 
116         CMDLINE_ARG_VAL("add-part-header", "", REQ_ARG, p_add_part_header), 
117         CMDLINE_ARG_VAL("del-part-header", "", REQ_ARG, p_del_part_header), 
118         CMDLINE_ARG_VAL("mod-part-header", "", REQ_ARG, p_mod_part_header), 
119         CMDLINE_ARG_VAL("attach", "", REQ_ARG, p_attach), 
120         CMDLINE_ARG_VAL("detach", "", NO_ARG, p_detach), 
121         CMDLINE_ARG_VAL("delete-part", "", NO_ARG, p_delete_part), 
122         CMDLINE_ARG_VAL("delete-message", "", NO_ARG, p_delete_msg), 
123         CMDLINE_ARG_VAL("print-part", "", NO_ARG,p_print_part), 
124         CMDLINE_ARG_VAL("print-message", "", NO_ARG,p_print_msg), 
125         CMDLINE_ARG_VAL("pipe-to", "", REQ_ARG, p_pipe_to), 
126
127         CMDLINE_ARG_VAL("recursive", "", NO_ARG, p_recursive), 
128         CMDLINE_ARG_VAL("invert-selection", "", NO_ARG, p_invert_selection), 
129         CMDLINE_ARG_VAL("match-shell", "", NO_ARG, p_match_shell), 
130         CMDLINE_ARG_VAL("match-regex", "", NO_ARG, p_match_regex), 
131         CMDLINE_ARG_VAL("perl-regex", "", NO_ARG, p_perl_regex), 
132         CMDLINE_ARG_VAL("case-insensitive", "", NO_ARG, p_case_insensitive), 
133         CMDLINE_ARG_VAL("encoding", "", REQ_ARG, p_encoding), 
134         CMDLINE_ARG_VAL("in", "", REQ_ARG, p_in), 
135         CMDLINE_ARG_VAL("out", "", REQ_ARG, p_out), 
136         CMDLINE_ARG_VAL("help", "", NO_ARG, p_help), 
137         CMDLINE_ARG_VAL("version", "", NO_ARG, p_version), 
138         {0, 0, 0, 0}
139     };
140
141
142     int ret;
143     while((ret = getopt_long(argc,argv, "hv", long_options, &opt_idx))!= -1)
144     {
145         switch(ret)
146         {
147         case ':':
148             die("missing parameter");
149         case '?':
150             die("unknown option");
151         case 'v':
152             cerr << MM_VERSION << endl;
153             exit(1);
154             break;
155         case 'h':
156             //usage_if(1);
157             for(int i = 0; long_options[i].name; ++i)
158             {
159                 const char *name= long_options[i].name;
160                 cerr << "--" << name;
161                 switch(long_options[i].has_arg)
162                 {
163                 case NO_ARG:
164                     break;
165                 case REQ_ARG:
166                     cerr << " ARG";
167                     break;
168                 case OPT_ARG:
169                     cerr << " [ARG]";
170                     break;
171                 default:
172                     die("unknown has_arg");
173                 }
174                 // past the end of name
175                 const char *desc = 1 + name + strlen(name);
176                 cerr << "\t" << desc << endl;
177             }
178             exit(0);
179             break;
180         default:
181             m_is_opt_set[ret]++;
182             for(int i = 0; long_options[i].name; ++i)
183             {
184                 struct option *opt = &long_options[i];
185                 if(ret == opt->val)
186                 {
187                     if(opt->has_arg == NO_ARG || !optarg)
188                         add_switch(opt->name,""); 
189                     else 
190                         add_switch(opt->name, optarg); 
191                 }
192             }
193         }
194     }
195     /*
196     switch(argc - optind)
197     {
198     case 0:
199         // read from stdin write to stdout
200         break;
201     case 1:
202         //stdin provided in argv[optind]
203         pCl->args.push_back(argv[optind]);
204         break;
205     case 2:
206         //stdin & stdout provided in argv[optind] && argv[++optind]
207         pCl->args.push_back(argv[optind]);
208         pCl->args.push_back(argv[++optind]);
209         break;
210     default:
211         usage();
212     }
213     cerr << endl;
214     */
215     return true;
216 }