gargoyle/src/gargoyle.c

177 lines
4.7 KiB
C
Raw Normal View History

2022-06-19 01:13:10 +00:00
#include <gargoyle.h>
#include <gargoyle/scribe.h>
#include <gargoyle/sleuth.h>
2022-06-29 01:24:07 +00:00
#include <gargoyle/twine.h>
#include <stddef.h>
2022-07-02 23:23:39 +00:00
#include <strings.h>
2022-06-19 01:13:10 +00:00
2022-07-08 00:43:06 +00:00
uint8_t gargoyle_digest_argv(uint16_t optc, struct gargoyle_optn *optv, int *argc, char ***argv, struct gargoyle_err *err, gargoyle_flag_type flags) {
if(!(flags & GARGOYLE_FLG_GREED)) {
2022-06-19 09:02:11 +00:00
*argc -= 1;
*argv += 1;
}
if(flags & GARGOYLE_FLG_BCASE) {
flags |= GARGOYLE_FLG_ICASE;
}
GARGOYLE_NEW_ERR(err);
while(1) {
2022-06-19 01:13:10 +00:00
const char *arg = **argv;
if(!arg || *arg != '-' || !*(arg + 1)) {
return GARGOYLE_ERR_SUCCESS;
2022-06-19 01:13:10 +00:00
} else if(*arg == '-' && *(arg + 1) == '-' && !*(arg + 2)) {
*argc -= 1;
*argv += 1;
return GARGOYLE_ERR_SUCCESS;
}
2022-07-08 00:43:06 +00:00
struct gargoyle_optn *optn = NULL;
if(*(arg + 1) == '-') {
2022-06-20 01:30:01 +00:00
const char *brand = arg + 2;
2022-07-10 22:19:44 +00:00
optn = gargoyle_find_brand(optc, optv, brand, "no-", 3, flags);
2022-07-08 00:43:06 +00:00
if(!optn) {
if(flags & GARGOYLE_FLG_STRCT) {
char *eql = index(brand, '=');
GARGOYLE_MK_ERR(err, GARGOYLE_ERR_UNKNOWN_OPTN, "unknown option '--%.*s'", (int) (eql - brand), brand);
return err->code;
} else {
*argc -= 1;
*argv += 1;
continue;
}
}
2022-06-20 01:30:01 +00:00
uint8_t res = 0;
const char *val = NULL;
2022-06-20 01:30:01 +00:00
2022-07-08 00:43:06 +00:00
if(optn->type & GARGOYLE_TYPE_BOOL) {
2022-07-10 22:19:44 +00:00
res = gargoyle_from_bool(optn, brand, "no-", 3, flags);
2022-07-08 00:43:06 +00:00
} else if(*(brand + optn->brand_sz) == '=') {
val = brand + optn->brand_sz + 1;
res = gargoyle_from_rope(optn, val, flags);
2022-06-20 01:30:01 +00:00
} else {
2022-06-20 17:49:17 +00:00
if(!*(*argv + 1)) {
2022-07-08 00:43:06 +00:00
GARGOYLE_MK_ERR(err, GARGOYLE_ERR_VAL_REQUIRED, "option '--%s' requires a value", optn->brand);
return err->code;
2022-06-20 01:30:01 +00:00
}
*argc -= 1;
*argv += 1;
val = **argv;
2022-07-08 00:43:06 +00:00
res = gargoyle_from_rope(optn, val, flags);
2022-06-20 01:30:01 +00:00
}
if(res) {
if(val) {
2022-07-08 00:43:06 +00:00
GARGOYLE_MK_ERR(err, res, "invalid value '%s' for option '--%s'", val, optn->brand);
} else {
2022-07-08 00:43:06 +00:00
GARGOYLE_MK_ERR(err, res, "invalid value for option '--%s'", optn->brand);
}
return err->code;
2022-06-20 01:30:01 +00:00
}
} else {
const char *idx = arg + 1;
for(; *idx; idx += 1) {
2022-07-08 00:43:06 +00:00
optn = gargoyle_find_emblem(optc, optv, *idx, flags);
2022-07-08 00:43:06 +00:00
if(!optn) {
if(flags & GARGOYLE_FLG_STRCT) {
GARGOYLE_MK_ERR(err, GARGOYLE_ERR_UNKNOWN_OPTN, "unknown option '-%c'", *idx);
return err->code;
} else {
idx += 1;
continue;
}
}
2022-06-29 01:24:07 +00:00
uint8_t res = 0;
const char *val = NULL;
2022-06-29 01:24:07 +00:00
2022-07-08 00:43:06 +00:00
if(optn->type & GARGOYLE_TYPE_BOOL) {
2022-07-10 22:19:44 +00:00
res = gargoyle_from_bool(optn, "", "*", 1, flags);
2022-06-29 01:24:07 +00:00
} else if(*(idx + 1)) {
val = idx + 1;
2022-07-08 00:43:06 +00:00
res = gargoyle_from_rope(optn, val, flags);
2022-06-29 01:24:07 +00:00
break;
} else {
if(!*(*argv + 1)) {
2022-07-08 00:43:06 +00:00
GARGOYLE_MK_ERR(err, GARGOYLE_ERR_VAL_REQUIRED, "option '-%c' requires a value", optn->emblem);
return err->code;
2022-06-29 01:24:07 +00:00
}
*argc -= 1;
*argv += 1;
val = **argv;
2022-07-08 00:43:06 +00:00
res = gargoyle_from_rope(optn, val, flags);
}
if(res) {
if(val) {
2022-07-08 00:43:06 +00:00
GARGOYLE_MK_ERR(err, res, "invalid value '%s' for option '-%c'", val, optn->emblem);
} else {
2022-07-08 00:43:06 +00:00
GARGOYLE_MK_ERR(err, res, "invalid value for option '-%c'", optn->emblem);
}
return err->code;
2022-06-29 01:24:07 +00:00
}
}
2022-06-19 01:13:10 +00:00
}
*argc -= 1;
*argv += 1;
}
return GARGOYLE_ERR_SUCCESS;
2022-06-19 01:13:10 +00:00
}
2022-06-29 01:27:17 +00:00
2022-07-08 00:43:06 +00:00
uint8_t gargoyle_digest_envh(uint16_t optc, struct gargoyle_optn *optv, const char *prefix, uint16_t prefix_sz, char ***envh, struct gargoyle_err *err, gargoyle_flag_type flags) {
2022-06-29 01:27:17 +00:00
if(flags & GARGOYLE_FLG_BCASE) {
flags |= GARGOYLE_FLG_ICASE;
}
GARGOYLE_NEW_ERR(err);
2022-06-29 01:27:17 +00:00
for(; **envh; *envh += 1) {
const char *var = **envh;
if(!gargoyle_cmp(prefix, var, prefix_sz, flags) || *(var + prefix_sz) != '_') {
continue;
}
const char *brand = var + prefix_sz + 1;
2022-07-08 00:43:06 +00:00
struct gargoyle_optn *optn = gargoyle_find_brand(optc, optv, brand, "NO_", 3, flags);
2022-06-29 01:27:17 +00:00
2022-07-08 00:43:06 +00:00
if(!optn) {
2022-06-29 01:27:17 +00:00
if(flags & GARGOYLE_FLG_STRCT) {
char *eql = index(brand, '=');
GARGOYLE_MK_ERR(err, GARGOYLE_ERR_UNKNOWN_OPTN, "unknown variable '%.*s'", (int) (eql - brand), brand);
return err->code;
2022-06-29 01:27:17 +00:00
} else {
continue;
}
}
uint8_t res = 0;
2022-07-08 00:43:06 +00:00
if(optn->type & GARGOYLE_TYPE_BOOL) {
res = gargoyle_from_bool(optn, brand, "NO_", 3, flags);
2022-06-29 01:27:17 +00:00
} else {
2022-07-08 00:43:06 +00:00
res = gargoyle_from_rope(optn, brand + optn->brand_sz + 1, flags);
2022-06-29 01:27:17 +00:00
}
if(res) {
2022-07-08 00:43:06 +00:00
GARGOYLE_MK_ERR(err, res, "invalid value '%s' for variable '%.*s'", brand + optn->brand_sz + 1, optn->brand_sz, optn->brand);
return err->code;
}
2022-06-29 01:27:17 +00:00
}
return GARGOYLE_ERR_SUCCESS;
2022-06-29 01:27:17 +00:00
}