1 #include "git-compat-util.h"
2 #include "parse-options.h"
14 static inline const char *get_arg(struct optparse_t
*p
)
17 const char *res
= p
->opt
;
25 static inline const char *skip_prefix(const char *str
, const char *prefix
)
27 size_t len
= strlen(prefix
);
28 return strncmp(str
, prefix
, len
) ? NULL
: str
+ len
;
31 static int opterror(const struct option
*opt
, const char *reason
, int flags
)
33 if (flags
& OPT_SHORT
)
34 return error("switch `%c' %s", opt
->short_name
, reason
);
35 if (flags
& OPT_UNSET
)
36 return error("option `no-%s' %s", opt
->long_name
, reason
);
37 return error("option `%s' %s", opt
->long_name
, reason
);
40 static int get_value(struct optparse_t
*p
,
41 const struct option
*opt
, int flags
)
45 if (p
->opt
&& (flags
& OPT_UNSET
))
46 return opterror(opt
, "takes no value", flags
);
50 if (!(flags
& OPT_SHORT
) && p
->opt
)
51 return opterror(opt
, "takes no value", flags
);
52 if (flags
& OPT_UNSET
)
53 *(int *)opt
->value
= 0;
55 (*(int *)opt
->value
)++;
59 if (flags
& OPT_UNSET
) {
60 *(const char **)opt
->value
= (const char *)NULL
;
63 if (!p
->opt
&& p
->argc
<= 1)
64 return opterror(opt
, "requires a value", flags
);
65 *(const char **)opt
->value
= get_arg(p
);
69 if (flags
& OPT_UNSET
) {
70 *(int *)opt
->value
= 0;
73 if (!p
->opt
&& p
->argc
<= 1)
74 return opterror(opt
, "requires a value", flags
);
75 *(int *)opt
->value
= strtol(get_arg(p
), (char **)&s
, 10);
77 return opterror(opt
, "expects a numerical value", flags
);
81 die("should not happen, someone must be hit on the forehead");
85 static int parse_short_opt(struct optparse_t
*p
, const struct option
*options
)
87 for (; options
->type
!= OPTION_END
; options
++) {
88 if (options
->short_name
== *p
->opt
) {
89 p
->opt
= p
->opt
[1] ? p
->opt
+ 1 : NULL
;
90 return get_value(p
, options
, OPT_SHORT
);
93 return error("unknown switch `%c'", *p
->opt
);
96 static int parse_long_opt(struct optparse_t
*p
, const char *arg
,
97 const struct option
*options
)
99 for (; options
->type
!= OPTION_END
; options
++) {
103 if (!options
->long_name
)
106 rest
= skip_prefix(arg
, options
->long_name
);
108 if (strncmp(arg
, "no-", 3))
111 rest
= skip_prefix(arg
+ 3, options
->long_name
);
120 return get_value(p
, options
, flags
);
122 return error("unknown option `%s'", arg
);
125 int parse_options(int argc
, const char **argv
, const struct option
*options
,
126 const char *usagestr
, int flags
)
128 struct optparse_t args
= { argv
+ 1, argc
- 1, NULL
};
131 for (; args
.argc
; args
.argc
--, args
.argv
++) {
132 const char *arg
= args
.argv
[0];
134 if (*arg
!= '-' || !arg
[1]) {
135 argv
[j
++] = args
.argv
[0];
142 if (*args
.opt
== 'h')
144 if (parse_short_opt(&args
, options
) < 0)
150 if (!arg
[2]) { /* "--" */
151 if (!(flags
& PARSE_OPT_KEEP_DASHDASH
)) {
158 if (!strcmp(arg
+ 2, "help"))
160 if (parse_long_opt(&args
, arg
+ 2, options
))
164 memmove(argv
+ j
, args
.argv
, args
.argc
* sizeof(*argv
));
165 argv
[j
+ args
.argc
] = NULL
;
166 return j
+ args
.argc
;