@@ -350,14 +350,40 @@ static int is_alias(struct parse_opt_ctx_t *ctx,
350
350
return 0 ;
351
351
}
352
352
353
+ struct parsed_option {
354
+ const struct option * option ;
355
+ enum opt_parsed flags ;
356
+ };
357
+
358
+ static void register_abbrev (struct parse_opt_ctx_t * p ,
359
+ const struct option * option , enum opt_parsed flags ,
360
+ struct parsed_option * abbrev ,
361
+ struct parsed_option * ambiguous )
362
+ {
363
+ if (p -> flags & PARSE_OPT_KEEP_UNKNOWN_OPT )
364
+ return ;
365
+ if (abbrev -> option &&
366
+ !is_alias (p , abbrev -> option , option )) {
367
+ /*
368
+ * If this is abbreviated, it is
369
+ * ambiguous. So when there is no
370
+ * exact match later, we need to
371
+ * error out.
372
+ */
373
+ ambiguous -> option = abbrev -> option ;
374
+ ambiguous -> flags = abbrev -> flags ;
375
+ }
376
+ abbrev -> option = option ;
377
+ abbrev -> flags = flags ;
378
+ }
379
+
353
380
static enum parse_opt_result parse_long_opt (
354
381
struct parse_opt_ctx_t * p , const char * arg ,
355
382
const struct option * options )
356
383
{
357
384
const char * arg_end = strchrnul (arg , '=' );
358
- const struct option * abbrev_option = NULL , * ambiguous_option = NULL ;
359
- enum opt_parsed abbrev_flags = OPT_LONG , ambiguous_flags = OPT_LONG ;
360
- int allow_abbrev = !(p -> flags & PARSE_OPT_KEEP_UNKNOWN_OPT );
385
+ struct parsed_option abbrev = { .option = NULL , .flags = OPT_LONG };
386
+ struct parsed_option ambiguous = { .option = NULL , .flags = OPT_LONG };
361
387
362
388
for (; options -> type != OPTION_END ; options ++ ) {
363
389
const char * rest , * long_name = options -> long_name ;
@@ -377,44 +403,33 @@ static enum parse_opt_result parse_long_opt(
377
403
rest = NULL ;
378
404
if (!rest ) {
379
405
/* abbreviated? */
380
- if (allow_abbrev &&
381
- !strncmp (long_name , arg , arg_end - arg )) {
382
- is_abbreviated :
383
- if (abbrev_option &&
384
- !is_alias (p , abbrev_option , options )) {
385
- /*
386
- * If this is abbreviated, it is
387
- * ambiguous. So when there is no
388
- * exact match later, we need to
389
- * error out.
390
- */
391
- ambiguous_option = abbrev_option ;
392
- ambiguous_flags = abbrev_flags ;
393
- }
394
- abbrev_option = options ;
395
- abbrev_flags = flags ^ opt_flags ;
406
+ if (!strncmp (long_name , arg , arg_end - arg )) {
407
+ register_abbrev (p , options , flags ^ opt_flags ,
408
+ & abbrev , & ambiguous );
396
409
continue ;
397
410
}
398
411
/* negation allowed? */
399
412
if (options -> flags & PARSE_OPT_NONEG )
400
413
continue ;
401
414
/* negated and abbreviated very much? */
402
- if (allow_abbrev && starts_with ("no-" , arg )) {
415
+ if (starts_with ("no-" , arg )) {
403
416
flags |= OPT_UNSET ;
404
- goto is_abbreviated ;
417
+ register_abbrev (p , options , flags ^ opt_flags ,
418
+ & abbrev , & ambiguous );
419
+ continue ;
405
420
}
406
421
/* negated? */
407
422
if (!starts_with (arg , "no-" ))
408
423
continue ;
409
424
flags |= OPT_UNSET ;
410
425
if (!skip_prefix (arg + 3 , long_name , & rest )) {
411
426
/* abbreviated and negated? */
412
- if (allow_abbrev &&
413
- !strncmp (long_name , arg + 3 ,
427
+ if (!strncmp (long_name , arg + 3 ,
414
428
arg_end - arg - 3 ))
415
- goto is_abbreviated ;
416
- else
417
- continue ;
429
+ register_abbrev (p , options ,
430
+ flags ^ opt_flags ,
431
+ & abbrev , & ambiguous );
432
+ continue ;
418
433
}
419
434
}
420
435
if (* rest ) {
@@ -425,24 +440,24 @@ static enum parse_opt_result parse_long_opt(
425
440
return get_value (p , options , flags ^ opt_flags );
426
441
}
427
442
428
- if (disallow_abbreviated_options && (ambiguous_option || abbrev_option ))
443
+ if (disallow_abbreviated_options && (ambiguous . option || abbrev . option ))
429
444
die ("disallowed abbreviated or ambiguous option '%.*s'" ,
430
445
(int )(arg_end - arg ), arg );
431
446
432
- if (ambiguous_option ) {
447
+ if (ambiguous . option ) {
433
448
error (_ ("ambiguous option: %s "
434
449
"(could be --%s%s or --%s%s)" ),
435
450
arg ,
436
- (ambiguous_flags & OPT_UNSET ) ? "no-" : "" ,
437
- ambiguous_option -> long_name ,
438
- (abbrev_flags & OPT_UNSET ) ? "no-" : "" ,
439
- abbrev_option -> long_name );
451
+ (ambiguous . flags & OPT_UNSET ) ? "no-" : "" ,
452
+ ambiguous . option -> long_name ,
453
+ (abbrev . flags & OPT_UNSET ) ? "no-" : "" ,
454
+ abbrev . option -> long_name );
440
455
return PARSE_OPT_HELP ;
441
456
}
442
- if (abbrev_option ) {
457
+ if (abbrev . option ) {
443
458
if (* arg_end )
444
459
p -> opt = arg_end + 1 ;
445
- return get_value (p , abbrev_option , abbrev_flags );
460
+ return get_value (p , abbrev . option , abbrev . flags );
446
461
}
447
462
return PARSE_OPT_UNKNOWN ;
448
463
}
0 commit comments