- ;; [ argument [ `,' argument ]* ]
-
- (parse (list (:min 0)
- (seq ((base-type (parse-c-type scanner))
- (dtor (parse-declarator scanner
- base-type
- :abstractp t)))
- (make-argument (cdr dtor) (car dtor)))
- #\,)))
+ ;; [ argument [ `,' argument ]* [ `,' `...' ] ] | `...'
+ ;;
+ ;; The possibility of a trailing `,' `...' means that we
+ ;; can't use the standard `list' parser. Note that, unlike
+ ;; `real' C, we allow an ellipsis even if there are no
+ ;; explicit arguments.
+
+ (let ((args nil))
+ (loop
+ (when (eq (token-type scanner) :ellipsis)
+ (push :ellipsis args)
+ (scanner-step scanner)
+ (return))
+ (multiple-value-bind (arg winp consumedp)
+ (parse (seq ((base-type (parse-c-type scanner))
+ (dtor (parse-declarator scanner
+ base-type
+ :abstractp t)))
+ (make-argument (cdr dtor) (car dtor))))
+ (unless winp
+ (if (or consumedp args)
+ (return-from argument-list (values arg nil t))
+ (return)))
+ (push arg args))
+ (unless (eq (token-type scanner) #\,)
+ (return))
+ (scanner-step scanner))
+ (values (nreverse args) t args)))