| File: | .build-ci/../util/argconfig.c |
| Warning: | line 434, column 3 Potential leak of memory pointed to by 'long_opts' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | // SPDX-License-Identifier: GPL-2.0-or-later | |||
| 2 | /* | |||
| 3 | * Copyright 2014 PMC-Sierra, Inc. | |||
| 4 | * | |||
| 5 | * This program is free software; you can redistribute it and/or | |||
| 6 | * modify it under the terms of the GNU General Public License | |||
| 7 | * as published by the Free Software Foundation; either version 2 | |||
| 8 | * of the License, or (at your option) any later version. | |||
| 9 | * | |||
| 10 | * This program is distributed in the hope that it will be useful, | |||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| 13 | * GNU General Public License for more details. | |||
| 14 | * | |||
| 15 | * You should have received a copy of the GNU General Public License | |||
| 16 | * along with this program; if not, write to the Free Software | |||
| 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
| 18 | * | |||
| 19 | */ | |||
| 20 | ||||
| 21 | /* | |||
| 22 | * | |||
| 23 | * Author: Logan Gunthorpe | |||
| 24 | * | |||
| 25 | * Date: Oct 23 2014 | |||
| 26 | * | |||
| 27 | * Description: | |||
| 28 | * Functions for parsing command line options. | |||
| 29 | * | |||
| 30 | */ | |||
| 31 | ||||
| 32 | #include <errno(*__errno_location ()).h> | |||
| 33 | #include <getopt.h> | |||
| 34 | #include <inttypes.h> | |||
| 35 | #include <limits.h> | |||
| 36 | #include <locale.h> | |||
| 37 | #include <stdbool.h> | |||
| 38 | #include <stdarg.h> | |||
| 39 | #include <stdio.h> | |||
| 40 | #include <stdlib.h> | |||
| 41 | #include <string.h> | |||
| 42 | ||||
| 43 | #include "argconfig.h" | |||
| 44 | #include "cleanup.h" | |||
| 45 | #include "suffix.h" | |||
| 46 | ||||
| 47 | const char *libnvme_strerror(int errnum); | |||
| 48 | ||||
| 49 | static bool_Bool is_null_or_empty(const char *s) | |||
| 50 | { | |||
| 51 | return !s || !*s; | |||
| 52 | } | |||
| 53 | ||||
| 54 | static const char *append_usage_str = ""; | |||
| 55 | ||||
| 56 | void argconfig_append_usage(const char *str) | |||
| 57 | { | |||
| 58 | append_usage_str = str; | |||
| 59 | } | |||
| 60 | ||||
| 61 | void print_word_wrapped(const char *s, int indent, int start, FILE *stream) | |||
| 62 | { | |||
| 63 | const int width = 76; | |||
| 64 | const char *c, *t; | |||
| 65 | int next_space = -1; | |||
| 66 | int last_line = indent; | |||
| 67 | ||||
| 68 | while (start < indent) { | |||
| 69 | putc(' ', stream); | |||
| 70 | start++; | |||
| 71 | } | |||
| 72 | ||||
| 73 | for (c = s; *c != 0; c++) { | |||
| 74 | if (*c == '\n') | |||
| 75 | goto new_line; | |||
| 76 | ||||
| 77 | if (*c == ' ' || next_space < 0) { | |||
| 78 | next_space = 0; | |||
| 79 | for (t = c + 1; *t != 0 && *t != ' '; t++) | |||
| 80 | next_space++; | |||
| 81 | ||||
| 82 | if (((int)(c - s) + start + next_space) > (last_line - indent + width)) { | |||
| 83 | int i; | |||
| 84 | new_line: | |||
| 85 | last_line = (int) (c-s) + start; | |||
| 86 | putc('\n', stream); | |||
| 87 | for (i = 0; i < indent; i++) | |||
| 88 | putc(' ', stream); | |||
| 89 | start = indent; | |||
| 90 | continue; | |||
| 91 | } | |||
| 92 | } | |||
| 93 | putc(*c, stream); | |||
| 94 | } | |||
| 95 | } | |||
| 96 | ||||
| 97 | static void show_option(const struct argconfig_commandline_options *option) | |||
| 98 | { | |||
| 99 | char buffer[0x1000]; | |||
| 100 | char *b = buffer; | |||
| 101 | ||||
| 102 | b += sprintf(b, " [ "); | |||
| 103 | if (option->option) { | |||
| 104 | b += sprintf(b, " --%s", option->option); | |||
| 105 | if (option->argument_type == optional_argument2) | |||
| 106 | b += sprintf(b, "[=<%s>]", option->meta ? option->meta : "arg"); | |||
| 107 | if (option->argument_type == required_argument1) | |||
| 108 | b += sprintf(b, "=<%s>", option->meta ? option->meta : "arg"); | |||
| 109 | if (option->short_option) | |||
| 110 | b += sprintf(b, ","); | |||
| 111 | } | |||
| 112 | if (option->short_option) { | |||
| 113 | b += sprintf(b, " -%c", option->short_option); | |||
| 114 | if (option->argument_type == optional_argument2) | |||
| 115 | b += sprintf(b, " [<%s>]", option->meta ? option->meta : "arg"); | |||
| 116 | if (option->argument_type == required_argument1) | |||
| 117 | b += sprintf(b, " <%s>", option->meta ? option->meta : "arg"); | |||
| 118 | } | |||
| 119 | b += sprintf(b, " ] "); | |||
| 120 | ||||
| 121 | fprintf(stderrstderr, "%s", buffer); | |||
| 122 | if (option->help) { | |||
| 123 | print_word_wrapped("--- ", 40, b - buffer, stderrstderr); | |||
| 124 | print_word_wrapped(option->help, 44, 44, stderrstderr); | |||
| 125 | } | |||
| 126 | fprintf(stderrstderr, "\n"); | |||
| 127 | } | |||
| 128 | ||||
| 129 | void argconfig_print_help(const char *program_desc, | |||
| 130 | struct argconfig_commandline_options *s) | |||
| 131 | { | |||
| 132 | const char *pending_header = "Options"; | |||
| 133 | bool_Bool header_printed = false0; | |||
| 134 | ||||
| 135 | fprintf(stderrstderr, "\033[1mUsage: %s\033[0m\n\n", | |||
| 136 | append_usage_str); | |||
| 137 | ||||
| 138 | print_word_wrapped(program_desc, 0, 0, stderrstderr); | |||
| 139 | fprintf(stderrstderr, "\n"); | |||
| 140 | ||||
| 141 | if (!s || !s->option) | |||
| 142 | return; | |||
| 143 | ||||
| 144 | for (; s->option; s++) { | |||
| 145 | if (s->config_type == CFG_GROUP_SEPARATOR) { | |||
| 146 | pending_header = s->help; | |||
| 147 | header_printed = false0; | |||
| 148 | continue; | |||
| 149 | } | |||
| 150 | if (!header_printed) { | |||
| 151 | fprintf(stderrstderr, "\n\033[1m%s:\033[0m\n", pending_header); | |||
| 152 | header_printed = true1; | |||
| 153 | } | |||
| 154 | if (!s->hidden) | |||
| 155 | show_option(s); | |||
| 156 | } | |||
| 157 | } | |||
| 158 | ||||
| 159 | static int argconfig_error(char *type, const char *opt, const char *arg) | |||
| 160 | { | |||
| 161 | fprintf(stderrstderr, "Expected %s argument for '%s' but got '%s'!\n", type, opt, arg); | |||
| 162 | return -EINVAL22; | |||
| 163 | } | |||
| 164 | ||||
| 165 | static int argconfig_parse_type(struct argconfig_commandline_options *s) | |||
| 166 | { | |||
| 167 | void *value = s->default_value; | |||
| 168 | char *endptr; | |||
| 169 | int ret = 0; | |||
| 170 | ||||
| 171 | errno(*__errno_location ()) = 0; /* To distinguish success/failure after strtol/stroul call */ | |||
| 172 | ||||
| 173 | switch (s->config_type) { | |||
| 174 | case CFG_STRING: | |||
| 175 | *(char **)value = optarg; | |||
| 176 | break; | |||
| 177 | case CFG_INT: | |||
| 178 | *(int *)value = strtol(optarg, &endptr, 0); | |||
| 179 | if (errno(*__errno_location ()) || optarg == endptr) | |||
| 180 | ret = argconfig_error("integer", s->option, optarg); | |||
| 181 | break; | |||
| 182 | case CFG_BYTE: { | |||
| 183 | unsigned long tmp = strtoul(optarg, &endptr, 0); | |||
| 184 | ||||
| 185 | if (errno(*__errno_location ()) || tmp >= 1 << 8 || optarg == endptr) | |||
| 186 | ret = argconfig_error("byte", s->option, optarg); | |||
| 187 | else | |||
| 188 | *(uint8_t *)value = tmp; | |||
| 189 | break; | |||
| 190 | } | |||
| 191 | case CFG_SHORT: { | |||
| 192 | unsigned long tmp = strtoul(optarg, &endptr, 0); | |||
| 193 | ||||
| 194 | if (errno(*__errno_location ()) || tmp >= 1 << 16 || optarg == endptr) | |||
| 195 | ret = argconfig_error("short", s->option, optarg); | |||
| 196 | else | |||
| 197 | *(uint16_t *)value = tmp; | |||
| 198 | break; | |||
| 199 | } | |||
| 200 | case CFG_POSITIVE: { | |||
| 201 | uint32_t tmp = strtoul(optarg, &endptr, 0); | |||
| 202 | ||||
| 203 | if (errno(*__errno_location ()) || optarg == endptr) | |||
| 204 | ret = argconfig_error("word", s->option, optarg); | |||
| 205 | else | |||
| 206 | *(uint32_t *)value = tmp; | |||
| 207 | break; | |||
| 208 | } | |||
| 209 | case CFG_INCREMENT: | |||
| 210 | *(int *)value += 1; | |||
| 211 | break; | |||
| 212 | case CFG_LONG: | |||
| 213 | *(unsigned long *)value = strtoul(optarg, &endptr, 0); | |||
| 214 | if (errno(*__errno_location ()) || optarg == endptr) | |||
| 215 | ret = argconfig_error("long integer", s->option, optarg); | |||
| 216 | break; | |||
| 217 | case CFG_LONG_SUFFIX: | |||
| 218 | ret = suffix_binary_parse(optarg, &endptr, (uint64_t *)value); | |||
| 219 | if (ret) | |||
| 220 | argconfig_error("long suffixed integer", s->option, optarg); | |||
| 221 | break; | |||
| 222 | case CFG_DOUBLE: | |||
| 223 | *(double *)value = strtod(optarg, &endptr); | |||
| 224 | if (errno(*__errno_location ()) || optarg == endptr) | |||
| 225 | ret = argconfig_error("float", s->option, optarg); | |||
| 226 | break; | |||
| 227 | case CFG_FLAG: | |||
| 228 | *(bool_Bool *)value = true1; | |||
| 229 | break; | |||
| 230 | case CFG_GROUP_SEPARATOR: | |||
| 231 | break; | |||
| 232 | } | |||
| 233 | ||||
| 234 | return ret; | |||
| 235 | } | |||
| 236 | ||||
| 237 | static void argconfig_set_opt_val(enum argconfig_types type, union argconfig_val *opt_val, void *val) | |||
| 238 | { | |||
| 239 | switch (type) { | |||
| 240 | case CFG_FLAG: | |||
| 241 | *(bool_Bool *)val = opt_val->bool_val; | |||
| 242 | break; | |||
| 243 | case CFG_LONG_SUFFIX: | |||
| 244 | *(uint64_t *)val = opt_val->long_suffix; | |||
| 245 | break; | |||
| 246 | case CFG_POSITIVE: | |||
| 247 | *(uint32_t *)val = opt_val->positive; | |||
| 248 | break; | |||
| 249 | case CFG_INT: | |||
| 250 | *(int *)val = opt_val->int_val; | |||
| 251 | break; | |||
| 252 | case CFG_LONG: | |||
| 253 | *(unsigned long *)val = opt_val->long_val; | |||
| 254 | break; | |||
| 255 | case CFG_DOUBLE: | |||
| 256 | *(double *)val = opt_val->double_val; | |||
| 257 | break; | |||
| 258 | case CFG_BYTE: | |||
| 259 | *(uint8_t *)val = opt_val->byte; | |||
| 260 | break; | |||
| 261 | case CFG_SHORT: | |||
| 262 | *(uint16_t *)val = opt_val->short_val; | |||
| 263 | break; | |||
| 264 | case CFG_INCREMENT: | |||
| 265 | *(int *)val = opt_val->increment; | |||
| 266 | break; | |||
| 267 | case CFG_STRING: | |||
| 268 | *(char **)val = opt_val->string; | |||
| 269 | break; | |||
| 270 | case CFG_GROUP_SEPARATOR: | |||
| 271 | break; | |||
| 272 | } | |||
| 273 | } | |||
| 274 | ||||
| 275 | static struct argconfig_opt_val * | |||
| 276 | argconfig_match_val(struct argconfig_opt_val *v, const char *str) | |||
| 277 | { | |||
| 278 | size_t len = strlen(str); | |||
| 279 | struct argconfig_opt_val *match = NULL((void*)0); | |||
| 280 | ||||
| 281 | for (; v->str; v++) { | |||
| 282 | if (strncasecmp(str, v->str, len)) | |||
| 283 | continue; | |||
| 284 | ||||
| 285 | if (len == strlen(v->str)) | |||
| 286 | return v; | |||
| 287 | ||||
| 288 | if (match) | |||
| 289 | return NULL((void*)0); /* multiple matches; input is ambiguous */ | |||
| 290 | ||||
| 291 | match = v; | |||
| 292 | } | |||
| 293 | ||||
| 294 | return match; | |||
| 295 | } | |||
| 296 | ||||
| 297 | static int argconfig_parse_val(struct argconfig_commandline_options *s) | |||
| 298 | { | |||
| 299 | struct argconfig_opt_val *v = s->opt_val; | |||
| 300 | ||||
| 301 | if (v) | |||
| 302 | v = argconfig_match_val(v, optarg); | |||
| 303 | if (!v) | |||
| 304 | return argconfig_parse_type(s); | |||
| 305 | ||||
| 306 | argconfig_set_opt_val(v->type, &v->val, s->default_value); | |||
| 307 | return 0; | |||
| 308 | } | |||
| 309 | ||||
| 310 | static bool_Bool argconfig_check_verbose(struct argconfig_commandline_options *s) | |||
| 311 | { | |||
| 312 | for (; s && s->option; s++) { | |||
| 313 | if (!strcmp(s->option, "verbose") && | |||
| 314 | s->config_type == CFG_INCREMENT) | |||
| 315 | return s->seen; | |||
| 316 | } | |||
| 317 | ||||
| 318 | return false0; | |||
| 319 | } | |||
| 320 | ||||
| 321 | int argconfig_parse(int argc, char *argv[], const char *program_desc, | |||
| 322 | struct argconfig_commandline_options *options) | |||
| 323 | { | |||
| 324 | __cleanup_free__attribute__((cleanup(freep))) char *short_opts = NULL((void*)0); | |||
| 325 | __cleanup_free__attribute__((cleanup(freep))) struct option *long_opts = NULL((void*)0); | |||
| 326 | __cleanup_free__attribute__((cleanup(freep))) int *long_opt_map = NULL((void*)0); | |||
| 327 | struct argconfig_commandline_options *s; | |||
| 328 | int c, long_opt_index = 0, opt_index = 0, short_index = 0, options_count = 0; | |||
| 329 | int ret = 0; | |||
| 330 | ||||
| 331 | errno(*__errno_location ()) = 0; | |||
| 332 | for (s = options; s->option; s++) | |||
| 333 | options_count++; | |||
| 334 | ||||
| 335 | long_opts = calloc(options_count + 2, sizeof(struct option)); | |||
| 336 | short_opts = calloc(options_count * 3 + 3, sizeof(*short_opts)); | |||
| 337 | long_opt_map = calloc(options_count + 2, sizeof(*long_opt_map)); | |||
| 338 | ||||
| 339 | if (!long_opts || !short_opts || !long_opt_map) { | |||
| 340 | fprintf(stderrstderr, "failed to allocate memory for opts: %s\n", libnvme_strerror(errno(*__errno_location ()))); | |||
| 341 | return -errno(*__errno_location ()); | |||
| 342 | } | |||
| 343 | ||||
| 344 | for (s = options, opt_index = 0; s->option; s++, opt_index++) { | |||
| 345 | s->seen = false0; | |||
| 346 | if (s->config_type == CFG_GROUP_SEPARATOR) | |||
| 347 | continue; | |||
| 348 | if (s->short_option) { | |||
| 349 | short_opts[short_index++] = s->short_option; | |||
| 350 | if (s->argument_type == required_argument1 || | |||
| 351 | s->argument_type == optional_argument2) | |||
| 352 | short_opts[short_index++] = ':'; | |||
| 353 | if (s->argument_type == optional_argument2) | |||
| 354 | short_opts[short_index++] = ':'; | |||
| 355 | } | |||
| 356 | if (!is_null_or_empty(s->option)) { | |||
| 357 | long_opts[long_opt_index].name = s->option; | |||
| 358 | long_opts[long_opt_index].has_arg = s->argument_type; | |||
| 359 | long_opt_map[long_opt_index] = opt_index; | |||
| 360 | long_opt_index++; | |||
| 361 | } | |||
| 362 | } | |||
| 363 | ||||
| 364 | long_opts[long_opt_index].name = "help"; | |||
| 365 | long_opts[long_opt_index].val = 'h'; | |||
| 366 | ||||
| 367 | short_opts[short_index++] = '?'; | |||
| 368 | short_opts[short_index] = 'h'; | |||
| 369 | ||||
| 370 | optind = 0; | |||
| 371 | while ((c = getopt_long_only(argc, argv, short_opts, long_opts, &long_opt_index)) != -1) { | |||
| 372 | if (c) { | |||
| 373 | if (c == '?' || c == 'h') { | |||
| 374 | argconfig_print_help(program_desc, options); | |||
| 375 | ret = -EINVAL22; | |||
| 376 | break; | |||
| 377 | } | |||
| 378 | for (opt_index = 0; opt_index < options_count; opt_index++) { | |||
| 379 | if (c == options[opt_index].short_option) | |||
| 380 | break; | |||
| 381 | } | |||
| 382 | if (opt_index == options_count) | |||
| 383 | continue; | |||
| 384 | } else { | |||
| 385 | opt_index = long_opt_map[long_opt_index]; | |||
| 386 | } | |||
| 387 | ||||
| 388 | s = &options[opt_index]; | |||
| 389 | s->seen = true1; | |||
| 390 | ||||
| 391 | if (!s->default_value) | |||
| 392 | continue; | |||
| 393 | ||||
| 394 | ret = argconfig_parse_val(s); | |||
| 395 | if (ret) | |||
| 396 | break; | |||
| 397 | } | |||
| 398 | ||||
| 399 | if (!argconfig_check_verbose(options)) | |||
| 400 | setlocale(LC_ALL6, "C"); | |||
| 401 | ||||
| 402 | return ret; | |||
| 403 | } | |||
| 404 | ||||
| 405 | /* | |||
| 406 | * Parse global (pre-subcommand) options from argc/argv. Stops at the first | |||
| 407 | * non-option argument (i.e. the subcommand name) so that subcommand-specific | |||
| 408 | * options are left in place for the subcommand dispatcher. After a successful | |||
| 409 | * call, optind points to the first non-option argument (the subcommand). | |||
| 410 | * | |||
| 411 | * Returns 0 on success, negative errno on failure. | |||
| 412 | */ | |||
| 413 | int argconfig_parse_global(int argc, char *argv[], | |||
| 414 | struct argconfig_commandline_options *options) | |||
| 415 | { | |||
| 416 | __cleanup_free__attribute__((cleanup(freep))) char *short_opts = NULL((void*)0); | |||
| 417 | __cleanup_free__attribute__((cleanup(freep))) struct option *long_opts = NULL((void*)0); | |||
| 418 | __cleanup_free__attribute__((cleanup(freep))) int *long_opt_map = NULL((void*)0); | |||
| 419 | struct argconfig_commandline_options *s; | |||
| 420 | int c, long_opt_index = 0, opt_index = 0; | |||
| 421 | int short_index = 0, options_count = 0; | |||
| 422 | int ret = 0; | |||
| 423 | ||||
| 424 | errno(*__errno_location ()) = 0; | |||
| 425 | for (s = options; s->option; s++) | |||
| ||||
| 426 | options_count++; | |||
| 427 | ||||
| 428 | long_opts = calloc(options_count + 2, sizeof(struct option)); | |||
| 429 | /* '+' prefix: stop at the first non-option argument (the subcommand) */ | |||
| 430 | short_opts = calloc(options_count * 3 + 4, sizeof(*short_opts)); | |||
| 431 | long_opt_map = calloc(options_count + 2, sizeof(*long_opt_map)); | |||
| 432 | ||||
| 433 | if (!long_opts || !short_opts || !long_opt_map) { | |||
| 434 | fprintf(stderrstderr, "failed to allocate memory for opts: %s\n", | |||
| ||||
| 435 | libnvme_strerror(errno(*__errno_location ()))); | |||
| 436 | return -errno(*__errno_location ()); | |||
| 437 | } | |||
| 438 | ||||
| 439 | short_opts[short_index++] = '+'; | |||
| 440 | ||||
| 441 | for (s = options, opt_index = 0; s->option; s++, opt_index++) { | |||
| 442 | s->seen = false0; | |||
| 443 | if (s->config_type == CFG_GROUP_SEPARATOR) | |||
| 444 | continue; | |||
| 445 | if (s->short_option) { | |||
| 446 | short_opts[short_index++] = s->short_option; | |||
| 447 | if (s->argument_type == required_argument1 || | |||
| 448 | s->argument_type == optional_argument2) | |||
| 449 | short_opts[short_index++] = ':'; | |||
| 450 | if (s->argument_type == optional_argument2) | |||
| 451 | short_opts[short_index++] = ':'; | |||
| 452 | } | |||
| 453 | if (!is_null_or_empty(s->option)) { | |||
| 454 | long_opts[long_opt_index].name = s->option; | |||
| 455 | long_opts[long_opt_index].has_arg = s->argument_type; | |||
| 456 | long_opt_map[long_opt_index] = opt_index; | |||
| 457 | long_opt_index++; | |||
| 458 | } | |||
| 459 | } | |||
| 460 | ||||
| 461 | optind = 0; | |||
| 462 | while ((c = getopt_long(argc, argv, short_opts, | |||
| 463 | long_opts, &long_opt_index)) != -1) { | |||
| 464 | if (c == '?' || c == ':') { | |||
| 465 | ret = -EINVAL22; | |||
| 466 | break; | |||
| 467 | } | |||
| 468 | if (c) { | |||
| 469 | for (opt_index = 0; opt_index < options_count; | |||
| 470 | opt_index++) { | |||
| 471 | if (c == options[opt_index].short_option) | |||
| 472 | break; | |||
| 473 | } | |||
| 474 | if (opt_index == options_count) { | |||
| 475 | ret = -EINVAL22; | |||
| 476 | break; | |||
| 477 | } | |||
| 478 | } else { | |||
| 479 | opt_index = long_opt_map[long_opt_index]; | |||
| 480 | } | |||
| 481 | ||||
| 482 | s = &options[opt_index]; | |||
| 483 | s->seen = true1; | |||
| 484 | ||||
| 485 | if (!s->default_value) | |||
| 486 | continue; | |||
| 487 | ||||
| 488 | ret = argconfig_parse_val(s); | |||
| 489 | if (ret) | |||
| 490 | break; | |||
| 491 | } | |||
| 492 | ||||
| 493 | return ret; | |||
| 494 | } | |||
| 495 | ||||
| 496 | #define DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_FUNC(name, ret_t, ret_max)int argconfig_parse_comma_sep_arrayname(char *string, ret_t * val, unsigned int max_length) { int ret = 0; uintmax_t v; char *tmp; char *p; if (is_null_or_empty(string)) return 0; tmp = strtok(string, ","); while (tmp) { if (ret >= max_length) return -1; v = strtoumax(tmp, &p, 0); if (*p != 0) return -1; if (v > ret_max) { fprintf(stderr, "%s out of range\n" , tmp); return -1; } val[ret] = v; ret++; tmp = strtok(((void *)0), ","); } return ret; } \ | |||
| 497 | int argconfig_parse_comma_sep_array ## name(char *string, \ | |||
| 498 | ret_t *val, \ | |||
| 499 | unsigned int max_length) \ | |||
| 500 | { \ | |||
| 501 | int ret = 0; \ | |||
| 502 | uintmax_t v; \ | |||
| 503 | char *tmp; \ | |||
| 504 | char *p; \ | |||
| 505 | \ | |||
| 506 | if (is_null_or_empty(string)) \ | |||
| 507 | return 0; \ | |||
| 508 | \ | |||
| 509 | tmp = strtok(string, ","); \ | |||
| 510 | \ | |||
| 511 | while (tmp) { \ | |||
| 512 | if (ret >= max_length) \ | |||
| 513 | return -1; \ | |||
| 514 | \ | |||
| 515 | v = strtoumax(tmp, &p, 0); \ | |||
| 516 | if (*p != 0) \ | |||
| 517 | return -1; \ | |||
| 518 | if (v > ret_max) { \ | |||
| 519 | fprintf(stderrstderr, "%s out of range\n", tmp); \ | |||
| 520 | return -1; \ | |||
| 521 | } \ | |||
| 522 | val[ret] = v; \ | |||
| 523 | ret++; \ | |||
| 524 | \ | |||
| 525 | tmp = strtok(NULL((void*)0), ","); \ | |||
| 526 | } \ | |||
| 527 | \ | |||
| 528 | return ret; \ | |||
| 529 | } | |||
| 530 | ||||
| 531 | DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_FUNC(, int, UINT_MAX)int argconfig_parse_comma_sep_array(char *string, int *val, unsigned int max_length) { int ret = 0; uintmax_t v; char *tmp; char * p; if (is_null_or_empty(string)) return 0; tmp = strtok(string , ","); while (tmp) { if (ret >= max_length) return -1; v = strtoumax(tmp, &p, 0); if (*p != 0) return -1; if (v > (2147483647 *2U +1U)) { fprintf(stderr, "%s out of range\n", tmp); return -1; } val[ret] = v; ret++; tmp = strtok(((void* )0), ","); } return ret; } | |||
| 532 | DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_FUNC(_short, unsigned short, UINT16_MAX)int argconfig_parse_comma_sep_array_short(char *string, unsigned short *val, unsigned int max_length) { int ret = 0; uintmax_t v; char *tmp; char *p; if (is_null_or_empty(string)) return 0 ; tmp = strtok(string, ","); while (tmp) { if (ret >= max_length ) return -1; v = strtoumax(tmp, &p, 0); if (*p != 0) return -1; if (v > (65535)) { fprintf(stderr, "%s out of range\n" , tmp); return -1; } val[ret] = v; ret++; tmp = strtok(((void *)0), ","); } return ret; } | |||
| 533 | DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_FUNC(_long, unsigned long long, ULLONG_MAX)int argconfig_parse_comma_sep_array_long(char *string, unsigned long long *val, unsigned int max_length) { int ret = 0; uintmax_t v; char *tmp; char *p; if (is_null_or_empty(string)) return 0 ; tmp = strtok(string, ","); while (tmp) { if (ret >= max_length ) return -1; v = strtoumax(tmp, &p, 0); if (*p != 0) return -1; if (v > (9223372036854775807LL*2ULL+1ULL)) { fprintf( stderr, "%s out of range\n", tmp); return -1; } val[ret] = v; ret++; tmp = strtok(((void*)0), ","); } return ret; } | |||
| 534 | ||||
| 535 | #define DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_UINT_FUNC(size)int argconfig_parse_comma_sep_array_usize(char *string, __usize *val, unsigned int max_length) { int ret = 0; uintmax_t v; char *tmp; char *p; if (is_null_or_empty(string)) return 0; tmp = strtok(string, ","); while (tmp) { if (ret >= max_length) return -1; v = strtoumax(tmp, &p, 0); if (*p != 0) return -1; if (v > UINTsize_MAX) { fprintf(stderr, "%s out of range\n" , tmp); return -1; } val[ret] = v; ret++; tmp = strtok(((void *)0), ","); } return ret; } \ | |||
| 536 | DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_FUNC(_u ## size, __u ## size, \int argconfig_parse_comma_sep_array_u ## size(char *string, __u ## size *val, unsigned int max_length) { int ret = 0; uintmax_t v; char *tmp; char *p; if (is_null_or_empty(string)) return 0 ; tmp = strtok(string, ","); while (tmp) { if (ret >= max_length ) return -1; v = strtoumax(tmp, &p, 0); if (*p != 0) return -1; if (v > UINT ## size ## _MAX) { fprintf(stderr, "%s out of range\n" , tmp); return -1; } val[ret] = v; ret++; tmp = strtok(((void *)0), ","); } return ret; } | |||
| 537 | UINT ## size ## _MAX)int argconfig_parse_comma_sep_array_u ## size(char *string, __u ## size *val, unsigned int max_length) { int ret = 0; uintmax_t v; char *tmp; char *p; if (is_null_or_empty(string)) return 0 ; tmp = strtok(string, ","); while (tmp) { if (ret >= max_length ) return -1; v = strtoumax(tmp, &p, 0); if (*p != 0) return -1; if (v > UINT ## size ## _MAX) { fprintf(stderr, "%s out of range\n" , tmp); return -1; } val[ret] = v; ret++; tmp = strtok(((void *)0), ","); } return ret; } | |||
| 538 | ||||
| 539 | DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_UINT_FUNC(16)int argconfig_parse_comma_sep_array_u16(char *string, __u16 * val, unsigned int max_length) { int ret = 0; uintmax_t v; char *tmp; char *p; if (is_null_or_empty(string)) return 0; tmp = strtok(string, ","); while (tmp) { if (ret >= max_length) return -1; v = strtoumax(tmp, &p, 0); if (*p != 0) return -1; if (v > (65535)) { fprintf(stderr, "%s out of range\n" , tmp); return -1; } val[ret] = v; ret++; tmp = strtok(((void *)0), ","); } return ret; }; | |||
| 540 | DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_UINT_FUNC(32)int argconfig_parse_comma_sep_array_u32(char *string, __u32 * val, unsigned int max_length) { int ret = 0; uintmax_t v; char *tmp; char *p; if (is_null_or_empty(string)) return 0; tmp = strtok(string, ","); while (tmp) { if (ret >= max_length) return -1; v = strtoumax(tmp, &p, 0); if (*p != 0) return -1; if (v > (4294967295U)) { fprintf(stderr, "%s out of range\n" , tmp); return -1; } val[ret] = v; ret++; tmp = strtok(((void *)0), ","); } return ret; }; | |||
| 541 | DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_UINT_FUNC(64)int argconfig_parse_comma_sep_array_u64(char *string, __u64 * val, unsigned int max_length) { int ret = 0; uintmax_t v; char *tmp; char *p; if (is_null_or_empty(string)) return 0; tmp = strtok(string, ","); while (tmp) { if (ret >= max_length) return -1; v = strtoumax(tmp, &p, 0); if (*p != 0) return -1; if (v > (18446744073709551615UL)) { fprintf(stderr, "%s out of range\n" , tmp); return -1; } val[ret] = v; ret++; tmp = strtok(((void *)0), ","); } return ret; }; | |||
| 542 | ||||
| 543 | bool_Bool argconfig_parse_seen(struct argconfig_commandline_options *s, | |||
| 544 | const char *option) | |||
| 545 | { | |||
| 546 | for (; s && s->option; s++) { | |||
| 547 | if (!strcmp(s->option, option)) | |||
| 548 | return s->seen; | |||
| 549 | } | |||
| 550 | ||||
| 551 | return false0; | |||
| 552 | } |