F4MP/f4mp_originalcode/thirdparty/zpl/code/source/opts.c
Jous99 37b16f1547 code upload
codigo original de f4mp y tilted para referencias
2026-01-06 18:45:00 +01:00

248 lines
7.3 KiB
C

// file: source/opts.c
////////////////////////////////////////////////////////////////
//
// CLI Options
//
//
#ifdef ZPL_EDITOR
#include <zpl.h>
#endif
ZPL_BEGIN_C_DECLS
void zpl_opts_init(zpl_opts *opts, zpl_allocator a, char const *app) {
zpl_opts opts_ = { 0 };
*opts = opts_;
opts->alloc = a;
opts->appname = app;
zpl_array_init(opts->entries, a);
zpl_array_init(opts->positioned, a);
zpl_array_init(opts->errors, a);
}
void zpl_opts_free(zpl_opts *opts) {
for (zpl_i32 i = 0; i < zpl_array_count(opts->entries); ++i) {
zpl_opts_entry *e = opts->entries + i;
if (e->type == ZPL_OPTS_STRING) {
zpl_string_free(e->text);
}
}
zpl_array_free(opts->entries);
zpl_array_free(opts->positioned);
zpl_array_free(opts->errors);
}
void zpl_opts_add(zpl_opts *opts, char const *name, char const *lname, const char *desc, zpl_u8 type) {
zpl_opts_entry e = { 0 };
e.name = name;
e.lname = lname;
e.desc = desc;
e.type = type;
e.met = false;
e.pos = false;
zpl_array_append(opts->entries, e);
}
zpl_opts_entry *zpl__opts_find(zpl_opts *opts, char const *name, zpl_usize len, zpl_b32 longname) {
zpl_opts_entry *e = 0;
for (int i = 0; i < zpl_array_count(opts->entries); ++i) {
e = opts->entries + i;
char const *n = (longname ? e->lname : e->name);
if (zpl_strnlen(name, len) == zpl_strlen(n) && !zpl_strncmp(n, name, len)) { return e; }
}
return NULL;
}
void zpl_opts_positional_add(zpl_opts *opts, char const *name) {
zpl_opts_entry *e = zpl__opts_find(opts, name, zpl_strlen(name), true);
if (e) {
e->pos = true;
zpl_array_append_at(opts->positioned, e, 0);
}
}
zpl_b32 zpl_opts_positionals_filled(zpl_opts *opts) { return zpl_array_count(opts->positioned) == 0; }
zpl_string zpl_opts_string(zpl_opts *opts, char const *name, char const *fallback) {
zpl_opts_entry *e = zpl__opts_find(opts, name, zpl_strlen(name), true);
return (char *)((e && e->met) ? e->text : fallback);
}
zpl_f64 zpl_opts_real(zpl_opts *opts, char const *name, zpl_f64 fallback) {
zpl_opts_entry *e = zpl__opts_find(opts, name, zpl_strlen(name), true);
return (e && e->met) ? e->real : fallback;
}
zpl_i64 zpl_opts_integer(zpl_opts *opts, char const *name, zpl_i64 fallback) {
zpl_opts_entry *e = zpl__opts_find(opts, name, zpl_strlen(name), true);
return (e && e->met) ? e->integer : fallback;
}
void zpl__opts_set_value(zpl_opts *opts, zpl_opts_entry *t, char *b) {
t->met = true;
switch (t->type) {
case ZPL_OPTS_STRING: {
t->text = zpl_string_make(opts->alloc, b);
} break;
case ZPL_OPTS_FLOAT: {
t->real = zpl_str_to_f64(b, NULL);
} break;
case ZPL_OPTS_INT: {
t->integer = zpl_str_to_i64(b, NULL, 10);
} break;
}
for (zpl_isize i=0; i < zpl_array_count(opts->positioned); i++) {
if (!zpl_strcmp(opts->positioned[i]->lname, t->lname)) {
zpl_array_remove_at(opts->positioned, i);
break;
}
}
}
zpl_b32 zpl_opts_has_arg(zpl_opts *opts, char const *name) {
zpl_opts_entry *e = zpl__opts_find(opts, name, zpl_strlen(name), true);
if (e) { return e->met; }
return false;
}
void zpl_opts_print_help(zpl_opts *opts) {
zpl_printf("USAGE: %s", opts->appname);
for (zpl_isize i = zpl_array_count(opts->entries); i >= 0; --i) {
zpl_opts_entry *e = opts->entries + i;
if (e->pos == (zpl_b32) true) { zpl_printf(" [%s]", e->lname); }
}
zpl_printf("\nOPTIONS:\n");
for (zpl_isize i = 0; i < zpl_array_count(opts->entries); ++i) {
zpl_opts_entry *e = opts->entries + i;
zpl_printf("\t-%s, --%s: %s\n", e->name, e->lname, e->desc);
}
}
void zpl_opts_print_errors(zpl_opts *opts) {
for (int i = 0; i < zpl_array_count(opts->errors); ++i) {
zpl_opts_err *err = (opts->errors + i);
zpl_printf("ERROR: ");
switch (err->type) {
case ZPL_OPTS_ERR_OPTION: zpl_printf("Invalid option \"%s\"", err->val); break;
case ZPL_OPTS_ERR_VALUE: zpl_printf("Invalid value \"%s\"", err->val); break;
case ZPL_OPTS_ERR_MISSING_VALUE: zpl_printf("Missing value for option \"%s\"", err->val); break;
case ZPL_OPTS_ERR_EXTRA_VALUE: zpl_printf("Extra value for option \"%s\"", err->val); break;
}
zpl_printf("\n");
}
}
void zpl__opts_push_error(zpl_opts *opts, char *b, zpl_u8 errtype) {
zpl_opts_err err = { 0 };
err.val = b;
err.type = errtype;
zpl_array_append(opts->errors, err);
}
zpl_b32 zpl_opts_compile(zpl_opts *opts, int argc, char **argv) {
zpl_b32 had_errors = false;
for (int i = 1; i < argc; ++i) {
char *p = argv[i];
if (*p) {
p = zpl_str_trim(p, false);
if (*p == '-') {
zpl_opts_entry *t = 0;
zpl_b32 checkln = false;
if (*(p + 1) == '-') {
checkln = true;
++p;
}
char *b = p + 1, *e = b;
while (zpl_char_is_alphanumeric(*e)) { ++e; }
t = zpl__opts_find(opts, b, (e - b), checkln);
if (t) {
char *ob = b;
b = e;
/**/ if (*e == '=') {
if (t->type == ZPL_OPTS_FLAG) {
*e = '\0';
zpl__opts_push_error(opts, ob, ZPL_OPTS_ERR_EXTRA_VALUE);
had_errors = true;
continue;
}
b = e = e + 1;
} else if (*e == '\0') {
char *sp = argv[i+1];
if (sp && *sp != '-' && (zpl_array_count(opts->positioned) < 1 || t->type != ZPL_OPTS_FLAG)) {
if (t->type == ZPL_OPTS_FLAG) {
zpl__opts_push_error(opts, b, ZPL_OPTS_ERR_EXTRA_VALUE);
had_errors = true;
continue;
}
p = sp;
b = e = sp;
++i;
} else {
if (t->type != ZPL_OPTS_FLAG) {
zpl__opts_push_error(opts, ob, ZPL_OPTS_ERR_MISSING_VALUE);
had_errors = true;
continue;
}
t->met = true;
continue;
}
}
e = zpl_str_control_skip(e, '\0');
zpl__opts_set_value(opts, t, b);
} else {
zpl__opts_push_error(opts, b, ZPL_OPTS_ERR_OPTION);
had_errors = true;
}
} else if (zpl_array_count(opts->positioned)) {
zpl_opts_entry *l = zpl_array_back(opts->positioned);
zpl_array_pop(opts->positioned);
zpl__opts_set_value(opts, l, p);
} else {
zpl__opts_push_error(opts, p, ZPL_OPTS_ERR_VALUE);
had_errors = true;
}
}
}
return !had_errors;
}
ZPL_END_C_DECLS