diff options
| author | Rutger Broekhoff | 2024-05-02 20:27:40 +0200 |
|---|---|---|
| committer | Rutger Broekhoff | 2024-05-02 20:27:40 +0200 |
| commit | 17a3ea880402338420699e03bcb24181e4ff3924 (patch) | |
| tree | da666ef91e0b60d20aa0b01529644c136fd1f4ab /src/querykv1/cliopts.cpp | |
| download | oeuf-17a3ea880402338420699e03bcb24181e4ff3924.tar.gz oeuf-17a3ea880402338420699e03bcb24181e4ff3924.zip | |
Initial commit
Based on dc4ba6a
Diffstat (limited to 'src/querykv1/cliopts.cpp')
| -rw-r--r-- | src/querykv1/cliopts.cpp | 456 |
1 files changed, 456 insertions, 0 deletions
diff --git a/src/querykv1/cliopts.cpp b/src/querykv1/cliopts.cpp new file mode 100644 index 0000000..bef7a98 --- /dev/null +++ b/src/querykv1/cliopts.cpp | |||
| @@ -0,0 +1,456 @@ | |||
| 1 | // vim:set sw=2 ts=2 sts et: | ||
| 2 | |||
| 3 | #include <cstdlib> | ||
| 4 | #include <cstdio> | ||
| 5 | #include <string> | ||
| 6 | #include <string_view> | ||
| 7 | |||
| 8 | #include <getopt.h> | ||
| 9 | |||
| 10 | #include "cliopts.hpp" | ||
| 11 | |||
| 12 | using namespace std::string_view_literals; | ||
| 13 | |||
| 14 | const char *opt_set = ""; | ||
| 15 | const char *opt_unset = nullptr; | ||
| 16 | |||
| 17 | const char help[] = R"(Usage: %1$s [OPTIONS] <COMMAND> | ||
| 18 | |||
| 19 | Global Options: | ||
| 20 | --kv1 <PATH> Path to file containing all KV1 data, '-' for stdin | ||
| 21 | -h, --help Print this help | ||
| 22 | |||
| 23 | Commands: | ||
| 24 | joparoute Generate CSV for journey pattern route | ||
| 25 | journeyinfo Print some information on a journey | ||
| 26 | journeyroute Generate CSV for journey route | ||
| 27 | journeys List journeys of a specific line going from stop A to B | ||
| 28 | schedule Generate schedule | ||
| 29 | )"; | ||
| 30 | |||
| 31 | const char joparoute_help[] = R"(Usage: %1$s joparoute --line <NUMBER> --jopa <CODE> [OPTIONS] | ||
| 32 | |||
| 33 | Options: | ||
| 34 | --line <NUMBER> Line planning number as in schedule | ||
| 35 | --jopa <CODE> Journey pattern code as in KV1 data | ||
| 36 | -o <PATH> Path of file to write to, '-' for stdout | ||
| 37 | |||
| 38 | Global Options: | ||
| 39 | --kv1 <PATH> Path to file containing all KV1 data, '-' for stdin | ||
| 40 | -h, --help Print this help | ||
| 41 | )"; | ||
| 42 | |||
| 43 | const char journeyroute_help[] = R"(Usage: %1$s journeyroute --line <NUMBER> [OPTIONS] | ||
| 44 | |||
| 45 | Options: | ||
| 46 | --line <NUMBER> Line planning number as in KV1 data | ||
| 47 | --journey <NUMBER> Journey number as in KV1 data | ||
| 48 | -o <PATH> Path of file to write to, '-' for stdout | ||
| 49 | |||
| 50 | Global Options: | ||
| 51 | --kv1 <PATH> Path to file containing all KV1 data, '-' for stdin | ||
| 52 | -h, --help Print this help | ||
| 53 | )"; | ||
| 54 | |||
| 55 | const char journeys_help[] = R"(Usage: %1$s journeys --line <NUMBER> --begin <STOP> --end <STOP> [OPTIONS] | ||
| 56 | |||
| 57 | For the --begin and --end arguments, use the following format: | ||
| 58 | --begin/--end stop:<USRSTOP CODE> | ||
| 59 | --begin/--end star:<USRSTAR CODE> | ||
| 60 | |||
| 61 | Options: | ||
| 62 | --begin <STOP> User stop code/area of stop the journey should begin at | ||
| 63 | --end <STOP> User stop code/area of stop the journey should end at | ||
| 64 | --line <NUMBER> Line planning number to filter on | ||
| 65 | -o <PATH> Path of file to write to, '-' for stdout | ||
| 66 | |||
| 67 | Global Options: | ||
| 68 | --kv1 <PATH> Path to file containing all KV1 data, '-' for stdin | ||
| 69 | -h, --help Print this help | ||
| 70 | )"; | ||
| 71 | |||
| 72 | const char journeyinfo_help[] = R"(Usage: %1$s journeyinfo --line <NUMBER> --journey <NUMBER> [OPTIONS] | ||
| 73 | |||
| 74 | Options: | ||
| 75 | --line <NUMBER> Line planning number to filter on | ||
| 76 | --journey <NUMBER> Journey number as in schedule | ||
| 77 | |||
| 78 | Global Options: | ||
| 79 | --kv1 <PATH> Path to file containing all KV1 data, '-' for stdin | ||
| 80 | -h, --help Print this help | ||
| 81 | )"; | ||
| 82 | |||
| 83 | const char schedule_help[] = R"(Usage: %1$s schedule --line <NUMBER> [OPTIONS] | ||
| 84 | |||
| 85 | Options: | ||
| 86 | --line <NUMBER> Line planning number to generate schedule for | ||
| 87 | -o <PATH> Path of file to write to, '-' for stdout | ||
| 88 | |||
| 89 | Global Options: | ||
| 90 | --kv1 <PATH> Path to file containing all KV1 data, '-' for stdin | ||
| 91 | -h, --help Print this help | ||
| 92 | )"; | ||
| 93 | |||
| 94 | void journeyRouteValidateOptions(const char *progname, Options *options) { | ||
| 95 | #define X(name, argument, long_, short_) \ | ||
| 96 | if (#name != "kv1_file_path"sv && #name != "line_planning_number"sv \ | ||
| 97 | && #name != "journey_number"sv && #name != "help"sv && #name != "output_file_path"sv) \ | ||
| 98 | if (options->name) { \ | ||
| 99 | if (long_) { \ | ||
| 100 | if (short_) fprintf(stderr, "%s: unexpected flag --%s (-%c) for journeyroute subcommand\n\n", progname, static_cast<const char *>(long_), short_); \ | ||
| 101 | else fprintf(stderr, "%s: unexpected flag --%s for journeyroute subcommand\n\n", progname, static_cast<const char *>(long_)); \ | ||
| 102 | } else if (short_) fprintf(stderr, "%s: unexpected flag -%c for journeyroute subcommand\n\n", progname, short_); \ | ||
| 103 | fprintf(stderr, journeyroute_help, progname); \ | ||
| 104 | exit(1); \ | ||
| 105 | } | ||
| 106 | LONG_OPTIONS | ||
| 107 | SHORT_OPTIONS | ||
| 108 | #undef X | ||
| 109 | |||
| 110 | if (options->positional.size() > 0) { | ||
| 111 | fprintf(stderr, "%s: unexpected positional argument(s) for journeyroute subcommand\n\n", progname); | ||
| 112 | for (auto pos : options->positional) fprintf(stderr, "opt: %s\n", pos); | ||
| 113 | fprintf(stderr, journeyroute_help, progname); | ||
| 114 | exit(1); | ||
| 115 | } | ||
| 116 | |||
| 117 | if (!options->kv1_file_path) | ||
| 118 | options->kv1_file_path = "-"; | ||
| 119 | if (!options->output_file_path) | ||
| 120 | options->output_file_path = "-"; | ||
| 121 | if (options->kv1_file_path == ""sv) { | ||
| 122 | fprintf(stderr, "%s: KV1 file path cannot be empty\n\n", progname); | ||
| 123 | fprintf(stderr, journeyroute_help, progname); | ||
| 124 | exit(1); | ||
| 125 | } | ||
| 126 | if (options->output_file_path == ""sv) { | ||
| 127 | fprintf(stderr, "%s: output file path cannot be empty\n\n", progname); | ||
| 128 | fprintf(stderr, journeyroute_help, progname); | ||
| 129 | exit(1); | ||
| 130 | } | ||
| 131 | if (!options->journey_number || options->journey_number == ""sv) { | ||
| 132 | fprintf(stderr, "%s: journey number must be provided\n\n", progname); | ||
| 133 | fprintf(stderr, journeyroute_help, progname); | ||
| 134 | exit(1); | ||
| 135 | } | ||
| 136 | if (!options->line_planning_number || options->line_planning_number == ""sv) { | ||
| 137 | fprintf(stderr, "%s: line planning number must be provided\n\n", progname); | ||
| 138 | fprintf(stderr, journeyroute_help, progname); | ||
| 139 | exit(1); | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | void scheduleValidateOptions(const char *progname, Options *options) { | ||
| 144 | #define X(name, argument, long_, short_) \ | ||
| 145 | if (#name != "kv1_file_path"sv && #name != "help"sv \ | ||
| 146 | && #name != "line_planning_number"sv && #name != "output_file_path"sv) \ | ||
| 147 | if (options->name) { \ | ||
| 148 | if (long_) { \ | ||
| 149 | if (short_) fprintf(stderr, "%s: unexpected flag --%s (-%c) for schedule subcommand\n\n", progname, static_cast<const char *>(long_), short_); \ | ||
| 150 | else fprintf(stderr, "%s: unexpected flag --%s for schedule subcommand\n\n", progname, static_cast<const char *>(long_)); \ | ||
| 151 | } else if (short_) fprintf(stderr, "%s: unexpected flag -%c for schedule subcommand\n\n", progname, short_); \ | ||
| 152 | fprintf(stderr, schedule_help, progname); \ | ||
| 153 | exit(1); \ | ||
| 154 | } | ||
| 155 | LONG_OPTIONS | ||
| 156 | SHORT_OPTIONS | ||
| 157 | #undef X | ||
| 158 | |||
| 159 | if (options->positional.size() > 0) { | ||
| 160 | fprintf(stderr, "%s: unexpected positional argument(s) for schedule subcommand\n\n", progname); | ||
| 161 | for (auto pos : options->positional) fprintf(stderr, "opt: %s\n", pos); | ||
| 162 | fprintf(stderr, schedule_help, progname); | ||
| 163 | exit(1); | ||
| 164 | } | ||
| 165 | |||
| 166 | if (!options->kv1_file_path) | ||
| 167 | options->kv1_file_path = "-"; | ||
| 168 | if (!options->output_file_path) | ||
| 169 | options->output_file_path = "-"; | ||
| 170 | if (options->kv1_file_path == ""sv) { | ||
| 171 | fprintf(stderr, "%s: KV1 file path cannot be empty\n\n", progname); | ||
| 172 | fprintf(stderr, schedule_help, progname); | ||
| 173 | exit(1); | ||
| 174 | } | ||
| 175 | if (options->output_file_path == ""sv) { | ||
| 176 | fprintf(stderr, "%s: output file path cannot be empty\n\n", progname); | ||
| 177 | fprintf(stderr, schedule_help, progname); | ||
| 178 | exit(1); | ||
| 179 | } | ||
| 180 | if (!options->line_planning_number || options->line_planning_number == ""sv) { | ||
| 181 | fprintf(stderr, "%s: line planning number must be provided\n\n", progname); | ||
| 182 | fprintf(stderr, schedule_help, progname); | ||
| 183 | exit(1); | ||
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 187 | void journeysValidateOptions(const char *progname, Options *options) { | ||
| 188 | #define X(name, argument, long_, short_) \ | ||
| 189 | if (#name != "kv1_file_path"sv && #name != "help"sv \ | ||
| 190 | && #name != "line_planning_number"sv && #name != "output_file_path"sv \ | ||
| 191 | && #name != "begin_stop_code"sv && #name != "end_stop_code"sv) \ | ||
| 192 | if (options->name) { \ | ||
| 193 | if (long_) { \ | ||
| 194 | if (short_) fprintf(stderr, "%s: unexpected flag --%s (-%c) for journeys subcommand\n\n", progname, static_cast<const char *>(long_), short_); \ | ||
| 195 | else fprintf(stderr, "%s: unexpected flag --%s for journeys subcommand\n\n", progname, static_cast<const char *>(long_)); \ | ||
| 196 | } else if (short_) fprintf(stderr, "%s: unexpected flag -%c for journeys subcommand\n\n", progname, short_); \ | ||
| 197 | fprintf(stderr, journeys_help, progname); \ | ||
| 198 | exit(1); \ | ||
| 199 | } | ||
| 200 | LONG_OPTIONS | ||
| 201 | SHORT_OPTIONS | ||
| 202 | #undef X | ||
| 203 | |||
| 204 | if (options->positional.size() > 0) { | ||
| 205 | fprintf(stderr, "%s: unexpected positional argument(s) for journeys subcommand\n\n", progname); | ||
| 206 | for (auto pos : options->positional) fprintf(stderr, "opt: %s\n", pos); | ||
| 207 | fprintf(stderr, journeys_help, progname); | ||
| 208 | exit(1); | ||
| 209 | } | ||
| 210 | |||
| 211 | if (!options->kv1_file_path) | ||
| 212 | options->kv1_file_path = "-"; | ||
| 213 | if (!options->output_file_path) | ||
| 214 | options->output_file_path = "-"; | ||
| 215 | if (options->kv1_file_path == ""sv) { | ||
| 216 | fprintf(stderr, "%s: KV1 file path cannot be empty\n\n", progname); | ||
| 217 | fprintf(stderr, journeys_help, progname); | ||
| 218 | exit(1); | ||
| 219 | } | ||
| 220 | if (options->output_file_path == ""sv) { | ||
| 221 | fprintf(stderr, "%s: output file path cannot be empty\n\n", progname); | ||
| 222 | fprintf(stderr, journeys_help, progname); | ||
| 223 | exit(1); | ||
| 224 | } | ||
| 225 | if (!options->line_planning_number || options->line_planning_number == ""sv) { | ||
| 226 | fprintf(stderr, "%s: line planning number must be provided\n\n", progname); | ||
| 227 | fprintf(stderr, journeys_help, progname); | ||
| 228 | exit(1); | ||
| 229 | } | ||
| 230 | if (!options->begin_stop_code || options->begin_stop_code == ""sv) { | ||
| 231 | fprintf(stderr, "%s: start user stop code must be provided\n\n", progname); | ||
| 232 | fprintf(stderr, journeys_help, progname); | ||
| 233 | exit(1); | ||
| 234 | } | ||
| 235 | if (!options->end_stop_code || options->end_stop_code == ""sv) { | ||
| 236 | fprintf(stderr, "%s: end user stop code must be provided\n\n", progname); | ||
| 237 | fprintf(stderr, journeys_help, progname); | ||
| 238 | exit(1); | ||
| 239 | } | ||
| 240 | if (!std::string_view(options->begin_stop_code).starts_with("star:") | ||
| 241 | && !std::string_view(options->begin_stop_code).starts_with("stop:")) { | ||
| 242 | fprintf(stderr, "%s: begin user stop code must be prefixed with star:/stop:\n\n", progname); | ||
| 243 | fprintf(stderr, journeys_help, progname); | ||
| 244 | exit(1); | ||
| 245 | } | ||
| 246 | if (!std::string_view(options->end_stop_code).starts_with("star:") | ||
| 247 | && !std::string_view(options->end_stop_code).starts_with("stop:")) { | ||
| 248 | fprintf(stderr, "%s: end user stop code must be prefixed with star:/stop:\n\n", progname); | ||
| 249 | fprintf(stderr, journeys_help, progname); | ||
| 250 | exit(1); | ||
| 251 | } | ||
| 252 | } | ||
| 253 | |||
| 254 | void journeyInfoValidateOptions(const char *progname, Options *options) { | ||
| 255 | #define X(name, argument, long_, short_) \ | ||
| 256 | if (#name != "kv1_file_path"sv && #name != "line_planning_number"sv \ | ||
| 257 | && #name != "journey_number"sv && #name != "help"sv) \ | ||
| 258 | if (options->name) { \ | ||
| 259 | if (long_) { \ | ||
| 260 | if (short_) fprintf(stderr, "%s: unexpected flag --%s (-%c) for journeyinfo subcommand\n\n", progname, static_cast<const char *>(long_), short_); \ | ||
| 261 | else fprintf(stderr, "%s: unexpected flag --%s for journeyinfo subcommand\n\n", progname, static_cast<const char *>(long_)); \ | ||
| 262 | } else if (short_) fprintf(stderr, "%s: unexpected flag -%c for journeyinfo subcommand\n\n", progname, short_); \ | ||
| 263 | fprintf(stderr, journeyinfo_help, progname); \ | ||
| 264 | exit(1); \ | ||
| 265 | } | ||
| 266 | LONG_OPTIONS | ||
| 267 | SHORT_OPTIONS | ||
| 268 | #undef X | ||
| 269 | |||
| 270 | if (options->positional.size() > 0) { | ||
| 271 | fprintf(stderr, "%s: unexpected positional argument(s) for journeyinfo subcommand\n\n", progname); | ||
| 272 | for (auto pos : options->positional) fprintf(stderr, "opt: %s\n", pos); | ||
| 273 | fprintf(stderr, journeyinfo_help, progname); | ||
| 274 | exit(1); | ||
| 275 | } | ||
| 276 | |||
| 277 | if (!options->kv1_file_path) | ||
| 278 | options->kv1_file_path = "-"; | ||
| 279 | if (options->kv1_file_path == ""sv) { | ||
| 280 | fprintf(stderr, "%s: KV1 file path cannot be empty\n\n", progname); | ||
| 281 | fprintf(stderr, journeyinfo_help, progname); | ||
| 282 | exit(1); | ||
| 283 | } | ||
| 284 | if (!options->journey_number || options->journey_number == ""sv) { | ||
| 285 | fprintf(stderr, "%s: journey number must be provided\n\n", progname); | ||
| 286 | fprintf(stderr, journeyinfo_help, progname); | ||
| 287 | exit(1); | ||
| 288 | } | ||
| 289 | if (!options->line_planning_number || options->line_planning_number == ""sv) { | ||
| 290 | fprintf(stderr, "%s: line planning number must be provided\n\n", progname); | ||
| 291 | fprintf(stderr, journeyinfo_help, progname); | ||
| 292 | exit(1); | ||
| 293 | } | ||
| 294 | } | ||
| 295 | |||
| 296 | void jopaRouteValidateOptions(const char *progname, Options *options) { | ||
| 297 | #define X(name, argument, long_, short_) \ | ||
| 298 | if (#name != "kv1_file_path"sv && #name != "line_planning_number"sv \ | ||
| 299 | && #name != "journey_pattern_code"sv && #name != "help"sv && #name != "output_file_path"sv) \ | ||
| 300 | if (options->name) { \ | ||
| 301 | if (long_) { \ | ||
| 302 | if (short_) fprintf(stderr, "%s: unexpected flag --%s (-%c) for joparoute subcommand\n\n", progname, static_cast<const char *>(long_), short_); \ | ||
| 303 | else fprintf(stderr, "%s: unexpected flag --%s for joparoute subcommand\n\n", progname, static_cast<const char *>(long_)); \ | ||
| 304 | } else if (short_) fprintf(stderr, "%s: unexpected flag -%c for joparoute subcommand\n\n", progname, short_); \ | ||
| 305 | fprintf(stderr, joparoute_help, progname); \ | ||
| 306 | exit(1); \ | ||
| 307 | } | ||
| 308 | LONG_OPTIONS | ||
| 309 | SHORT_OPTIONS | ||
| 310 | #undef X | ||
| 311 | |||
| 312 | if (options->positional.size() > 0) { | ||
| 313 | fprintf(stderr, "%s: unexpected positional argument(s) for joparoute subcommand\n\n", progname); | ||
| 314 | for (auto pos : options->positional) fprintf(stderr, "opt: %s\n", pos); | ||
| 315 | fprintf(stderr, joparoute_help, progname); | ||
| 316 | exit(1); | ||
| 317 | } | ||
| 318 | |||
| 319 | if (!options->kv1_file_path) | ||
| 320 | options->kv1_file_path = "-"; | ||
| 321 | if (!options->output_file_path) | ||
| 322 | options->output_file_path = "-"; | ||
| 323 | if (options->kv1_file_path == ""sv) { | ||
| 324 | fprintf(stderr, "%s: KV1 file path cannot be empty\n\n", progname); | ||
| 325 | fprintf(stderr, joparoute_help, progname); | ||
| 326 | exit(1); | ||
| 327 | } | ||
| 328 | if (options->output_file_path == ""sv) { | ||
| 329 | fprintf(stderr, "%s: output file path cannot be empty\n\n", progname); | ||
| 330 | fprintf(stderr, joparoute_help, progname); | ||
| 331 | exit(1); | ||
| 332 | } | ||
| 333 | if (!options->journey_pattern_code || options->journey_pattern_code == ""sv) { | ||
| 334 | fprintf(stderr, "%s: journey pattern code must be provided\n\n", progname); | ||
| 335 | fprintf(stderr, joparoute_help, progname); | ||
| 336 | exit(1); | ||
| 337 | } | ||
| 338 | if (!options->line_planning_number || options->line_planning_number == ""sv) { | ||
| 339 | fprintf(stderr, "%s: line planning number must be provided\n\n", progname); | ||
| 340 | fprintf(stderr, joparoute_help, progname); | ||
| 341 | exit(1); | ||
| 342 | } | ||
| 343 | } | ||
| 344 | |||
| 345 | struct ShortFlag { | ||
| 346 | int has_arg; | ||
| 347 | int c; | ||
| 348 | }; | ||
| 349 | |||
| 350 | template<ShortFlag ...flags> | ||
| 351 | const std::string mkargarr = | ||
| 352 | (std::string() | ||
| 353 | + ... | ||
| 354 | + (flags.c == 0 | ||
| 355 | ? "" | ||
| 356 | : std::string((const char[]){ flags.c, '\0' }) | ||
| 357 | + (flags.has_arg == required_argument | ||
| 358 | ? ":" | ||
| 359 | : flags.has_arg == optional_argument | ||
| 360 | ? "::" | ||
| 361 | : ""))); | ||
| 362 | |||
| 363 | #define X(name, has_arg, long_, short_) ShortFlag(has_arg, short_), | ||
| 364 | const std::string argarr = mkargarr<SHORT_OPTIONS LONG_OPTIONS ShortFlag(no_argument, 0)>; | ||
| 365 | #undef X | ||
| 366 | |||
| 367 | Options parseOptions(int argc, char *argv[]) { | ||
| 368 | const char *progname = argv[0]; | ||
| 369 | |||
| 370 | // Struct with options for augmentkv6. | ||
| 371 | Options options; | ||
| 372 | |||
| 373 | static option long_options[] = { | ||
| 374 | #define X(name, argument, long_, short_) { long_, argument, nullptr, short_ }, | ||
| 375 | LONG_OPTIONS | ||
| 376 | #undef X | ||
| 377 | { 0 }, | ||
| 378 | }; | ||
| 379 | |||
| 380 | int c; | ||
| 381 | int option_index = 0; | ||
| 382 | bool error = false; | ||
| 383 | while ((c = getopt_long(argc, argv, argarr.c_str(), long_options, &option_index)) != -1) { | ||
| 384 | // If a long option was used, c corresponds with val. We have val = 0 for | ||
| 385 | // options which have no short alternative, so checking for c = 0 gives us | ||
| 386 | // whether a long option with no short alternative was used. | ||
| 387 | // Below, we check for c = 'h', which corresponds with the long option | ||
| 388 | // '--help', for which val = 'h'. | ||
| 389 | if (c == 0) { | ||
| 390 | const char *name = long_options[option_index].name; | ||
| 391 | #define X(opt_name, opt_has_arg, opt_long, opt_short) \ | ||
| 392 | if (name == opt_long ## sv) { options.opt_name = optarg; continue; } | ||
| 393 | LONG_OPTIONS | ||
| 394 | #undef X | ||
| 395 | error = true; | ||
| 396 | } | ||
| 397 | #define X(opt_name, opt_has_arg, opt_long, opt_short) \ | ||
| 398 | if (c == opt_short) { options.opt_name = optarg ? optarg : opt_set; continue; } | ||
| 399 | LONG_OPTIONS | ||
| 400 | SHORT_OPTIONS | ||
| 401 | #undef X | ||
| 402 | error = true; | ||
| 403 | } | ||
| 404 | |||
| 405 | if (optind < argc) | ||
| 406 | options.subcommand = argv[optind++]; | ||
| 407 | while (optind < argc) | ||
| 408 | options.positional.push_back(argv[optind++]); | ||
| 409 | |||
| 410 | if (options.subcommand | ||
| 411 | && options.subcommand != "schedule"sv | ||
| 412 | && options.subcommand != "joparoute"sv | ||
| 413 | && options.subcommand != "journeyinfo"sv | ||
| 414 | && options.subcommand != "journeyroute"sv | ||
| 415 | && options.subcommand != "journeys"sv) { | ||
| 416 | fprintf(stderr, "%s: unknown subcommand '%s'\n\n", progname, options.subcommand); | ||
| 417 | fprintf(stderr, help, progname); | ||
| 418 | exit(1); | ||
| 419 | } | ||
| 420 | if (options.subcommand && error) { | ||
| 421 | fputc('\n', stderr); | ||
| 422 | if (options.subcommand == "joparoute"sv) fprintf(stderr, joparoute_help, progname); | ||
| 423 | if (options.subcommand == "journeyinfo"sv) fprintf(stderr, journeyinfo_help, progname); | ||
| 424 | if (options.subcommand == "journeyroute"sv) fprintf(stderr, journeyroute_help, progname); | ||
| 425 | if (options.subcommand == "journeys"sv) fprintf(stderr, journeys_help, progname); | ||
| 426 | if (options.subcommand == "schedule"sv) fprintf(stderr, schedule_help, progname); | ||
| 427 | exit(1); | ||
| 428 | } | ||
| 429 | if (error || !options.subcommand) { | ||
| 430 | if (!options.subcommand) fprintf(stderr, "%s: no subcommand provided\n", progname); | ||
| 431 | fputc('\n', stderr); | ||
| 432 | fprintf(stderr, help, progname); | ||
| 433 | exit(1); | ||
| 434 | } | ||
| 435 | if (options.help) { | ||
| 436 | if (options.subcommand == "joparoute"sv) fprintf(stderr, joparoute_help, progname); | ||
| 437 | if (options.subcommand == "journeyinfo"sv) fprintf(stderr, journeyinfo_help, progname); | ||
| 438 | if (options.subcommand == "journeyroute"sv) fprintf(stderr, journeyroute_help, progname); | ||
| 439 | if (options.subcommand == "journeys"sv) fprintf(stderr, journeys_help, progname); | ||
| 440 | if (options.subcommand == "schedule"sv) fprintf(stderr, schedule_help, progname); | ||
| 441 | exit(0); | ||
| 442 | } | ||
| 443 | |||
| 444 | if (options.subcommand == "joparoute"sv) | ||
| 445 | jopaRouteValidateOptions(progname, &options); | ||
| 446 | if (options.subcommand == "journeyinfo"sv) | ||
| 447 | journeyInfoValidateOptions(progname, &options); | ||
| 448 | if (options.subcommand == "journeyroute"sv) | ||
| 449 | journeyRouteValidateOptions(progname, &options); | ||
| 450 | if (options.subcommand == "journeys"sv) | ||
| 451 | journeysValidateOptions(progname, &options); | ||
| 452 | if (options.subcommand == "schedule"sv) | ||
| 453 | scheduleValidateOptions(progname, &options); | ||
| 454 | |||
| 455 | return options; | ||
| 456 | } | ||