*/
extern kw_unkhookfn *kw_unkhook;
+/*----- Atoms -------------------------------------------------------------*/
+
+#ifdef __arm__
+# define KW__SECTTY "%"
+#else
+# define KW__SECTTY "@"
+#endif
+
+#if defined(__GNUC__) && defined(__ELF__) && 0
+# define KWATOM_DECL(id, name) \
+ __asm__( ".ifndef " #id "\n" \
+ ".pushsection .rodata." #id ", " \
+ "\"aGS\", " KW__SECTTY "progbits, " \
+ ".rodata." #id ", comdat\n" \
+ ".globl " #id "\n" \
+ #id ": .asciz " #name "\n" \
+ ".popsection\n" \
+ ".endif"); \
+ extern const char id[]
+#endif
+
+#ifdef KWATOM_DECL
+# define KW_ATOM(id, name) id
+#else
+# define KWATOM_DECL(id, name) extern int kw__fake_##id
+# define KW_ATOM(id, name) (name + 0*sizeof(kw__fake_##id))
+#endif
+
+#define KADECL(atom) KWATOM_DECL(kw__atom__##atom, #atom)
+#define KA(atom) KW_ATOM(kw__atom__##atom, #atom)
+#define KA_TAB KW_ATOM(kw__atom_kw_tab, "kw.tab")
+#define KA_UNKNOWN KW_ATOM(kw__atom_kw_unknown, "kw.unknown")
+#define KA_VALIST KW_ATOM(kw__atom_kw_valist, "kw.valist")
+
+KWATOM_DECL(kw__atom_kw_tab, "kw.tab");
+KWATOM_DECL(kw__atom_kw_unknown, "kw.unknown");
+KWATOM_DECL(kw__atom_kw_valist, "kw.valist");
+
/*----- Argument list macros ----------------------------------------------*/
/* These macros are intended to be conveniences rather than a proper
* Use: Bundles a keyword @kw@ and value @val@ together.
*/
-#define K(kw, val) #kw, (val),
+#define K(kw, val) KA(kw), (val),
/* --- @K_VALIST@ --- *
*
* function.
*/
-#define K_VALIST(ap) "kw.valist", &(ap),
+#define K_VALIST(ap) KA_VALIST, &(ap),
/* --- @K_TAB@ --- *
*
* function.
*/
-#define K_TAB(v, n) "kw.tab", (v), (size_t)(n),
+#define K_TAB(v, n) KA_TAB, (v), (size_t)(n),
/*----- Keyword set definitions -------------------------------------------*
*
kw->name = *(type const *)v->val; \
} else
+#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
+
/*----- Defining keyword-accepting functions ------------------------------*/
/* --- @KWDECL@ --- *