Add generic library for option parsing.
* configure.ac: Build libmailutils/opt * include/mailutils/Makefile.am: Add opt.h * include/mailutils/opt.h: New file. * include/mailutils/util.h (mu_c_type_t): New datatype. (mu_str_to_c): New proto. * libmailutils/Makefile.am: Add opt to subdirs. * libmailutils/opt/Makefile.am: New file. * libmailutils/opt/help.c: New file. * libmailutils/opt/opt.c: New file. * libmailutils/opt/progname.c: New file. * libmailutils/string/Makefile.am: Add new files. * libmailutils/string/str_to_c.c: New file. * libmailutils/string/to_sn.c: New file. * libmailutils/string/to_un.c: New file. * libmailutils/tests/.gitignore: Update. * libmailutils/tests/Makefile.am: Update. * libmailutils/tests/parseopt.c: New file.
Showing
16 changed files
with
1059 additions
and
3 deletions
... | @@ -1519,6 +1519,7 @@ AC_CONFIG_FILES([ | ... | @@ -1519,6 +1519,7 @@ AC_CONFIG_FILES([ |
1519 | libmailutils/mailer/Makefile | 1519 | libmailutils/mailer/Makefile |
1520 | libmailutils/mime/Makefile | 1520 | libmailutils/mime/Makefile |
1521 | libmailutils/msgset/Makefile | 1521 | libmailutils/msgset/Makefile |
1522 | libmailutils/opt/Makefile | ||
1522 | libmailutils/property/Makefile | 1523 | libmailutils/property/Makefile |
1523 | libmailutils/server/Makefile | 1524 | libmailutils/server/Makefile |
1524 | libmailutils/string/Makefile | 1525 | libmailutils/string/Makefile | ... | ... |
include/mailutils/opt.h
0 → 100644
1 | /* opt.h -- general-purpose command line option parser | ||
2 | Copyright (C) 2016 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 | |||
18 | #ifndef _MAILUTILS_OPT_H | ||
19 | #define _MAILUTILS_OPT_H | ||
20 | #include <stdio.h> | ||
21 | #include <mailutils/types.h> | ||
22 | #include <mailutils/list.h> | ||
23 | #include <mailutils/util.h> | ||
24 | #include <mailutils/cctype.h> | ||
25 | |||
26 | extern char *mu_progname; | ||
27 | extern char *mu_absprogname; | ||
28 | |||
29 | void mu_set_progname (char const *arg); | ||
30 | |||
31 | #define MU_OPTION_DEFAULT 0 | ||
32 | #define MU_OPTION_ARG_OPTIONAL 0x01 | ||
33 | #define MU_OPTION_HIDDEN 0x02 | ||
34 | #define MU_OPTION_ALIAS 0x04 | ||
35 | #define MU_OPTION_IMMEDIATE 0x08 | ||
36 | |||
37 | struct mu_parseopt; | ||
38 | |||
39 | struct mu_option | ||
40 | { | ||
41 | char *opt_long; /* Long option name */ | ||
42 | int opt_short; /* Short option character */ | ||
43 | char *opt_arg; /* Argument name */ | ||
44 | int opt_flags; /* Flags (see above) */ | ||
45 | char *opt_doc; /* Human-readable documentation */ | ||
46 | mu_c_type_t opt_type; /* Option type */ | ||
47 | void *opt_ptr; /* Data pointer */ | ||
48 | void (*opt_set) (struct mu_parseopt *, struct mu_option *, char const *); | ||
49 | /* Function to set the option */ | ||
50 | }; | ||
51 | |||
52 | #define MU_OPTION_GROUP(text) { NULL, 0, NULL, 0, text } | ||
53 | #define MU_OPTION_END { NULL, 0, NULL, 0, NULL } | ||
54 | |||
55 | #define MU_OPTION_IS_END(opt) \ | ||
56 | (!(opt)->opt_long && !(opt)->opt_short && !(opt)->opt_doc) | ||
57 | |||
58 | #define MU_OPTION_IS_OPTION(opt) \ | ||
59 | ((opt)->opt_short || (opt)->opt_long) | ||
60 | #define MU_OPTION_IS_GROUP_HEADER(opt) \ | ||
61 | (!MU_OPTION_IS_OPTION(opt) && (opt)->opt_doc) | ||
62 | #define MU_OPTION_IS_VALID_SHORT_OPTION(opt) \ | ||
63 | ((opt)->opt_short > 0 && (opt)->opt_short < 127 && \ | ||
64 | mu_isalnum ((opt)->opt_short)) | ||
65 | #define MU_OPTION_IS_VALID_LONG_OPTION(opt) \ | ||
66 | ((opt)->opt_long != NULL) | ||
67 | |||
68 | typedef struct mu_option_cache *mu_option_cache_ptr_t; | ||
69 | |||
70 | struct mu_option_cache | ||
71 | { | ||
72 | struct mu_option *cache_opt; | ||
73 | char *cache_arg; | ||
74 | }; | ||
75 | |||
76 | #define MU_PARSEOPT_DEFAULT 0 | ||
77 | /* Don't ignore the first element of ARGV. By default it is the program | ||
78 | name */ | ||
79 | #define MU_PARSEOPT_ARGV0 0x00000001 | ||
80 | /* Ignore command line errors. */ | ||
81 | #define MU_PARSEOPT_IGNORE_ERRORS 0x00000002 | ||
82 | /* Don't order arguments so that options come first. */ | ||
83 | #define MU_PARSEOPT_IN_ORDER 0x00000004 | ||
84 | /* Don't provide standard options: -h, --help, --usage, --version */ | ||
85 | #define MU_PARSEOPT_NO_STDOPT 0x00000008 | ||
86 | /* Don't exit on errors */ | ||
87 | #define MU_PARSEOPT_NO_ERREXIT 0x00000010 | ||
88 | /* Apply all options immediately */ | ||
89 | #define MU_PARSEOPT_IMMEDIATE 0x00000020 | ||
90 | |||
91 | /* Don't sort options */ | ||
92 | #define MU_PARSEOPT_NO_SORT 0x00001000 | ||
93 | |||
94 | #define MU_PARSEOPT_PROG_NAME 0x00002000 | ||
95 | #define MU_PARSEOPT_PROG_DOC 0x00004000 | ||
96 | #define MU_PARSEOPT_PROG_ARGS 0x00008000 | ||
97 | #define MU_PARSEOPT_BUG_ADDRESS 0x00010000 | ||
98 | #define MU_PARSEOPT_PACKAGE_NAME 0x00020000 | ||
99 | #define MU_PARSEOPT_PACKAGE_URL 0x00040000 | ||
100 | #define MU_PARSEOPT_DATA 0x00080000 | ||
101 | #define MU_PARSEOPT_HELP_HOOK 0x00100000 | ||
102 | |||
103 | /* Reuse mu_parseopt struct initialized previously */ | ||
104 | #define MU_PARSEOPT_REUSE 0x80000000 | ||
105 | /* Mask for immutable flag bits */ | ||
106 | #define MU_PARSEOPT_IMMUTABLE_MASK 0xFFFFF000 | ||
107 | |||
108 | |||
109 | struct mu_parseopt | ||
110 | { | ||
111 | /* Input data: */ | ||
112 | int po_argc; /* Number of argiments */ | ||
113 | char **po_argv; /* Array of arguments */ | ||
114 | size_t po_optc; /* Number of elements in optv */ | ||
115 | struct mu_option **po_optv; /* Array of ptrs to option structures */ | ||
116 | int po_flags; | ||
117 | |||
118 | char *po_data; /* Call-specific data */ | ||
119 | |||
120 | /* Informational: */ | ||
121 | char const *po_prog_name; | ||
122 | char const *po_prog_doc; | ||
123 | char const *po_prog_args; | ||
124 | char const *po_bug_address; | ||
125 | char const *po_package_name; | ||
126 | char const *po_package_url; | ||
127 | |||
128 | void (*po_help_hook) (FILE *stream); /* FIXME: should take mu_Stream_t ?*/ | ||
129 | |||
130 | /* Output data */ | ||
131 | int po_ind; /* Index of the next option */ | ||
132 | int po_opterr; /* Index of the element in po_argv that | ||
133 | caused last error, or -1 if no errors */ | ||
134 | mu_list_t po_optlist; | ||
135 | |||
136 | /* Auxiliary data */ | ||
137 | char *po_cur; /* Points to the next character */ | ||
138 | int po_chr; /* Single-char option */ | ||
139 | |||
140 | /* The following two keep the position of the first non-optional argument | ||
141 | and the number of contiguous non-optional arguments after it. | ||
142 | Obviously, the following holds true: | ||
143 | |||
144 | arg_start + arg_count == opt_ind | ||
145 | |||
146 | If permutation is not allowed (MU_OPTION_PARSE_IN_ORDER flag is set), | ||
147 | arg_count is always 0. | ||
148 | */ | ||
149 | int po_arg_start; | ||
150 | int po_arg_count; | ||
151 | |||
152 | }; | ||
153 | |||
154 | int mu_parseopt (struct mu_parseopt *p, | ||
155 | int argc, char **argv, struct mu_option **optv, | ||
156 | int flags); | ||
157 | |||
158 | int mu_parseopt_apply (struct mu_parseopt *p); | ||
159 | void mu_parseopt_free (struct mu_parseopt *p); | ||
160 | |||
161 | void mu_option_describe_options (struct mu_option **optbuf, size_t optcnt); | ||
162 | void mu_program_help (struct mu_parseopt *p); | ||
163 | void mu_program_usage (struct mu_parseopt *p); | ||
164 | |||
165 | void mu_option_set_value (struct mu_parseopt *po, struct mu_option *opt, | ||
166 | char const *arg); | ||
167 | |||
168 | #endif |
... | @@ -152,6 +152,35 @@ int mu_getpass (mu_stream_t in, mu_stream_t out, const char *prompt, | ... | @@ -152,6 +152,35 @@ int mu_getpass (mu_stream_t in, mu_stream_t out, const char *prompt, |
152 | char **passptr); | 152 | char **passptr); |
153 | 153 | ||
154 | /* ----------------------- */ | 154 | /* ----------------------- */ |
155 | /* String conversions. */ | ||
156 | /* ----------------------- */ | ||
157 | |||
158 | enum mu_c_type | ||
159 | { | ||
160 | mu_c_string, | ||
161 | mu_c_short, | ||
162 | mu_c_ushort, | ||
163 | mu_c_int, | ||
164 | mu_c_uint, | ||
165 | mu_c_long, | ||
166 | mu_c_ulong, | ||
167 | mu_c_size, | ||
168 | mu_c_off, | ||
169 | mu_c_time, | ||
170 | mu_c_bool, | ||
171 | mu_c_ipv4, | ||
172 | mu_c_cidr, | ||
173 | mu_c_host, | ||
174 | mu_c_incr, /* C int value, incremented each time mu_str_to_c is | ||
175 | invoked */ | ||
176 | }; | ||
177 | |||
178 | typedef enum mu_c_type mu_c_type_t; | ||
179 | |||
180 | int mu_str_to_c (char const *string, mu_c_type_t type, void *tgt, | ||
181 | char **errmsg); | ||
182 | |||
183 | /* ----------------------- */ | ||
155 | /* Assorted functions. */ | 184 | /* Assorted functions. */ |
156 | /* ----------------------- */ | 185 | /* ----------------------- */ |
157 | int mu_getmaxfd (void); | 186 | int mu_getmaxfd (void); |
... | @@ -208,7 +237,6 @@ int mu_file_safety_compose (int *res, const char *name, int defval); | ... | @@ -208,7 +237,6 @@ int mu_file_safety_compose (int *res, const char *name, int defval); |
208 | int mu_file_mode_to_safety_criteria (int mode); | 237 | int mu_file_mode_to_safety_criteria (int mode); |
209 | int mu_safety_criteria_to_file_mode (int crit); | 238 | int mu_safety_criteria_to_file_mode (int crit); |
210 | 239 | ||
211 | |||
212 | #ifdef __cplusplus | 240 | #ifdef __cplusplus |
213 | } | 241 | } |
214 | #endif | 242 | #endif | ... | ... |
... | @@ -18,7 +18,7 @@ | ... | @@ -18,7 +18,7 @@ |
18 | 18 | ||
19 | SUBDIRS = \ | 19 | SUBDIRS = \ |
20 | auth base address list sockaddr cidr cfg diag\ | 20 | auth base address list sockaddr cidr cfg diag\ |
21 | filter mailbox mailer mime msgset server string stream stdstream\ | 21 | filter mailbox mailer mime msgset opt server string stream stdstream\ |
22 | property url imapio datetime . tests | 22 | property url imapio datetime . tests |
23 | 23 | ||
24 | lib_LTLIBRARIES = libmailutils.la | 24 | lib_LTLIBRARIES = libmailutils.la |
... | @@ -42,6 +42,7 @@ libmailutils_la_LIBADD = \ | ... | @@ -42,6 +42,7 @@ libmailutils_la_LIBADD = \ |
42 | mailer/libmailer.la\ | 42 | mailer/libmailer.la\ |
43 | mime/libmime.la\ | 43 | mime/libmime.la\ |
44 | msgset/libmsgset.la\ | 44 | msgset/libmsgset.la\ |
45 | opt/libopt.la\ | ||
45 | property/libproperty.la\ | 46 | property/libproperty.la\ |
46 | server/libserver.la\ | 47 | server/libserver.la\ |
47 | string/libstring.la\ | 48 | string/libstring.la\ | ... | ... |
libmailutils/opt/Makefile.am
0 → 100644
1 | # GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | # Copyright (C) 2016 Free Software Foundation, Inc. | ||
3 | # | ||
4 | # This library is free software; you can redistribute it and/or | ||
5 | # modify it under the terms of the GNU Lesser General Public | ||
6 | # License as published by the Free Software Foundation; either | ||
7 | # version 3 of the License, or (at your option) any later version. | ||
8 | # | ||
9 | # This library 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 GNU | ||
12 | # Lesser General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU Lesser General | ||
15 | # Public License along with this library. If not, see | ||
16 | # <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | noinst_LTLIBRARIES = libopt.la | ||
19 | |||
20 | libopt_la_SOURCES = \ | ||
21 | opt.c\ | ||
22 | help.c\ | ||
23 | progname.c | ||
24 | |||
25 | AM_CPPFLAGS = \ | ||
26 | @MU_LIB_COMMON_INCLUDES@ -I/libmailutils |
libmailutils/opt/help.c
0 → 100644
1 | /* help.c -- general-purpose command line option parser | ||
2 | Copyright (C) 2016 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 | #ifdef HAVE_CONFIG_H | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | #include <stdlib.h> | ||
21 | #include <string.h> | ||
22 | #include <mailutils/alloc.h> | ||
23 | #include <mailutils/opt.h> | ||
24 | #include <mailutils/cctype.h> | ||
25 | #include <mailutils/nls.h> | ||
26 | |||
27 | #define LMARGIN 2 | ||
28 | #define DESCRCOLUMN 30 | ||
29 | #define RMARGIN 79 | ||
30 | #define GROUPCOLUMN 2 | ||
31 | #define USAGECOLUMN 13 | ||
32 | |||
33 | static void | ||
34 | indent (size_t start, size_t col) | ||
35 | { | ||
36 | for (; start < col; start++) | ||
37 | putchar (' '); | ||
38 | } | ||
39 | |||
40 | static void | ||
41 | print_option_descr (const char *descr, size_t lmargin, size_t rmargin) | ||
42 | { | ||
43 | while (*descr) | ||
44 | { | ||
45 | size_t s = 0; | ||
46 | size_t i; | ||
47 | size_t width = rmargin - lmargin; | ||
48 | |||
49 | for (i = 0; ; i++) | ||
50 | { | ||
51 | if (descr[i] == 0 || descr[i] == ' ' || descr[i] == '\t') | ||
52 | { | ||
53 | if (i > width) | ||
54 | break; | ||
55 | s = i; | ||
56 | if (descr[i] == 0) | ||
57 | break; | ||
58 | } | ||
59 | } | ||
60 | fwrite (descr, 1, s, stdout); | ||
61 | fputc ('\n', stdout); | ||
62 | descr += s; | ||
63 | if (*descr) | ||
64 | { | ||
65 | indent (0, lmargin); | ||
66 | descr++; | ||
67 | } | ||
68 | } | ||
69 | } | ||
70 | |||
71 | |||
72 | static size_t | ||
73 | print_option (struct mu_option **optbuf, size_t optcnt, size_t num, | ||
74 | int *argsused) | ||
75 | { | ||
76 | struct mu_option *opt = optbuf[num]; | ||
77 | size_t next, i; | ||
78 | int delim; | ||
79 | int w; | ||
80 | |||
81 | if (MU_OPTION_IS_GROUP_HEADER (opt)) | ||
82 | { | ||
83 | if (num) | ||
84 | putchar ('\n'); | ||
85 | indent (0, GROUPCOLUMN); | ||
86 | print_option_descr (gettext (opt->opt_doc), GROUPCOLUMN, RMARGIN); | ||
87 | putchar ('\n'); | ||
88 | return num + 1; | ||
89 | } | ||
90 | |||
91 | /* count aliases */ | ||
92 | for (next = num + 1; | ||
93 | next < optcnt && optbuf[next]->opt_flags & MU_OPTION_ALIAS; | ||
94 | next++); | ||
95 | |||
96 | if (opt->opt_flags & MU_OPTION_HIDDEN) | ||
97 | return next; | ||
98 | |||
99 | w = 0; | ||
100 | for (i = num; i < next; i++) | ||
101 | { | ||
102 | if (MU_OPTION_IS_VALID_SHORT_OPTION (optbuf[i])) | ||
103 | { | ||
104 | if (w == 0) | ||
105 | { | ||
106 | indent (0, LMARGIN); | ||
107 | w = LMARGIN; | ||
108 | } | ||
109 | else | ||
110 | w += printf (", "); | ||
111 | w += printf ("-%c", optbuf[i]->opt_short); | ||
112 | delim = ' '; | ||
113 | } | ||
114 | } | ||
115 | |||
116 | for (i = num; i < next; i++) | ||
117 | { | ||
118 | if (MU_OPTION_IS_VALID_LONG_OPTION (optbuf[i])) | ||
119 | { | ||
120 | if (w == 0) | ||
121 | { | ||
122 | indent (0, LMARGIN); | ||
123 | w = LMARGIN; | ||
124 | } | ||
125 | else | ||
126 | w += printf (", "); | ||
127 | w += printf ("--%s", optbuf[i]->opt_long); | ||
128 | delim = '='; | ||
129 | } | ||
130 | } | ||
131 | |||
132 | if (opt->opt_arg) | ||
133 | { | ||
134 | *argsused = 1; | ||
135 | w += printf ("%c%s", delim, gettext (opt->opt_arg)); | ||
136 | } | ||
137 | if (w >= DESCRCOLUMN) | ||
138 | { | ||
139 | putchar ('\n'); | ||
140 | w = 0; | ||
141 | } | ||
142 | indent (w, DESCRCOLUMN); | ||
143 | print_option_descr (gettext (opt->opt_doc), DESCRCOLUMN, RMARGIN); | ||
144 | |||
145 | return next; | ||
146 | } | ||
147 | |||
148 | void | ||
149 | mu_option_describe_options (struct mu_option **optbuf, size_t optcnt) | ||
150 | { | ||
151 | unsigned i; | ||
152 | int argsused = 0; | ||
153 | |||
154 | for (i = 0; i < optcnt; ) | ||
155 | i = print_option (optbuf, optcnt, i, &argsused); | ||
156 | putchar ('\n'); | ||
157 | |||
158 | if (argsused) | ||
159 | { | ||
160 | print_option_descr (_("Mandatory or optional arguments to long options are also mandatory or optional for any corresponding short options."), 0, RMARGIN); | ||
161 | putchar ('\n'); | ||
162 | } | ||
163 | } | ||
164 | |||
165 | void | ||
166 | mu_program_help (struct mu_parseopt *po) | ||
167 | { | ||
168 | printf ("%s", _("Usage:")); | ||
169 | if (po->po_prog_name) | ||
170 | printf (" %s", po->po_prog_name); | ||
171 | printf (" [%s]...", _("OPTION")); | ||
172 | if (po->po_prog_args) | ||
173 | printf (" %s", gettext (po->po_prog_args)); | ||
174 | putchar ('\n'); | ||
175 | |||
176 | if (po->po_prog_doc) | ||
177 | print_option_descr (gettext (po->po_prog_doc), 0, RMARGIN); | ||
178 | putchar ('\n'); | ||
179 | |||
180 | mu_option_describe_options (po->po_optv, po->po_optc); | ||
181 | |||
182 | if (po->po_help_hook) | ||
183 | po->po_help_hook (stdout); | ||
184 | |||
185 | if (po->po_bug_address) | ||
186 | /* TRANSLATORS: The placeholder indicates the bug-reporting address | ||
187 | for this package. Please add _another line_ saying | ||
188 | "Report translation bugs to <...>\n" with the address for translation | ||
189 | bugs (typically your translation team's web or email address). */ | ||
190 | printf (_("Report bugs to %s.\n"), po->po_bug_address); | ||
191 | |||
192 | if (po->po_package_name && po->po_package_url) | ||
193 | printf (_("%s home page: <%s>\n"), | ||
194 | po->po_package_name, po->po_package_url); | ||
195 | } | ||
196 | |||
197 | static struct mu_option **option_tab; | ||
198 | |||
199 | static int | ||
200 | cmpidx_short (const void *a, const void *b) | ||
201 | { | ||
202 | unsigned const *ai = (unsigned const *)a; | ||
203 | unsigned const *bi = (unsigned const *)b; | ||
204 | |||
205 | return option_tab[*ai]->opt_short - option_tab[*bi]->opt_short; | ||
206 | } | ||
207 | |||
208 | static int | ||
209 | cmpidx_long (const void *a, const void *b) | ||
210 | { | ||
211 | unsigned const *ai = (unsigned const *)a; | ||
212 | unsigned const *bi = (unsigned const *)b; | ||
213 | struct mu_option const *ap = option_tab[*ai]; | ||
214 | struct mu_option const *bp = option_tab[*bi]; | ||
215 | return strcmp (ap->opt_long, bp->opt_long); | ||
216 | } | ||
217 | |||
218 | void | ||
219 | mu_program_usage (struct mu_parseopt *po) | ||
220 | { | ||
221 | unsigned i; | ||
222 | unsigned n; | ||
223 | char buf[RMARGIN+1]; | ||
224 | unsigned *idxbuf; | ||
225 | unsigned nidx; | ||
226 | |||
227 | struct mu_option **optbuf = po->po_optv; | ||
228 | size_t optcnt = po->po_optc; | ||
229 | |||
230 | #define FLUSH \ | ||
231 | do \ | ||
232 | { \ | ||
233 | buf[n] = 0; \ | ||
234 | printf ("%s\n", buf); \ | ||
235 | n = USAGECOLUMN; \ | ||
236 | memset (buf, ' ', n); \ | ||
237 | } \ | ||
238 | while (0) | ||
239 | #define ADDC(c) \ | ||
240 | do \ | ||
241 | { \ | ||
242 | if (n == RMARGIN) FLUSH; \ | ||
243 | buf[n++] = c; \ | ||
244 | } \ | ||
245 | while (0) | ||
246 | |||
247 | option_tab = optbuf; | ||
248 | |||
249 | idxbuf = mu_calloc (optcnt, sizeof (idxbuf[0])); | ||
250 | |||
251 | n = snprintf (buf, sizeof buf, "%s %s ", _("Usage:"), mu_progname); | ||
252 | |||
253 | /* Print a list of short options without arguments. */ | ||
254 | for (i = nidx = 0; i < optcnt; i++) | ||
255 | if (MU_OPTION_IS_VALID_SHORT_OPTION (optbuf[i]) && !optbuf[i]->opt_arg) | ||
256 | idxbuf[nidx++] = i; | ||
257 | |||
258 | if (nidx) | ||
259 | { | ||
260 | qsort (idxbuf, nidx, sizeof (idxbuf[0]), cmpidx_short); | ||
261 | |||
262 | ADDC ('['); | ||
263 | ADDC ('-'); | ||
264 | for (i = 0; i < nidx; i++) | ||
265 | { | ||
266 | ADDC (optbuf[idxbuf[i]]->opt_short); | ||
267 | } | ||
268 | ADDC (']'); | ||
269 | } | ||
270 | |||
271 | /* Print a list of short options with arguments. */ | ||
272 | for (i = nidx = 0; i < optcnt; i++) | ||
273 | { | ||
274 | if (MU_OPTION_IS_VALID_SHORT_OPTION (optbuf[i]) && optbuf[i]->opt_arg) | ||
275 | idxbuf[nidx++] = i; | ||
276 | } | ||
277 | |||
278 | if (nidx) | ||
279 | { | ||
280 | qsort (idxbuf, nidx, sizeof (idxbuf[0]), cmpidx_short); | ||
281 | |||
282 | for (i = 0; i < nidx; i++) | ||
283 | { | ||
284 | struct mu_option *opt = optbuf[idxbuf[i]]; | ||
285 | const char *arg = gettext (opt->opt_arg); | ||
286 | size_t len = 5 + strlen (arg) + 1; | ||
287 | |||
288 | if (n + len > RMARGIN) FLUSH; | ||
289 | buf[n++] = ' '; | ||
290 | buf[n++] = '['; | ||
291 | buf[n++] = '-'; | ||
292 | buf[n++] = opt->opt_short; | ||
293 | buf[n++] = ' '; | ||
294 | strcpy (&buf[n], arg); | ||
295 | n += strlen (arg); | ||
296 | buf[n++] = ']'; | ||
297 | } | ||
298 | } | ||
299 | |||
300 | /* Print a list of long options */ | ||
301 | for (i = nidx = 0; i < optcnt; i++) | ||
302 | { | ||
303 | if (MU_OPTION_IS_VALID_LONG_OPTION (optbuf[i])) | ||
304 | idxbuf[nidx++] = i; | ||
305 | } | ||
306 | |||
307 | if (nidx) | ||
308 | { | ||
309 | qsort (idxbuf, nidx, sizeof (idxbuf[0]), cmpidx_long); | ||
310 | |||
311 | for (i = 0; i < nidx; i++) | ||
312 | { | ||
313 | struct mu_option *opt = optbuf[idxbuf[i]]; | ||
314 | const char *arg = opt->opt_arg ? gettext (opt->opt_arg) : NULL; | ||
315 | size_t len = 3 + strlen (opt->opt_long) | ||
316 | + (arg ? 1 + strlen (arg) : 0); | ||
317 | if (n + len > RMARGIN) FLUSH; | ||
318 | buf[n++] = ' '; | ||
319 | buf[n++] = '['; | ||
320 | buf[n++] = '-'; | ||
321 | buf[n++] = '-'; | ||
322 | strcpy (&buf[n], opt->opt_long); | ||
323 | n += strlen (opt->opt_long); | ||
324 | if (opt->opt_arg) | ||
325 | { | ||
326 | buf[n++] = '='; | ||
327 | strcpy (&buf[n], arg); | ||
328 | n += strlen (arg); | ||
329 | } | ||
330 | buf[n++] = ']'; | ||
331 | } | ||
332 | } | ||
333 | |||
334 | FLUSH; | ||
335 | free (idxbuf); | ||
336 | } | ||
337 |
libmailutils/opt/opt.c
0 → 100644
This diff is collapsed.
Click to expand it.
libmailutils/opt/progname.c
0 → 100644
1 | /* help.c -- general-purpose command line option parser | ||
2 | Copyright (C) 2016 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 | #ifdef HAVE_CONFIG_H | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | #include <stdlib.h> | ||
21 | #include <string.h> | ||
22 | #include <mailutils/alloc.h> | ||
23 | #include <mailutils/opt.h> | ||
24 | |||
25 | char *mu_progname; | ||
26 | char *mu_absprogname; | ||
27 | |||
28 | void | ||
29 | mu_set_progname (char const *arg) | ||
30 | { | ||
31 | char *p; | ||
32 | |||
33 | free (mu_absprogname); | ||
34 | mu_absprogname = mu_strdup (arg); | ||
35 | |||
36 | p = strrchr (arg, '/'); | ||
37 | if (p) | ||
38 | ++p; | ||
39 | else | ||
40 | p = (char*) arg; | ||
41 | free (mu_progname); | ||
42 | mu_progname = mu_strdup (p); | ||
43 | } |
... | @@ -25,6 +25,7 @@ libstring_la_SOURCES = \ | ... | @@ -25,6 +25,7 @@ libstring_la_SOURCES = \ |
25 | cstrupper.c\ | 25 | cstrupper.c\ |
26 | hexstr.c\ | 26 | hexstr.c\ |
27 | stpcpy.c\ | 27 | stpcpy.c\ |
28 | str_to_c.c\ | ||
28 | strltrim.c\ | 29 | strltrim.c\ |
29 | strskip.c\ | 30 | strskip.c\ |
30 | stripws.c\ | 31 | stripws.c\ |
... | @@ -40,4 +41,6 @@ libstring_la_SOURCES = \ | ... | @@ -40,4 +41,6 @@ libstring_la_SOURCES = \ |
40 | wordsplit.c\ | 41 | wordsplit.c\ |
41 | xdecode.c | 42 | xdecode.c |
42 | 43 | ||
43 | AM_CPPFLAGS = @MU_LIB_COMMON_INCLUDES@ -I/libmailutils | 44 | EXTRA_DIST=to_sn.c to_un.c |
45 | |||
46 | AM_CPPFLAGS = @MU_LIB_COMMON_INCLUDES@ -I/libmailutils -I${srcdir} | ... | ... |
libmailutils/string/str_to_c.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2016 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | ||
7 | version 3 of the License, or (at your option) any later version. | ||
8 | |||
9 | This library 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 GNU | ||
12 | Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General | ||
15 | Public License along with this library. If not, see | ||
16 | <http://www.gnu.org/licenses/>. */ | ||
17 | |||
18 | #if HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | |||
22 | #include <stdlib.h> | ||
23 | #include <inttypes.h> | ||
24 | #include <limits.h> | ||
25 | #include <string.h> | ||
26 | #include <mailutils/cidr.h> | ||
27 | #include <mailutils/error.h> | ||
28 | #include <mailutils/errno.h> | ||
29 | #include <mailutils/util.h> | ||
30 | #include <mailutils/alloc.h> | ||
31 | #include <mailutils/cctype.h> | ||
32 | #include <mailutils/io.h> | ||
33 | #include <mailutils/nls.h> | ||
34 | |||
35 | typedef int (*str_to_c_t) (void *tgt, char const *string, char **errmsg); | ||
36 | |||
37 | static int | ||
38 | to_string (void *tgt, char const *string, char **errmsg) | ||
39 | { | ||
40 | char **cptr = tgt; | ||
41 | if (string) | ||
42 | { | ||
43 | *cptr = mu_strdup (string); | ||
44 | if (!*cptr) | ||
45 | return errno; | ||
46 | } | ||
47 | else | ||
48 | *cptr = NULL; | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | #define STR_TO_FUN to_short | ||
53 | #define STR_TO_TYPE signed short | ||
54 | #define STR_TO_MIN SHRT_MIN | ||
55 | #define STR_TO_MAX SHRT_MAX | ||
56 | #include "to_sn.c" | ||
57 | |||
58 | #define STR_TO_FUN to_ushort | ||
59 | #define STR_TO_TYPE unsigned short | ||
60 | #define STR_TO_MAX USHRT_MAX | ||
61 | #include "to_un.c" | ||
62 | |||
63 | #define STR_TO_FUN to_int | ||
64 | #define STR_TO_TYPE signed int | ||
65 | #define STR_TO_MIN INT_MIN | ||
66 | #define STR_TO_MAX INT_MAX | ||
67 | #include "to_sn.c" | ||
68 | |||
69 | #define STR_TO_FUN to_uint | ||
70 | #define STR_TO_TYPE unsigned int | ||
71 | #define STR_TO_MAX UINT_MAX | ||
72 | #include "to_un.c" | ||
73 | |||
74 | #define STR_TO_FUN to_long | ||
75 | #define STR_TO_TYPE signed long | ||
76 | #define STR_TO_MIN LONG_MIN | ||
77 | #define STR_TO_MAX LONG_MAX | ||
78 | #include "to_sn.c" | ||
79 | |||
80 | #define STR_TO_FUN to_ulong | ||
81 | #define STR_TO_TYPE unsigned long | ||
82 | #define STR_TO_MAX ULONG_MAX | ||
83 | #include "to_un.c" | ||
84 | |||
85 | #define STR_TO_FUN to_size_t | ||
86 | #define STR_TO_TYPE size_t | ||
87 | #define STR_TO_MAX ((size_t)-1) | ||
88 | #include "to_un.c" | ||
89 | |||
90 | static int | ||
91 | time_multiplier (const char *str, unsigned *m, unsigned *plen) | ||
92 | { | ||
93 | static struct timetab | ||
94 | { | ||
95 | char *name; | ||
96 | unsigned mul; | ||
97 | } tab[] = { | ||
98 | { "seconds", 1 }, | ||
99 | { "minutes", 60 }, | ||
100 | { "hours", 60*60 }, | ||
101 | { "days", 24*60*60 }, | ||
102 | { "weeks", 7*24*60*60 }, | ||
103 | { "months", 31*7*24*60*60 }, | ||
104 | { NULL } | ||
105 | }; | ||
106 | struct timetab *p; | ||
107 | int slen; | ||
108 | |||
109 | for (slen = 0; str[slen]; slen++) | ||
110 | if (mu_isspace (str[slen])) | ||
111 | break; | ||
112 | |||
113 | for (p = tab; p->name; p++) | ||
114 | { | ||
115 | if (p->name[0] == mu_tolower (str[0])) | ||
116 | { | ||
117 | int nlen = strlen (p->name); | ||
118 | |||
119 | if (nlen > slen) | ||
120 | nlen = slen; | ||
121 | |||
122 | if (strncasecmp (p->name, str, nlen) == 0) { | ||
123 | *m = p->mul; | ||
124 | if (plen) | ||
125 | *plen = nlen; | ||
126 | return 0; | ||
127 | } | ||
128 | } | ||
129 | } | ||
130 | return 1; | ||
131 | } | ||
132 | |||
133 | static int | ||
134 | to_time_t (void *tgt, char const *string, char **errmsg) | ||
135 | { | ||
136 | time_t *ptr = tgt; | ||
137 | int rc = 0; | ||
138 | time_t interval = 0; | ||
139 | |||
140 | while (*string) | ||
141 | { | ||
142 | char *p; | ||
143 | unsigned long n; | ||
144 | unsigned mul, len; | ||
145 | |||
146 | while (*string && mu_isspace (*string)) | ||
147 | string++; | ||
148 | |||
149 | if (!mu_isdigit (*string) && time_multiplier (string, &mul, &len) == 0) | ||
150 | { | ||
151 | n = 1; | ||
152 | string += len; | ||
153 | } | ||
154 | else | ||
155 | { | ||
156 | n = strtoul (string, &p, 10); | ||
157 | if (*p && !mu_isspace (*p)) | ||
158 | { | ||
159 | string = p; | ||
160 | rc = 1; | ||
161 | break; | ||
162 | } | ||
163 | |||
164 | while (*p && mu_isspace (*p)) | ||
165 | p++; | ||
166 | |||
167 | string = p; | ||
168 | if (*string) | ||
169 | { | ||
170 | if ((rc = time_multiplier (string, &mul, &len))) | ||
171 | break; | ||
172 | string += len; | ||
173 | } | ||
174 | else | ||
175 | mul = 1; | ||
176 | } | ||
177 | interval += n * mul; | ||
178 | } | ||
179 | |||
180 | if (rc) | ||
181 | { | ||
182 | mu_asprintf (errmsg, _("invalid time specification near %s"), string); | ||
183 | return EINVAL; | ||
184 | } | ||
185 | |||
186 | *ptr = interval; | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static int | ||
191 | to_bool (void *tgt, char const *string, char **errmsg) | ||
192 | { | ||
193 | int *ptr = tgt; | ||
194 | |||
195 | if (strcmp (string, "yes") == 0 | ||
196 | || strcmp (string, "on") == 0 | ||
197 | || strcmp (string, "t") == 0 | ||
198 | || strcmp (string, "true") == 0 | ||
199 | || strcmp (string, "1") == 0) | ||
200 | *ptr = 1; | ||
201 | else if (strcmp (string, "no") == 0 | ||
202 | || strcmp (string, "off") == 0 | ||
203 | || strcmp (string, "nil") == 0 | ||
204 | || strcmp (string, "false") == 0 | ||
205 | || strcmp (string, "0") == 0) | ||
206 | *ptr = 0; | ||
207 | else | ||
208 | return EINVAL; | ||
209 | |||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | #if 0 | ||
214 | static int | ||
215 | to_ipv4 (void *tgt, char const *string, char **errmsg) | ||
216 | { | ||
217 | struct in_addr *ptr = tgt; | ||
218 | struct in_addr addr; | ||
219 | |||
220 | if (inet_aton (string, &addr) == 0) | ||
221 | { | ||
222 | mu_diag_at_locus (MU_LOG_ERROR, &mu_cfg_locus, _("not an IPv4")); | ||
223 | mu_cfg_error_count++; | ||
224 | return 1; | ||
225 | } | ||
226 | addr.s_addr = ntohl (addr.s_addr); | ||
227 | |||
228 | *ptr = addr; | ||
229 | return 0; | ||
230 | } | ||
231 | #endif | ||
232 | |||
233 | static int | ||
234 | to_cidr (void *tgt, char const *string, char **errmsg) | ||
235 | { | ||
236 | struct mu_cidr *ptr = tgt; | ||
237 | return mu_cidr_from_string (ptr, string); | ||
238 | } | ||
239 | |||
240 | static int | ||
241 | to_incr (void *tgt, char const *string, char **errmsg) | ||
242 | { | ||
243 | ++*(int*)tgt; | ||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | static str_to_c_t str_to_c[] = { | ||
248 | [mu_c_string] = to_string, | ||
249 | [mu_c_short] = to_short, | ||
250 | [mu_c_ushort] = to_ushort, | ||
251 | [mu_c_int] = to_int, | ||
252 | [mu_c_uint] = to_uint, | ||
253 | [mu_c_long] = to_long, | ||
254 | [mu_c_ulong] = to_ulong, | ||
255 | [mu_c_size] = to_size_t, | ||
256 | /* FIXME [mu_c_off] = { to_off, generic_dealloc }, */ | ||
257 | [mu_c_time] = to_time_t, | ||
258 | [mu_c_bool] = to_bool, | ||
259 | /* FIXME [mu_c_ipv4] = to_ipv4, */ | ||
260 | [mu_c_cidr] = to_cidr, | ||
261 | /* FIXME [mu_c_host] = { to_host, generic_dealloc } */ | ||
262 | [mu_c_incr] = to_incr | ||
263 | }; | ||
264 | |||
265 | int | ||
266 | mu_str_to_c (char const *string, enum mu_c_type type, void *tgt, char **errmsg) | ||
267 | { | ||
268 | *errmsg = NULL; | ||
269 | if ((size_t)type >= sizeof (str_to_c) / sizeof (str_to_c[0])) | ||
270 | return EINVAL; | ||
271 | if (!str_to_c[type]) | ||
272 | return ENOSYS; | ||
273 | return str_to_c[type] (tgt, string, errmsg); | ||
274 | } |
libmailutils/string/to_sn.c
0 → 100644
1 | #ifndef STR_TO_FUN | ||
2 | # error "STR_TO_FUN not defined" | ||
3 | #endif | ||
4 | #ifndef STR_TO_TYPE | ||
5 | # error "STR_TO_TYPE not defined" | ||
6 | #endif | ||
7 | #ifndef STR_TO_MIN | ||
8 | # error "STR_TO_MIN not defined" | ||
9 | #endif | ||
10 | #ifndef STR_TO_MAX | ||
11 | # error "STR_TO_MAX not defined" | ||
12 | #endif | ||
13 | |||
14 | static int | ||
15 | STR_TO_FUN (void *tgt, char const *string, char **errmsg) | ||
16 | { | ||
17 | STR_TO_TYPE *ptr = tgt; | ||
18 | intmax_t v; | ||
19 | char *p; | ||
20 | |||
21 | errno = 0; | ||
22 | v = strtoimax (string, &p, 10); | ||
23 | if (errno) | ||
24 | return errno; | ||
25 | if (*p) | ||
26 | return EINVAL; | ||
27 | if (STR_TO_MIN <= v && v <= STR_TO_MAX) | ||
28 | { | ||
29 | *ptr = (STR_TO_TYPE) v; | ||
30 | return 0; | ||
31 | } | ||
32 | return ERANGE; | ||
33 | } | ||
34 | #undef STR_TO_FUN | ||
35 | #undef STR_TO_TYPE | ||
36 | #undef STR_TO_MIN | ||
37 | #undef STR_TO_MAX |
libmailutils/string/to_un.c
0 → 100644
1 | #ifndef STR_TO_FUN | ||
2 | # error "STR_TO_FUN not defined" | ||
3 | #endif | ||
4 | #ifndef STR_TO_TYPE | ||
5 | # error "STR_TO_TYPE not defined" | ||
6 | #endif | ||
7 | #ifndef STR_TO_MAX | ||
8 | # error "STR_TO_MAX not defined" | ||
9 | #endif | ||
10 | |||
11 | static int | ||
12 | STR_TO_FUN (void *tgt, char const *string, char **errmsg) | ||
13 | { | ||
14 | STR_TO_TYPE *ptr = tgt; | ||
15 | uintmax_t v; | ||
16 | char *p; | ||
17 | |||
18 | errno = 0; | ||
19 | v = strtoumax (string, &p, 10); | ||
20 | if (errno) | ||
21 | return errno; | ||
22 | if (*p) | ||
23 | return EINVAL; | ||
24 | if (v <= STR_TO_MAX) | ||
25 | { | ||
26 | *ptr = (STR_TO_TYPE) v; | ||
27 | return 0; | ||
28 | } | ||
29 | return ERANGE; | ||
30 | } | ||
31 | |||
32 | #undef STR_TO_FUN | ||
33 | #undef STR_TO_TYPE | ||
34 | #undef STR_TO_MAX |
libmailutils/tests/parseopt.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2016 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 | #ifdef HAVE_CONFIG_H | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | #include <mailutils/mailutils.h> | ||
21 | #include <mailutils/opt.h> | ||
22 | |||
23 | char *file_name; | ||
24 | char *find_value; | ||
25 | char *opt_value = "initial"; | ||
26 | int jobs = 0; | ||
27 | int x_option; | ||
28 | int a_option; | ||
29 | int d_option; | ||
30 | |||
31 | struct mu_option group_a[] = { | ||
32 | MU_OPTION_GROUP("Group A"), | ||
33 | { "file", 'f', "FILE", MU_OPTION_DEFAULT, | ||
34 | "set file name", | ||
35 | mu_c_string, &file_name | ||
36 | }, | ||
37 | { "find", 'F', "VALUE", MU_OPTION_DEFAULT, | ||
38 | "find VALUE", | ||
39 | mu_c_string, &find_value }, | ||
40 | { "optional", 'o', "FILE", MU_OPTION_ARG_OPTIONAL, | ||
41 | "optional argument", | ||
42 | mu_c_string, &opt_value }, | ||
43 | { NULL, 'x', NULL, MU_OPTION_DEFAULT, | ||
44 | "short-only option", | ||
45 | mu_c_incr, &x_option }, | ||
46 | { "all", 'a', NULL, MU_OPTION_DEFAULT, | ||
47 | "no arguments to this one", | ||
48 | mu_c_bool, &a_option }, | ||
49 | MU_OPTION_END | ||
50 | }; | ||
51 | |||
52 | struct mu_option group_b[] = { | ||
53 | MU_OPTION_GROUP("Group B"), | ||
54 | { "debug", 'd', NULL, MU_OPTION_DEFAULT, | ||
55 | "another option", | ||
56 | mu_c_incr, &d_option }, | ||
57 | { "verbose", 'v', NULL, MU_OPTION_ALIAS }, | ||
58 | { "jobs", 'j', "N", MU_OPTION_DEFAULT, | ||
59 | "sets numeric value", | ||
60 | mu_c_int, &jobs }, | ||
61 | MU_OPTION_END | ||
62 | }; | ||
63 | |||
64 | struct mu_option *optv[] = { group_a, group_b, NULL }; | ||
65 | |||
66 | #define S(s) ((s)?(s):"(null)") | ||
67 | |||
68 | int | ||
69 | main (int argc, char *argv[]) | ||
70 | { | ||
71 | struct mu_parseopt po; | ||
72 | int rc; | ||
73 | int i; | ||
74 | |||
75 | mu_stdstream_setup (MU_STDSTREAM_RESET_NONE); | ||
76 | |||
77 | rc = mu_parseopt (&po, argc, argv, optv, MU_PARSEOPT_DEFAULT); | ||
78 | printf ("rc=%d\n", rc); | ||
79 | mu_parseopt_apply (&po); | ||
80 | |||
81 | argc -= po.po_ind; | ||
82 | argv += po.po_ind; | ||
83 | |||
84 | mu_parseopt_free (&po); | ||
85 | |||
86 | printf ("file_name=%s\n", S(file_name)); | ||
87 | printf ("find_value=%s\n", S(find_value)); | ||
88 | printf ("opt_value=%s\n", S(opt_value)); | ||
89 | printf ("x_option=%d\n", x_option); | ||
90 | printf ("a_option=%d\n", a_option); | ||
91 | printf ("d_option=%d\n", d_option); | ||
92 | printf ("jobs=%d\n", jobs); | ||
93 | |||
94 | printf ("argv:\n"); | ||
95 | for (i = 0; i < argc; i++) | ||
96 | { | ||
97 | printf ("%d: %s\n", i, argv[i]); | ||
98 | } | ||
99 | |||
100 | return 0; | ||
101 | } |
-
Please register or sign in to post a comment