/* * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include #include #include void ArgParseStateInit(ArgParseState * state) { state->optPos = 1; state->optErr = 1; state->optInd = 1; state->optOpt = 0; state->optArg = NULL; } int ArgParse(ArgParseState * state, Array * args, const char *optStr) { const char *arg; arg = ArrayGet(args, state->optInd); if (arg && StrEquals(arg, "--")) { state->optInd++; return -1; } else if (!arg || arg[0] != '-' || !isalnum((unsigned char) arg[1])) { return -1; } else { const char *opt = strchr(optStr, arg[state->optPos]); state->optOpt = arg[state->optPos]; if (!opt) { if (state->optErr && *optStr != ':') { Log(LOG_ERR, "Illegal option: %c", ArrayGet(args, 0), state->optOpt); } if (!arg[++state->optPos]) { state->optInd++; state->optPos = 1; } return '?'; } else if (opt[1] == ':') { if (arg[state->optPos + 1]) { state->optArg = (char *) arg + state->optPos + 1; state->optInd++; state->optPos = 1; return state->optOpt; } else if (ArrayGet(args, state->optInd + 1)) { state->optArg = (char *) ArrayGet(args, state->optInd + 1); state->optInd += 2; state->optPos = 1; return state->optOpt; } else { if (state->optErr && *optStr != ':') { Log(LOG_ERR, "Option requires an argument: %c", state->optOpt); } if (!arg[++state->optPos]) { state->optInd++; state->optPos = 1; } return *optStr == ':' ? ':' : '?'; } } else { if (!arg[++state->optPos]) { state->optInd++; state->optPos = 1; } return state->optOpt; } } }