+#define KWSET_PARSEFN_ATOMS(set) \
+ void set##_kwparse(struct set##_kwargs *kw, \
+ const char *kwfirst, va_list *ap, \
+ const struct kwval *v, size_t n) \
+ { \
+ const char *k, *kk; \
+ va_list *aap; \
+ const struct kwtab *t; \
+ const struct kwval *vv; \
+ size_t nn; \
+ \
+ for (k = kwfirst; k; k = va_arg(*ap, const char *)) { \
+ set##_KWSET(KWSET__ARGVA_ATOM) \
+ /*else*/ if (k == KA_VALIST) { \
+ aap = va_arg(*ap, va_list *); \
+ kk = va_arg(*aap, const char *); \
+ set##_kwparse(kw, kk, aap, 0, 0); \
+ } else if (k == KA_TAB) { \
+ vv = va_arg(*ap, const struct kwval *); \
+ nn = va_arg(*ap, size_t); \
+ set##_kwparse(kw, 0, 0, vv, nn); \
+ } else set##_KWSET(KWSET__ARGVA) \
+ /*else*/ if (!strcmp(k, KA_VALIST)) { \
+ aap = va_arg(*ap, va_list *); \
+ kk = va_arg(*aap, const char *); \
+ set##_kwparse(kw, kk, aap, 0, 0); \
+ } else if (!strcmp(k, KA_TAB)) { \
+ vv = va_arg(*ap, const struct kwval *); \
+ nn = va_arg(*ap, size_t); \
+ set##_kwparse(kw, 0, 0, vv, nn); \
+ } else kw_unknown(#set, k); \
+ } \
+ \
+ while (n) { \
+ set##_KWSET(KWSET__ARGTAB) \
+ /*else*/ if (!strcmp(v->kw, KA_VALIST)) { \
+ aap = *(va_list *const *)v->val; \
+ kk = va_arg(*aap, const char *); \
+ set##_kwparse(kw, kk, aap, 0, 0); \
+ } else if (!strcmp(v->kw, KA_TAB)) { \
+ t = (const struct kwtab *)v->val; \
+ set##_kwparse(kw, 0, 0, t->v, t->n); \
+ } else kw_unknown(#set, v->kw); \
+ v++; n--; \
+ } \
+ }
+
+#define KWSET__ARGVA_ATOM(type, name, dflt) \
+ if (k == KA(name)) { \
+ kw->name##_suppliedp = 1; \
+ kw->name = va_arg(*ap, type); \
+ } else
+#define KWSET__ARGTAB_ATOM(type, name, dflt) \
+ if (v->kw == KA(name)) { \
+ kw->name##_suppliedp = 1; \
+ kw->name = *(type const *)v->val; \
+ } else
+
+#define KWSET__ARGVA(type, name, dflt) \
+ if (!strcmp(k, #name)) { \
+ kw->name##_suppliedp = 1; \
+ kw->name = va_arg(*ap, type); \
+ } else
+#define KWSET__ARGTAB(type, name, dflt) \
+ if (!strcmp(v->kw, #name)) { \
+ kw->name##_suppliedp = 1; \
+ kw->name = *(type const *)v->val; \
+ } else
+