1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
#include "Cli/Cli.h"
#include "Logger/Logger.h"
#include "Version/Version.h"
#include <getopt.h>
#include <stdio.h>
void cli_print_usage(const char *program_name) {
fprintf(
stderr,
"Usage:\n"
" %s FILE [-o OUTPUT]\n"
" %s -d DIRECTORY [-o OUTPUT] [-f]\n\n"
"Options:\n"
" -d, --directory DIRECTORY Process a directory recursively\n"
" -o, --output OUTPUT Set the output path\n"
" -f, --overwrite Overwrite an existing output directory\n"
" --include PATTERN Keep entries matching PATTERN\n"
" --exclude PATTERN Drop entries matching PATTERN\n"
" -l, --log-level LEVEL error, warning, info, debug, or silent\n"
" -v, --version Show the program version\n"
" -h, --help Show this help\n",
program_name, program_name);
}
static void cli_print_version(void) { printf("yapssg %s\n", yapssg_version); }
static const char *strip_optional_equals(const char *value) {
return value != NULL && value[0] == '=' ? value + 1 : value;
}
static CliParseResult append_pattern(CliOptions *options, PatternKind kind,
const char *value, const char *name) {
const char *pattern = strip_optional_equals(value);
if (pattern_list_append(&options->patterns, kind, pattern) != 0) {
logger_error("invalid %s pattern '%s'", name, pattern);
return CLI_PARSE_ERROR;
}
return CLI_PARSE_OK;
}
void cli_free_options(CliOptions *options) {
pattern_list_clear(&options->patterns);
}
CliParseResult cli_parse(int argc, char **argv, CliOptions *options) {
static const struct option long_options[] = {
{"directory", required_argument, NULL, 'd'},
{"output", required_argument, NULL, 'o'},
{"overwrite", no_argument, NULL, 'f'},
{"force", no_argument, NULL, 'f'},
{"include", required_argument, NULL, 1},
{"exclude", required_argument, NULL, 2},
{"log-level", required_argument, NULL, 'l'},
{"version", no_argument, NULL, 'v'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}};
const char *directory = NULL;
int option;
options->input_type = INPUT_TYPE_NONE;
options->input_path = NULL;
options->output_path = NULL;
options->overwrite_output = 0;
options->log_level = LOG_LEVEL_INFO;
options->patterns.items = NULL;
options->patterns.length = 0;
options->patterns.capacity = 0;
while ((option = getopt_long(argc, argv, "d:o:fl:vh", long_options, NULL)) !=
-1) {
switch (option) {
case 'd':
directory = strip_optional_equals(optarg);
break;
case 'o':
options->output_path = strip_optional_equals(optarg);
break;
case 'f':
options->overwrite_output = 1;
break;
case 1:
if (append_pattern(options, PATTERN_INCLUDE, optarg, "include") !=
CLI_PARSE_OK) {
return CLI_PARSE_ERROR;
}
break;
case 2:
if (append_pattern(options, PATTERN_EXCLUDE, optarg, "exclude") !=
CLI_PARSE_OK) {
return CLI_PARSE_ERROR;
}
break;
case 'l':
if (logger_parse_level(optarg, &options->log_level) != 0) {
logger_error("unknown log level '%s'", optarg);
return CLI_PARSE_ERROR;
}
break;
case 'v':
cli_print_version();
return CLI_PARSE_VERSION;
case 'h':
cli_print_usage(argv[0]);
return CLI_PARSE_HELP;
default:
cli_print_usage(argv[0]);
return CLI_PARSE_ERROR;
}
}
if (directory != NULL) {
if (optind != argc || directory[0] == '\0') {
logger_error("a directory cannot be combined with a file");
return CLI_PARSE_ERROR;
}
options->input_type = INPUT_TYPE_DIRECTORY;
options->input_path = directory;
} else {
if (optind + 1 != argc) {
cli_print_usage(argv[0]);
return CLI_PARSE_ERROR;
}
options->input_type = INPUT_TYPE_FILE;
options->input_path = argv[optind];
}
if (options->output_path != NULL && options->output_path[0] == '\0') {
logger_error("output path cannot be empty");
return CLI_PARSE_ERROR;
}
return CLI_PARSE_OK;
}
|