(gethash kw *declspec-map*))))))
(cond ((or (not ds) (and predicate (not (funcall predicate ds))))
(values (list indicator) nil nil))
- ((ds-taggedp ds)
+ ((and (typep ds 'declspec) (ds-taggedp ds))
(scanner-step scanner)
(if (eq (token-type scanner) :id)
(let ((ty (make-c-tagged-type (ds-label ds)
(make-pointer-type type quals)))
(cdr state))))))
- (next-declspec-p ()
- ;; Ansert whether the next token is a valid declaration
- ;; specifier, without consuming it.
- (and (eq (token-type scanner) :id)
- (let ((id (token-value scanner)))
- (or (gethash id *module-type-map*)
- (gethash id *declspec-map*)))))
+ (predict-argument-list-p ()
+ ;; See `prefix-lparen'. Predict an argument list rather
+ ;; than a nested declarator if (a) abstract declarators are
+ ;; permitted and (b) the next token is a declaration
+ ;; specifier or ellipsis.
+ (let ((type (token-type scanner))
+ (value (token-value scanner)))
+ (and abstractp
+ (or (eq type :ellipsis)
+ (and (eq type :id)
+ (or (gethash value *module-type-map*)
+ (gethash value *declspec-map*)))))))
(prefix-lparen ()
;; Prefix: `('
;; specifier, then we have a postfix argument list.
(parse
(peek (seq (#\(
- (nil (if (and abstractp (next-declspec-p))
+ (nil (if (predict-argument-list-p)
(values nil nil nil)
(values t t nil))))
(lparen #\))))))
(cons #'identity name))))
(argument-list ()
- ;; [ argument [ `,' argument ]* ]
-
- (parse (list ()
- (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)))
(postfix-lparen ()
;; Postfix: `(' argument-list `)'