joeylib2/tests/gate/common/gateArg.c

125 lines
2.7 KiB
C

// 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 <ctype.h>
#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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;
}