Commit 53eb6813 53eb68133eeede20c49445cd4ff58ad6e4becc07 by Sergey Poznyakoff

Support for single-dash long options (as in MH) and negation for boolean options.

* include/mailutils/opt.h (MU_PARSEOPT_SINGLE_DASH)
(MU_PARSEOPT_NEGATION): New flags.
(mu_parseopt) <po_negation, po_long_opt_start>: New fields.
(mu_option_describe_options): Change signature.
* libmailutils/opt/help.c (init_usage_vars): Initialize
long_opt_col depending on the value of MU_PARSEOPT_SINGLE_DASH
bit.
(print_option): Handle single-dash long options and boolean
options with negations.
(option_summary): Likewise.
(mu_option_describe_options): Take struct mu_parseopt *
as its second parameter.
* libmailutils/opt/opt.c (find_long_option): Handle
boolean options with negations.  Return also a pointer
to the mu_option describing the originally used option
(as opposed to the canonical one returned by the function).
(parse): Handle single-dash long options.
(parseopt_init): Initialize po_negation and po_long_opt_start.
* libmailutils/tests/parseopt.c (parseopt_param): Handle
MU_PARSEOPT_SINGLE_DASH and MU_PARSEOPT_NEGATION.
1 parent fa7ac605
...@@ -103,13 +103,17 @@ struct mu_option_cache ...@@ -103,13 +103,17 @@ struct mu_option_cache
103 #define MU_PARSEOPT_DATA 0x00400000 103 #define MU_PARSEOPT_DATA 0x00400000
104 #define MU_PARSEOPT_VERSION_HOOK 0x00800000 104 #define MU_PARSEOPT_VERSION_HOOK 0x00800000
105 #define MU_PARSEOPT_PROG_DOC_HOOK 0x01000000 105 #define MU_PARSEOPT_PROG_DOC_HOOK 0x01000000
106 /* Long options start with single dash. Disables recognition of traditional
107 short options */
108 #define MU_PARSEOPT_SINGLE_DASH 0x02000000
109 /* Negation prefix is set */
110 #define MU_PARSEOPT_NEGATION 0x04000000
106 111
107 /* Reuse mu_parseopt struct initialized previously */ 112 /* Reuse mu_parseopt struct initialized previously */
108 #define MU_PARSEOPT_REUSE 0x80000000 113 #define MU_PARSEOPT_REUSE 0x80000000
109 /* Mask for immutable flag bits */ 114 /* Mask for immutable flag bits */
110 #define MU_PARSEOPT_IMMUTABLE_MASK 0xFFFFF000 115 #define MU_PARSEOPT_IMMUTABLE_MASK 0xFFFFF000
111 116
112
113 struct mu_parseopt 117 struct mu_parseopt
114 { 118 {
115 /* Input data: */ 119 /* Input data: */
...@@ -119,6 +123,7 @@ struct mu_parseopt ...@@ -119,6 +123,7 @@ struct mu_parseopt
119 struct mu_option **po_optv; /* Array of ptrs to option structures */ 123 struct mu_option **po_optv; /* Array of ptrs to option structures */
120 int po_flags; 124 int po_flags;
121 125
126 char *po_negation; /* Negation prefix for boolean options */
122 void *po_data; /* Call-specific data */ 127 void *po_data; /* Call-specific data */
123 128
124 int po_exit_error; /* Exit on error with this code */ 129 int po_exit_error; /* Exit on error with this code */
...@@ -146,6 +151,9 @@ struct mu_parseopt ...@@ -146,6 +151,9 @@ struct mu_parseopt
146 char *po_cur; /* Points to the next character */ 151 char *po_cur; /* Points to the next character */
147 int po_chr; /* Single-char option */ 152 int po_chr; /* Single-char option */
148 153
154 char *po_long_opt_start; /* Character sequence that starts
155 long option */
156
149 /* The following two keep the position of the first non-optional argument 157 /* The following two keep the position of the first non-optional argument
150 and the number of contiguous non-optional arguments after it. 158 and the number of contiguous non-optional arguments after it.
151 Obviously, the following holds true: 159 Obviously, the following holds true:
...@@ -161,6 +169,7 @@ struct mu_parseopt ...@@ -161,6 +169,7 @@ struct mu_parseopt
161 unsigned po_permuted:1; /* Whether the arguments were permuted */ 169 unsigned po_permuted:1; /* Whether the arguments were permuted */
162 }; 170 };
163 171
172
164 int mu_parseopt (struct mu_parseopt *p, 173 int mu_parseopt (struct mu_parseopt *p,
165 int argc, char **argv, struct mu_option **optv, 174 int argc, char **argv, struct mu_option **optv,
166 int flags); 175 int flags);
...@@ -171,8 +180,7 @@ void mu_parseopt_free (struct mu_parseopt *p); ...@@ -171,8 +180,7 @@ void mu_parseopt_free (struct mu_parseopt *p);
171 180
172 unsigned mu_parseopt_getcolumn (const char *name); 181 unsigned mu_parseopt_getcolumn (const char *name);
173 182
174 void mu_option_describe_options (mu_stream_t str, 183 void mu_option_describe_options (mu_stream_t str, struct mu_parseopt *p);
175 struct mu_option **optbuf, size_t optcnt);
176 void mu_program_help (struct mu_parseopt *p, mu_stream_t str); 184 void mu_program_help (struct mu_parseopt *p, mu_stream_t str);
177 void mu_program_usage (struct mu_parseopt *p, int optsummary, mu_stream_t str); 185 void mu_program_usage (struct mu_parseopt *p, int optsummary, mu_stream_t str);
178 void mu_program_version (struct mu_parseopt *po, mu_stream_t str); 186 void mu_program_version (struct mu_parseopt *po, mu_stream_t str);
...@@ -180,4 +188,6 @@ void mu_program_version (struct mu_parseopt *po, mu_stream_t str); ...@@ -180,4 +188,6 @@ void mu_program_version (struct mu_parseopt *po, mu_stream_t str);
180 void mu_option_set_value (struct mu_parseopt *po, struct mu_option *opt, 188 void mu_option_set_value (struct mu_parseopt *po, struct mu_option *opt,
181 char const *arg); 189 char const *arg);
182 190
191 int mu_option_possible_negation (struct mu_parseopt *po, struct mu_option *opt);
192
183 #endif 193 #endif
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
30 #include <mailutils/stream.h> 30 #include <mailutils/stream.h>
31 31
32 unsigned short_opt_col = 2; 32 unsigned short_opt_col = 2;
33 unsigned long_opt_col = 6; 33 unsigned long_opt_col; /* Initialized in init_usage_vars */
34 /*FIXME: doc_opt_col? */ 34 /*FIXME: doc_opt_col? */
35 unsigned header_col = 1; 35 unsigned header_col = 1;
36 unsigned opt_doc_col = 29; 36 unsigned opt_doc_col = 29;
...@@ -170,6 +170,11 @@ init_usage_vars (struct mu_parseopt *po) ...@@ -170,6 +170,11 @@ init_usage_vars (struct mu_parseopt *po)
170 struct mu_wordsplit ws; 170 struct mu_wordsplit ws;
171 size_t i; 171 size_t i;
172 172
173 if (po->po_flags & MU_PARSEOPT_SINGLE_DASH)
174 long_opt_col = 2;
175 else
176 long_opt_col = 6;
177
173 fmt = getenv ("ARGP_HELP_FMT"); 178 fmt = getenv ("ARGP_HELP_FMT");
174 if (!fmt) 179 if (!fmt)
175 return; 180 return;
...@@ -223,11 +228,10 @@ print_opt_arg (mu_stream_t str, struct mu_option *opt, int delim) ...@@ -223,11 +228,10 @@ print_opt_arg (mu_stream_t str, struct mu_option *opt, int delim)
223 } 228 }
224 229
225 static size_t 230 static size_t
226 print_option (mu_stream_t str, 231 print_option (mu_stream_t str, struct mu_parseopt *po, size_t num,
227 struct mu_option **optbuf, size_t optcnt, size_t num,
228 int *argsused) 232 int *argsused)
229 { 233 {
230 struct mu_option *opt = optbuf[num]; 234 struct mu_option *opt = po->po_optv[num];
231 size_t next, i; 235 size_t next, i;
232 int delim; 236 int delim;
233 int first_option = 1; 237 int first_option = 1;
...@@ -240,38 +244,47 @@ print_option (mu_stream_t str, ...@@ -240,38 +244,47 @@ print_option (mu_stream_t str,
240 if (opt->opt_doc[0]) 244 if (opt->opt_doc[0])
241 { 245 {
242 set_margin (str, header_col); 246 set_margin (str, header_col);
243 mu_stream_printf (str, "%s", gettext (opt->opt_doc)); 247 mu_stream_printf (str, "%s\n", gettext (opt->opt_doc));
244 } 248 }
245 return num + 1; 249 return num + 1;
246 } 250 }
247 251
248 /* count aliases */ 252 /* count aliases */
249 for (next = num + 1; 253 for (next = num + 1;
250 next < optcnt && optbuf[next]->opt_flags & MU_OPTION_ALIAS; 254 next < po->po_optc && po->po_optv[next]->opt_flags & MU_OPTION_ALIAS;
251 next++); 255 next++);
252 256
253 if (opt->opt_flags & MU_OPTION_HIDDEN) 257 if (opt->opt_flags & MU_OPTION_HIDDEN)
254 return next; 258 return next;
255 259
260 if (po->po_flags & MU_PARSEOPT_SINGLE_DASH)
261 {
262 if (!opt->opt_long)
263 return num + 1; /* Ignore erroneous option */
264 set_margin (str, long_opt_col);
265 }
266 else
267 {
256 set_margin (str, short_opt_col); 268 set_margin (str, short_opt_col);
257 for (i = num; i < next; i++) 269 for (i = num; i < next; i++)
258 { 270 {
259 if (MU_OPTION_IS_VALID_SHORT_OPTION (optbuf[i])) 271 if (MU_OPTION_IS_VALID_SHORT_OPTION (po->po_optv[i]))
260 { 272 {
261 if (first_option) 273 if (first_option)
262 first_option = 0; 274 first_option = 0;
263 else 275 else
264 mu_stream_printf (str, ", "); 276 mu_stream_printf (str, ", ");
265 mu_stream_printf (str, "-%c", optbuf[i]->opt_short); 277 mu_stream_printf (str, "-%c", po->po_optv[i]->opt_short);
266 delim = ' '; 278 delim = ' ';
267 if (opt->opt_arg && dup_args) 279 if (opt->opt_arg && dup_args)
268 print_opt_arg (str, opt, delim); 280 print_opt_arg (str, opt, delim);
269 } 281 }
270 } 282 }
283 }
271 284
272 for (i = num; i < next; i++) 285 for (i = num; i < next; i++)
273 { 286 {
274 if (MU_OPTION_IS_VALID_LONG_OPTION (optbuf[i])) 287 if (MU_OPTION_IS_VALID_LONG_OPTION (po->po_optv[i]))
275 { 288 {
276 if (first_option) 289 if (first_option)
277 first_option = 0; 290 first_option = 0;
...@@ -287,8 +300,12 @@ print_option (mu_stream_t str, ...@@ -287,8 +300,12 @@ print_option (mu_stream_t str,
287 first_long_option = 0; 300 first_long_option = 0;
288 } 301 }
289 302
290 mu_stream_printf (str, "--%s", optbuf[i]->opt_long); 303 mu_stream_printf (str, "%s", po->po_long_opt_start);
291 delim = '='; 304 if (mu_option_possible_negation (po, po->po_optv[i]))
305 mu_stream_printf (str, "[%s]", po->po_negation);
306 mu_stream_printf (str, "%s", po->po_optv[i]->opt_long);
307 delim = ((po->po_flags & MU_PARSEOPT_SINGLE_DASH)
308 && !(opt->opt_flags & MU_OPTION_ARG_OPTIONAL)) ? ' ' : '=';
292 if (opt->opt_arg && dup_args) 309 if (opt->opt_arg && dup_args)
293 print_opt_arg (str, opt, delim); 310 print_opt_arg (str, opt, delim);
294 } 311 }
...@@ -308,14 +325,13 @@ print_option (mu_stream_t str, ...@@ -308,14 +325,13 @@ print_option (mu_stream_t str,
308 } 325 }
309 326
310 void 327 void
311 mu_option_describe_options (mu_stream_t str, 328 mu_option_describe_options (mu_stream_t str, struct mu_parseopt *po)
312 struct mu_option **optbuf, size_t optcnt)
313 { 329 {
314 unsigned i; 330 unsigned i;
315 int argsused = 0; 331 int argsused = 0;
316 332
317 for (i = 0; i < optcnt; ) 333 for (i = 0; i < po->po_optc; )
318 i = print_option (str, optbuf, optcnt, i, &argsused); 334 i = print_option (str, po, i, &argsused);
319 mu_stream_printf (str, "\n"); 335 mu_stream_printf (str, "\n");
320 336
321 if (argsused && dup_args_note) 337 if (argsused && dup_args_note)
...@@ -358,7 +374,7 @@ mu_program_help (struct mu_parseopt *po, mu_stream_t outstr) ...@@ -358,7 +374,7 @@ mu_program_help (struct mu_parseopt *po, mu_stream_t outstr)
358 mu_stream_printf (str, "\n"); 374 mu_stream_printf (str, "\n");
359 } 375 }
360 376
361 mu_option_describe_options (str, po->po_optv, po->po_optc); 377 mu_option_describe_options (str, po);
362 378
363 if (po->po_help_hook) 379 if (po->po_help_hook)
364 { 380 {
...@@ -432,6 +448,8 @@ option_summary (struct mu_parseopt *po, mu_stream_t str) ...@@ -432,6 +448,8 @@ option_summary (struct mu_parseopt *po, mu_stream_t str)
432 448
433 idxbuf = mu_calloc (optcnt, sizeof (idxbuf[0])); 449 idxbuf = mu_calloc (optcnt, sizeof (idxbuf[0]));
434 450
451 if (!(po->po_flags & MU_PARSEOPT_SINGLE_DASH))
452 {
435 /* Print a list of short options without arguments. */ 453 /* Print a list of short options without arguments. */
436 for (i = nidx = 0; i < optcnt; i++) 454 for (i = nidx = 0; i < optcnt; i++)
437 if (MU_OPTION_IS_VALID_SHORT_OPTION (optbuf[i]) && !optbuf[i]->opt_arg) 455 if (MU_OPTION_IS_VALID_SHORT_OPTION (optbuf[i]) && !optbuf[i]->opt_arg)
...@@ -469,6 +487,7 @@ option_summary (struct mu_parseopt *po, mu_stream_t str) ...@@ -469,6 +487,7 @@ option_summary (struct mu_parseopt *po, mu_stream_t str)
469 mu_stream_printf (str, " [-%c %s]", opt->opt_short, arg); 487 mu_stream_printf (str, " [-%c %s]", opt->opt_short, arg);
470 } 488 }
471 } 489 }
490 }
472 491
473 /* Print a list of long options */ 492 /* Print a list of long options */
474 for (i = nidx = 0; i < optcnt; i++) 493 for (i = nidx = 0; i < optcnt; i++)
...@@ -486,11 +505,17 @@ option_summary (struct mu_parseopt *po, mu_stream_t str) ...@@ -486,11 +505,17 @@ option_summary (struct mu_parseopt *po, mu_stream_t str)
486 struct mu_option *opt = optbuf[idxbuf[i]]; 505 struct mu_option *opt = optbuf[idxbuf[i]];
487 const char *arg = opt->opt_arg ? gettext (opt->opt_arg) : NULL; 506 const char *arg = opt->opt_arg ? gettext (opt->opt_arg) : NULL;
488 507
489 mu_stream_printf (str, " [--%s", opt->opt_long); 508 mu_stream_printf (str, " [%s", po->po_long_opt_start);
509 if (mu_option_possible_negation (po, opt))
510 mu_stream_printf (str, "[%s]", po->po_negation);
511 mu_stream_printf (str, "%s", opt->opt_long);
512
490 if (opt->opt_arg) 513 if (opt->opt_arg)
491 { 514 {
492 if (opt->opt_flags & MU_OPTION_ARG_OPTIONAL) 515 if (opt->opt_flags & MU_OPTION_ARG_OPTIONAL)
493 mu_stream_printf (str, "[=%s]", arg); 516 mu_stream_printf (str, "[=%s]", arg);
517 else if (po->po_flags & MU_PARSEOPT_SINGLE_DASH)
518 mu_stream_printf (str, " %s", arg);
494 else 519 else
495 mu_stream_printf (str, "=%s", arg); 520 mu_stream_printf (str, "=%s", arg);
496 } 521 }
......
...@@ -193,43 +193,68 @@ find_short_option (struct mu_parseopt *po, int chr) ...@@ -193,43 +193,68 @@ find_short_option (struct mu_parseopt *po, int chr)
193 it in *ARGPTR. */ 193 it in *ARGPTR. */
194 struct mu_option * 194 struct mu_option *
195 find_long_option (struct mu_parseopt *po, char const *optstr, 195 find_long_option (struct mu_parseopt *po, char const *optstr,
196 char **argptr) 196 struct mu_option **used_opt_ptr,
197 char **used_value,
198 char **value)
197 { 199 {
198 size_t i; 200 size_t i;
199 size_t optlen; 201 size_t optlen; /* Length of the option in optstr */
200 size_t ind; 202 int found = 0; /* 1 if the match was found, 2 if option is ambiguous */
201 int found = 0; 203 int neglen; /* Length of the negation prefix, if any */
204 int neg = 0; /* 1 if a boolean option is negated */
205 struct mu_option *ret_opt = NULL;
206 struct mu_option *used_opt;
202 207
203 optlen = strcspn (optstr, "="); 208 optlen = strcspn (optstr, "=");
209 if (po->po_negation)
210 neglen = strlen (po->po_negation);
204 211
205 for (i = 0; i < po->po_optc; i++) 212 for (i = 0; i < po->po_optc; i++)
206 { 213 {
207 if (MU_OPTION_IS_VALID_LONG_OPTION (po->po_optv[i]) 214 if (MU_OPTION_IS_VALID_LONG_OPTION (po->po_optv[i]))
208 && optlen <= strlen (po->po_optv[i]->opt_long) 215 {
216 size_t len = strlen (po->po_optv[i]->opt_long);
217 struct mu_option *opt = option_unalias (po, i);
218
219 if ((optlen <= len
209 && memcmp (po->po_optv[i]->opt_long, optstr, optlen) == 0) 220 && memcmp (po->po_optv[i]->opt_long, optstr, optlen) == 0)
221 || (neg = (mu_option_possible_negation (po, opt)
222 && optlen <= neglen + len
223 && memcmp (optstr, po->po_negation, neglen) == 0
224 && memcmp (optstr + neglen, po->po_optv[i]->opt_long,
225 optlen - neglen) == 0)))
210 { 226 {
211 switch (found) 227 switch (found)
212 { 228 {
213 case 0: 229 case 0:
214 ind = i; 230 used_opt = po->po_optv[i];
231 ret_opt = opt;
215 found++; 232 found++;
216 if (optlen == strlen (po->po_optv[i]->opt_long)) 233 if (optlen == len || (neg && optlen == neglen + len))
217 i = po->po_optc - 1; /* exact match: break the loop */ 234 i = po->po_optc - 1; /* exact match: break the loop */
218 break; 235 break;
219 236
220 case 1: 237 case 1:
221 if (option_unalias (po, i) == option_unalias (po, ind)) 238 if (opt == ret_opt)
222 continue; 239 continue;
223 if (po->po_flags & MU_PARSEOPT_IGNORE_ERRORS) 240 if (po->po_flags & MU_PARSEOPT_IGNORE_ERRORS)
224 return NULL; 241 return NULL;
225 mu_parseopt_error (po, 242 mu_parseopt_error (po,
226 _("option '--%*.*s' is ambiguous; possibilities:"), 243 _("option '%s%*.*s' is ambiguous; possibilities:"),
244 po->po_long_opt_start,
227 optlen, optlen, optstr); 245 optlen, optlen, optstr);
228 fprintf (stderr, "--%s\n", po->po_optv[ind]->opt_long); 246 fprintf (stderr, "%s%s%s\n",
247 po->po_long_opt_start,
248 neg ? po->po_negation : "",
249 used_opt->opt_long);
229 found++; 250 found++;
230 251
231 case 2: 252 case 2:
232 fprintf (stderr, "--%s\n", po->po_optv[i]->opt_long); 253 fprintf (stderr, "%s%s%s\n",
254 po->po_long_opt_start,
255 neg ? po->po_negation : "",
256 po->po_optv[i]->opt_long);
257 }
233 } 258 }
234 } 259 }
235 } 260 }
...@@ -237,14 +262,25 @@ find_long_option (struct mu_parseopt *po, char const *optstr, ...@@ -237,14 +262,25 @@ find_long_option (struct mu_parseopt *po, char const *optstr,
237 switch (found) 262 switch (found)
238 { 263 {
239 case 0: 264 case 0:
240 mu_parseopt_error (po, _("unrecognized option '--%s'"), optstr); 265 mu_parseopt_error (po, _("unrecognized option '%s%s'"),
266 po->po_long_opt_start, optstr);
241 break; 267 break;
242 268
243 case 1: 269 case 1:
270 *used_opt_ptr = used_opt;
244 if (optstr[optlen]) 271 if (optstr[optlen])
245 ++optlen; 272 ++optlen;
246 *argptr = (char *)(optstr + optlen); 273 *used_value = (char *)(optstr + optlen);
247 return option_unalias (po, ind); 274 if (ret_opt->opt_type == mu_c_bool)
275 {
276 if (neg)
277 *value = "0";
278 else
279 *value = "1";
280 }
281 else
282 *value = NULL;
283 return ret_opt;
248 284
249 case 2: 285 case 2:
250 break; 286 break;
...@@ -313,18 +349,7 @@ next_opt (struct mu_parseopt *po) ...@@ -313,18 +349,7 @@ next_opt (struct mu_parseopt *po)
313 if (!po->po_cur) 349 if (!po->po_cur)
314 return 1; 350 return 1;
315 if (po->po_cur[0] == '-' && po->po_cur[1]) 351 if (po->po_cur[0] == '-' && po->po_cur[1])
316 break;
317 if (!(po->po_flags & MU_PARSEOPT_IN_ORDER))
318 { 352 {
319 if (!po->po_permuted && po->po_arg_count == 0)
320 po->po_arg_start = po->po_ind - 1;
321 po->po_arg_count++;
322 continue;
323 }
324 else
325 return 1;
326 }
327
328 if (*++po->po_cur == '-') 353 if (*++po->po_cur == '-')
329 { 354 {
330 if (*++po->po_cur == 0) 355 if (*++po->po_cur == 0)
...@@ -335,11 +360,36 @@ next_opt (struct mu_parseopt *po) ...@@ -335,11 +360,36 @@ next_opt (struct mu_parseopt *po)
335 return 1; 360 return 1;
336 } 361 }
337 362
363 if (po->po_flags & MU_PARSEOPT_SINGLE_DASH)
364 /* a non-optional argument */;
365 else
366 {
338 /* It's a long option */ 367 /* It's a long option */
339 po->po_chr = 0; 368 po->po_chr = 0;
340 return 0; 369 return 0;
341 } 370 }
342 } 371 }
372 else if (po->po_flags & MU_PARSEOPT_SINGLE_DASH)
373 {
374 /* Assume single-dash long option */
375 po->po_chr = 0;
376 return 0;
377 }
378 else
379 break;
380 }
381
382 if (!(po->po_flags & MU_PARSEOPT_IN_ORDER))
383 {
384 if (!po->po_permuted && po->po_arg_count == 0)
385 po->po_arg_start = po->po_ind - 1;
386 po->po_arg_count++;
387 continue;
388 }
389 else
390 return 1;
391 }
392 }
343 393
344 po->po_chr = *po->po_cur++; 394 po->po_chr = *po->po_cur++;
345 395
...@@ -386,18 +436,18 @@ parse (struct mu_parseopt *po) ...@@ -386,18 +436,18 @@ parse (struct mu_parseopt *po)
386 436
387 while (next_opt (po) == 0) 437 while (next_opt (po) == 0)
388 { 438 {
389 struct mu_option *opt; 439 struct mu_option *opt, *uopt;
390 char *long_opt; 440 char *value;
391 441
392 if (po->po_chr) 442 if (po->po_chr)
393 { 443 {
394 opt = find_short_option (po, po->po_chr); 444 opt = find_short_option (po, po->po_chr);
395 long_opt = NULL; 445 uopt = NULL;
446 value = NULL;
396 } 447 }
397 else 448 else
398 { 449 {
399 long_opt = po->po_cur; 450 opt = find_long_option (po, po->po_cur, &uopt, &po->po_cur, &value);
400 opt = find_long_option (po, long_opt, &po->po_cur);
401 } 451 }
402 452
403 if (opt) 453 if (opt)
...@@ -417,10 +467,10 @@ parse (struct mu_parseopt *po) ...@@ -417,10 +467,10 @@ parse (struct mu_parseopt *po)
417 arg = po->po_argv[po->po_ind++]; 467 arg = po->po_argv[po->po_ind++];
418 else 468 else
419 { 469 {
420 if (long_opt) 470 if (uopt)
421 mu_parseopt_error (po, 471 mu_parseopt_error (po,
422 _("option '--%s' requires an argument"), 472 _("option '%s%s' requires an argument"),
423 long_opt); 473 po->po_long_opt_start, uopt->opt_long);
424 else 474 else
425 mu_parseopt_error (po, 475 mu_parseopt_error (po,
426 _("option '-%c' requires an argument"), 476 _("option '-%c' requires an argument"),
...@@ -437,13 +487,14 @@ parse (struct mu_parseopt *po) ...@@ -437,13 +487,14 @@ parse (struct mu_parseopt *po)
437 } 487 }
438 else 488 else
439 { 489 {
440 if (long_opt 490 if (uopt
441 && po->po_cur[0] 491 && po->po_cur[0]
442 && !(po->po_flags & MU_OPTION_ARG_OPTIONAL)) 492 && !(po->po_flags & MU_OPTION_ARG_OPTIONAL))
443 { 493 {
444 mu_parseopt_error (po, 494 mu_parseopt_error (po,
445 _("option '--%s' doesn't allow an argument"), 495 _("option '%s%s' doesn't allow an argument"),
446 long_opt); 496 po->po_long_opt_start,
497 uopt->opt_long);
447 po->po_opterr = po->po_ind; 498 po->po_opterr = po->po_ind;
448 if (po->po_flags & MU_PARSEOPT_NO_ERREXIT) 499 if (po->po_flags & MU_PARSEOPT_NO_ERREXIT)
449 { 500 {
...@@ -456,6 +507,9 @@ parse (struct mu_parseopt *po) ...@@ -456,6 +507,9 @@ parse (struct mu_parseopt *po)
456 arg = NULL; 507 arg = NULL;
457 } 508 }
458 509
510 if (!arg && value)
511 arg = value;
512
459 add_option_cache (po, opt, arg); 513 add_option_cache (po, opt, arg);
460 } 514 }
461 else 515 else
...@@ -515,6 +569,13 @@ parseopt_init (struct mu_parseopt *po, struct mu_option **options, ...@@ -515,6 +569,13 @@ parseopt_init (struct mu_parseopt *po, struct mu_option **options,
515 po->po_version_hook = NULL; 569 po->po_version_hook = NULL;
516 if (!(flags & MU_PARSEOPT_PROG_DOC_HOOK)) 570 if (!(flags & MU_PARSEOPT_PROG_DOC_HOOK))
517 po->po_prog_doc_hook = NULL; 571 po->po_prog_doc_hook = NULL;
572 if (!(flags & MU_PARSEOPT_NEGATION))
573 po->po_negation = NULL;
574
575 if (flags & MU_PARSEOPT_SINGLE_DASH)
576 po->po_long_opt_start = "-";
577 else
578 po->po_long_opt_start = "--";
518 579
519 /* Count the options */ 580 /* Count the options */
520 po->po_optc = 0; 581 po->po_optc = 0;
...@@ -686,3 +747,9 @@ mu_option_set_value (struct mu_parseopt *po, struct mu_option *opt, ...@@ -686,3 +747,9 @@ mu_option_set_value (struct mu_parseopt *po, struct mu_option *opt,
686 } 747 }
687 } 748 }
688 } 749 }
750
751 int
752 mu_option_possible_negation (struct mu_parseopt *po, struct mu_option *opt)
753 {
754 return po->po_negation && opt->opt_type == mu_c_bool && !opt->opt_arg;
755 }
......
...@@ -141,6 +141,10 @@ static struct parseopt_param parseopt_param[] = { ...@@ -141,6 +141,10 @@ static struct parseopt_param parseopt_param[] = {
141 { "MU_PARSEOPT_EXIT_ERROR", MU_PARSEOPT_EXIT_ERROR, 141 { "MU_PARSEOPT_EXIT_ERROR", MU_PARSEOPT_EXIT_ERROR,
142 mu_c_int, mu_offsetof(struct mu_parseopt, po_exit_error) }, 142 mu_c_int, mu_offsetof(struct mu_parseopt, po_exit_error) },
143 { "MU_PARSEOPT_VERSION_HOOK", MU_PARSEOPT_VERSION_HOOK, mu_c_void }, 143 { "MU_PARSEOPT_VERSION_HOOK", MU_PARSEOPT_VERSION_HOOK, mu_c_void },
144 { "MU_PARSEOPT_SINGLE_DASH", MU_PARSEOPT_SINGLE_DASH, mu_c_void },
145 { "MU_PARSEOPT_NEGATION", MU_PARSEOPT_NEGATION,
146 mu_c_string, mu_offsetof(struct mu_parseopt, po_negation) },
147
144 { NULL } 148 { NULL }
145 }; 149 };
146 150
......