// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License. // See LICENSE.md for license information. // SPDX-License-Identifier: MIT // // gateArg.c - command lines for the gate tools (gateArg.h). #include #include #include #include #include #include #include "gateArg.h" #include "toolFile.h" #define DECIMAL 10 #define PORT_MAX 65535L void gateArgBad(const char *name, const char *text) { toolFailCode(GATE_USAGE_EXIT, "bad %s: %s", name, text); } double gateArgDouble(const char *name, const char *text) { double value; if (!gateArgParseDouble(text, &value)) { gateArgBad(name, text); } return value; } long gateArgLong(const char *name, const char *text) { long value; if (!gateArgParseLong(text, &value)) { gateArgBad(name, text); } return value; } void gateArgPair(const char *name, const char *text, char separator, long *first, long *second) { char *copy; char *split; size_t len; bool good; len = strlen(text); copy = (char *)malloc(len + 1u); if (copy == NULL) { toolFail("out of memory"); } memcpy(copy, text, len + 1u); split = strchr(copy, separator); good = split != NULL && strchr(split + 1, separator) == NULL; if (good) { *split = '\0'; good = gateArgParseLong(copy, first) && gateArgParseLong(split + 1, second); } free(copy); if (!good) { gateArgBad(name, text); } } bool gateArgParseDouble(const char *text, double *out) { char *end; if (text[0] == '\0' || isspace((unsigned char)text[0])) { return false; } *out = strtod(text, &end); return *end == '\0' && isfinite(*out); } bool gateArgParseLong(const char *text, long *out) { char *end; if (text[0] == '\0' || isspace((unsigned char)text[0])) { return false; } errno = 0; *out = strtol(text, &end, DECIMAL); return *end == '\0' && errno != ERANGE; } uint16_t gateArgPort(const char *text) { long port; port = gateArgLong("port", text); if (port < 0 || port > PORT_MAX) { gateArgBad("port", text); } return (uint16_t)port; } bool gateModeRun(const GateModeT *modes, size_t count, int argc, char **argv, int *exitCode) { size_t m; for (m = 0; argc >= 2 && m < count; m++) { if (strcmp(argv[1], modes[m].name) == 0 && argc == modes[m].argCount + 2) { *exitCode = modes[m].run(argv + 2); return true; } } return false; } int gateUsage(const char *const *lines, size_t count) { size_t i; for (i = 0; i < count; i++) { fprintf(stderr, "%s\n", lines[i]); } return GATE_USAGE_EXIT; }