// SPDX-License-Identifier: GPL-2.0-only /* * getopt.c - a simple getopt(3) implementation. See getopt.h for explanation. * * Copyright (C) 2020 Sean Anderson * Copyright (c) 2007 Sascha Hauer , Pengutronix */ #define LOG_CATEGORY LOGC_CORE #include #include #include void getopt_init_state(struct getopt_state *gs) { gs->index = 1; gs->arg_index = 1; } int __getopt(struct getopt_state *gs, int argc, char *const argv[], const char *optstring, bool silent) { char curopt; /* current option character */ const char *curoptp; /* pointer to the current option in optstring */ while (1) { log_debug("arg_index: %d index: %d\n", gs->arg_index, gs->index); /* `--` indicates the end of options */ if (gs->arg_index == 1 && argv[gs->index] && !strcmp(argv[gs->index], "--")) { gs->index++; return -1; } /* Out of arguments */ if (gs->index >= argc) return -1; /* Can't parse non-options */ if (*argv[gs->index] != '-') return -1; /* We have found an option */ curopt = argv[gs->index][gs->arg_index]; if (curopt) break; /* * no more options in current argv[] element; try the next one */ gs->index++; gs->arg_index = 1; } /* look up current option in optstring */ curoptp = strchr(optstring, curopt); if (!curoptp) { if (!silent) printf("%s: invalid option -- %c\n", argv[0], curopt); gs->opt = curopt; gs->arg_index++; return '?'; } if (*(curoptp + 1) != ':') { /* option with no argument. Just return it */ gs->arg = NULL; gs->arg_index++; return curopt; } if (*(curoptp + 1) && *(curoptp + 2) == ':') { /* optional argument */ if (argv[gs->index][gs->arg_index + 1]) { /* optional argument with directly following arg */ gs->arg = argv[gs->index++] + gs->arg_index + 1; gs->arg_index = 1; return curopt; } if (gs->index + 1 == argc) { /* We are at the last argv[] element */ gs->arg = NULL; gs->index++; return curopt; } if (*argv[gs->index + 1] != '-') { /* * optional argument with arg in next argv[] element */ gs->index++; gs->arg = argv[gs->index++]; gs->arg_index = 1; return curopt; } /* no optional argument found */ gs->arg = NULL; gs->arg_index = 1; gs->index++; return curopt; } if (argv[gs->index][gs->arg_index + 1]) { /* required argument with directly following arg */ gs->arg = argv[gs->index++] + gs->arg_index + 1; gs->arg_index = 1; return curopt; } gs->index++; gs->arg_index = 1; if (gs->index >= argc || argv[gs->index][0] == '-') { if (!silent) printf("option requires an argument -- %c\n", curopt); gs->opt = curopt; return ':'; } gs->arg = argv[gs->index++]; return curopt; }