#include #include #include #include #include #include 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)) { *argc -= 1; *argv += 1; } if(flags & GARGOYLE_FLG_BCASE) { flags |= GARGOYLE_FLG_ICASE; } GARGOYLE_NEW_ERR(err); while(1) { const char *arg = **argv; if(!arg || *arg != '-' || !*(arg + 1)) { return GARGOYLE_ERR_SUCCESS; } else if(*arg == '-' && *(arg + 1) == '-' && !*(arg + 2)) { *argc -= 1; *argv += 1; return GARGOYLE_ERR_SUCCESS; } struct gargoyle_optn *optn = NULL; if(*(arg + 1) == '-') { const char *brand = arg + 2; optn = gargoyle_find_brand(optc, optv, brand, "no-", 3, flags); 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; } } uint8_t res = 0; const char *val = NULL; if(optn->type & GARGOYLE_TYPE_BOOL) { res = gargoyle_from_bool(optn, brand, "no-", 3, flags); } else if(*(brand + optn->brand_sz) == '=') { val = brand + optn->brand_sz + 1; res = gargoyle_from_rope(optn, val, flags); } else { if(!*(*argv + 1)) { GARGOYLE_MK_ERR(err, GARGOYLE_ERR_VAL_REQUIRED, "option '--%s' requires a value", optn->brand); return err->code; } *argc -= 1; *argv += 1; val = **argv; res = gargoyle_from_rope(optn, val, flags); } if(res) { if(val) { GARGOYLE_MK_ERR(err, res, "invalid value '%s' for option '--%s'", val, optn->brand); } else { GARGOYLE_MK_ERR(err, res, "invalid value for option '--%s'", optn->brand); } return err->code; } } else { const char *idx = arg + 1; for(; *idx; idx += 1) { optn = gargoyle_find_emblem(optc, optv, *idx, flags); 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; } } uint8_t res = 0; const char *val = NULL; if(optn->type & GARGOYLE_TYPE_BOOL) { res = gargoyle_from_bool(optn, "", "*", 1, flags); } else if(*(idx + 1)) { val = idx + 1; res = gargoyle_from_rope(optn, val, flags); break; } else { if(!*(*argv + 1)) { GARGOYLE_MK_ERR(err, GARGOYLE_ERR_VAL_REQUIRED, "option '-%c' requires a value", optn->emblem); return err->code; } *argc -= 1; *argv += 1; val = **argv; res = gargoyle_from_rope(optn, val, flags); } if(res) { if(val) { GARGOYLE_MK_ERR(err, res, "invalid value '%s' for option '-%c'", val, optn->emblem); } else { GARGOYLE_MK_ERR(err, res, "invalid value for option '-%c'", optn->emblem); } return err->code; } } } *argc -= 1; *argv += 1; } return GARGOYLE_ERR_SUCCESS; } 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) { if(flags & GARGOYLE_FLG_BCASE) { flags |= GARGOYLE_FLG_ICASE; } GARGOYLE_NEW_ERR(err); 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; struct gargoyle_optn *optn = gargoyle_find_brand(optc, optv, brand, "NO_", 3, flags); if(!optn) { 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; } else { continue; } } uint8_t res = 0; if(optn->type & GARGOYLE_TYPE_BOOL) { res = gargoyle_from_bool(optn, brand, "NO_", 3, flags); } else { res = gargoyle_from_rope(optn, brand + optn->brand_sz + 1, flags); } if(res) { GARGOYLE_MK_ERR(err, res, "invalid value '%s' for variable '%.*s'", brand + optn->brand_sz + 1, optn->brand_sz, optn->brand); return err->code; } } return GARGOYLE_ERR_SUCCESS; }