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
|
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "tools/cmdline.h"
#include <memory>
#include <string>
namespace jpegxl {
namespace tools {
void CommandLineParser::PrintHelp() const {
// Use stdout, not stderr, so help can easily be grepped.
FILE* out = stdout;
fprintf(out, "Usage: %s", program_name_ ? program_name_ : "command");
for (const auto& option : options_) {
if (option->positional()) {
if (option->verbosity_level() > verbosity) continue;
if (option->required()) {
fprintf(out, " %s", option->help_flags().c_str());
} else {
fprintf(out, " [%s]", option->help_flags().c_str());
}
}
}
fprintf(out, " [OPTIONS...]\n");
bool showed_all = true;
for (const auto& option : options_) {
if (option->verbosity_level() > verbosity) {
showed_all = false;
continue;
}
fprintf(out, " %s\n", option->help_flags().c_str());
const char* help_text = option->help_text();
if (help_text) {
fprintf(out, " %s\n", help_text);
}
}
fprintf(out, " -h, --help\n Prints this help message%s.\n",
(showed_all ? "" : " (use -v to see more options)"));
}
bool CommandLineParser::Parse(int argc, const char* argv[]) {
if (argc) program_name_ = argv[0];
int i = 1; // argv[0] is the program name.
// if false, stop matching options and take only positional arguments
bool parse_options = true;
while (i < argc) {
if (!strcmp("-h", argv[i]) || !strcmp("--help", argv[i])) {
help_ = true;
i++;
continue;
}
if (!strcmp("-v", argv[i]) || !strcmp("--verbose", argv[i])) {
verbosity++;
}
// after "--", filenames starting with "-" can be used
if (!strcmp("--", argv[i])) {
parse_options = false;
i++;
continue;
}
// special case: "-" is a filename denoting stdin or stdout
bool parse_this_option = true;
if (!strcmp("-", argv[i])) {
parse_this_option = false;
}
bool found = false;
for (const auto& option : options_) {
if (option->Match(argv[i], parse_options && parse_this_option)) {
// Parsing advances the value i on success.
const char* arg = argv[i];
if (!option->Parse(argc, argv, &i)) {
fprintf(stderr, "Error parsing flag %s\n", arg);
return false;
}
found = true;
break;
}
}
if (!found) {
// No option matched argv[i].
fprintf(stderr, "Unknown argument: %s\n", argv[i]);
return false;
}
}
return true;
}
} // namespace tools
} // namespace jpegxl
|