bin-refactor: Add parse_options generic method
This commit is contained in:
parent
c8ae964a56
commit
5368b35153
1 changed files with 69 additions and 7 deletions
76
bin/common.h
76
bin/common.h
|
@ -11,7 +11,8 @@
|
||||||
#define count_of(arr) (sizeof(arr)/sizeof(0[arr]))
|
#define count_of(arr) (sizeof(arr)/sizeof(0[arr]))
|
||||||
|
|
||||||
int
|
int
|
||||||
parseint(const char *string, long *result) {
|
parseint(const char *string, long *result)
|
||||||
|
{
|
||||||
char *end;
|
char *end;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
*result = strtol(string, &end, 10);
|
*result = strtol(string, &end, 10);
|
||||||
|
@ -19,7 +20,8 @@ parseint(const char *string, long *result) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
strprefix(const char *str, const char *prefix) {
|
strprefix(const char *str, const char *prefix)
|
||||||
|
{
|
||||||
while (*prefix) {
|
while (*prefix) {
|
||||||
if (!(*str && *str == *prefix)) return 0;
|
if (!(*str && *str == *prefix)) return 0;
|
||||||
prefix++; str++;
|
prefix++; str++;
|
||||||
|
@ -28,7 +30,8 @@ strprefix(const char *str, const char *prefix) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
print_option(char short_opt, const char *long_opt, const char *description) {
|
print_option(char short_opt, const char *long_opt, const char *description)
|
||||||
|
{
|
||||||
if (short_opt)
|
if (short_opt)
|
||||||
printf(" -%c, ", short_opt);
|
printf(" -%c, ", short_opt);
|
||||||
else
|
else
|
||||||
|
@ -38,8 +41,67 @@ print_option(char short_opt, const char *long_opt, const char *description) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
print_version() {
|
print_version()
|
||||||
int major, minor, revision;
|
{
|
||||||
hoedown_version(&major, &minor, &revision);
|
printf("Built with Hoedown " HOEDOWN_VERSION ".\n");
|
||||||
printf("Built with Hoedown v%d.%d.%d.\n", major, minor, revision);
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
parse_options(
|
||||||
|
int argc, char **argv,
|
||||||
|
int(*parse_short_option)(char opt, char *next, void *opaque),
|
||||||
|
int(*parse_long_option)(char *opt, char *next, void *opaque),
|
||||||
|
int(*parse_argument)(int argn, char *arg, int is_forced, void *opaque),
|
||||||
|
void *opaque)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
int i = 1, regular_args = 0;
|
||||||
|
|
||||||
|
/* Parse options mixed with arguments */
|
||||||
|
while (i < argc) {
|
||||||
|
char *arg = argv[i];
|
||||||
|
|
||||||
|
if (arg[0] == '-' && arg[1]) {
|
||||||
|
char *next_arg = (i+1 < argc) ? argv[i+1] : NULL;
|
||||||
|
|
||||||
|
if (arg[1] == '-' && !arg[2]) {
|
||||||
|
/* '--' signals end of options */
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg[1] == '-') {
|
||||||
|
/* Long option */
|
||||||
|
result = parse_long_option(arg + 2, next_arg, opaque);
|
||||||
|
if (!result) return 0;
|
||||||
|
i += result;
|
||||||
|
} else {
|
||||||
|
/* Sequence of short options */
|
||||||
|
size_t pos;
|
||||||
|
for (pos = 1; arg[pos]; pos++) {
|
||||||
|
char *next = (arg[pos+1]) ? arg + pos+1 : next_arg;
|
||||||
|
result = parse_short_option(arg[pos], next, opaque);
|
||||||
|
if (!result) return 0;
|
||||||
|
if (result == 2) {
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Argument */
|
||||||
|
result = parse_argument(regular_args++, arg, 0, opaque);
|
||||||
|
if (!result) return 0;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse rest as forced arguments */
|
||||||
|
while (i < argc) {
|
||||||
|
parse_argument(regular_args++, argv[i], 1, opaque);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue