size_t nn; \
\
for (k = kwfirst; k; k = va_arg(*ap, const char *)) { \
- if (!strcmp(k, "kw.valist")) { \
+ set##_KWSET(KWSET__ARGVA) \
+ /*else*/ if (!strcmp(k, "kw.valist")) { \
aap = va_arg(*ap, va_list *); \
kk = va_arg(*aap, const char *); \
set##_kwparse(kw, kk, aap, 0, 0); \
vv = va_arg(*ap, const struct kwval *); \
nn = va_arg(*ap, size_t); \
set##_kwparse(kw, 0, 0, vv, nn); \
- } \
- set##_KWSET(KWSET__ARGVA) \
- else kw_unknown(#set, k); \
+ } else kw_unknown(#set, k); \
} \
\
while (n) { \
- if (!strcmp(v->kw, "kw.valist")) { \
+ set##_KWSET(KWSET__ARGTAB) \
+ /*else*/ if (!strcmp(v->kw, "kw.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, "kw.tab")) { \
t = (const struct kwtab *)v->val; \
set##_kwparse(kw, 0, 0, t->v, t->n); \
- } \
- set##_KWSET(KWSET__ARGTAB) \
- else kw_unknown(#set, v->kw); \
+ } else kw_unknown(#set, v->kw); \
v++; n--; \
} \
}
+
#define KWSET__ARGVA(type, name, dflt) \
- else if (!strcmp(k, #name)) { \
+ if (!strcmp(k, #name)) { \
kw->name##_suppliedp = 1; \
kw->name = va_arg(*ap, type); \
- }
+ } else
#define KWSET__ARGTAB(type, name, dflt) \
- else if (!strcmp(v->kw, #name)) { \
+ if (!strcmp(v->kw, #name)) { \
kw->name##_suppliedp = 1; \
kw->name = *(type const *)v->val; \
- }
+ } else
/*----- Defining keyword-accepting functions ------------------------------*/
set "v->kw")))
(name (effective-method-keyword-parser-function-name method)))
+ ;; Deal with the special `kw.' keywords read via varargs. We're
+ ;; building the dispatch up backwards, so if we do these first, they
+ ;; get checked last, which priviliges the function-specific arguments
+ ;; over these special effects.
+ (codegen-push codegen)
+ (call "vv" "va_arg" "*ap" (c-type (* (struct "kwval" :const))))
+ (call "nn" "va_arg" "*ap" c-type-size-t)
+ (call :void name "kw" *null-pointer* "vv" "nn")
+ (setf va-act (namecheck "k" "kw.tab"
+ (codegen-pop-block codegen) va-act))
+
+ (codegen-push codegen)
+ (call "aap" "va_arg" "*ap" (c-type (* va-list)))
+ (call :void name "kw" "aap" *null-pointer* 0)
+ (setf va-act (namecheck "k" "kw.valist"
+ (codegen-pop-block codegen) va-act))
+
+ ;; Deal with the special `kw.' keywords read from a table.
+ (codegen-push codegen)
+ (deliver-expr codegen "t"
+ (format nil "(~A)v->val"
+ (c-type (* (struct "kwtab" :const)))))
+ (call :void name "kw" *null-pointer* "t->v" "t->n")
+ (setf tab-act (namecheck "v->kw" "kw.tab"
+ (codegen-pop-block codegen) tab-act))
+
+ (codegen-push codegen)
+ (convert "aap" (c-type (* va-list)))
+ (call :void name "kw" "aap" *null-pointer* 0)
+ (setf tab-act (namecheck "v->kw" "kw.valist"
+ (codegen-pop-block codegen) tab-act))
+
;; Work through the keywords. We're going to be building up the
;; conditional dispatch from the end, so reverse the (nicely sorted)
;; list before processing it.
(setf tab-act (namecheck "v->kw" key-name
(codegen-pop-block codegen) tab-act))))
- ;; Deal with the special `kw.' keywords read via varargs.
- (codegen-push codegen)
- (call "vv" "va_arg" "*ap" (c-type (* (struct "kwval" :const))))
- (call "nn" "va_arg" "*ap" c-type-size-t)
- (call :void name "kw" *null-pointer* "vv" "nn")
- (setf va-act (namecheck "k" "kw.tab"
- (codegen-pop-block codegen) va-act))
-
- (codegen-push codegen)
- (call "aap" "va_arg" "*ap" (c-type (* va-list)))
- (call :void name "kw" "aap" *null-pointer* 0)
- (setf va-act (namecheck "k" "kw.valist"
- (codegen-pop-block codegen) va-act))
-
;; Finish up the varargs loop.
(emit-banner codegen "Parse keywords from the variable-length tail.")
(codegen-push codegen)
(emit-inst codegen
(make-if-inst "ap" (make-block-inst nil (list loop)))))
- ;; Deal with the special `kw.' keywords read from a table.
- (codegen-push codegen)
- (deliver-expr codegen "t"
- (format nil "(~A)v->val"
- (c-type (* (struct "kwtab" :const)))))
- (call :void name "kw" *null-pointer* "t->v" "t->n")
- (setf tab-act (namecheck "v->kw" "kw.tab"
- (codegen-pop-block codegen) tab-act))
-
- (emit-banner codegen "Parse keywords from the argument table.")
- (codegen-push codegen)
- (convert "aap" (c-type (* va-list)))
- (call :void name "kw" "aap" *null-pointer* 0)
- (setf tab-act (namecheck "v->kw" "kw.valist"
- (codegen-pop-block codegen) tab-act))
-
;; Finish off the table loop.
+ (emit-banner codegen "Parse keywords from the argument table.")
(codegen-push codegen)
(emit-inst codegen tab-act)
(emit-inst codegen (make-expr-inst "v++"))