src/c-types-parse.lisp: Parse `...' in argument lists.
authorMark Wooding <mdw@distorted.org.uk>
Sun, 30 Aug 2015 09:58:38 +0000 (10:58 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sun, 6 Sep 2015 11:11:37 +0000 (12:11 +0100)
Somehow this got missed out.  There are a number of bugs elsewhere,
where things can't cope with the `:ellipsis' marker, to be fixed in
subsequent commits.

src/c-types-parse.lisp

index 4a8e1d7..39a805e 100644 (file)
                          (cons #'identity name))))
 
               (argument-list ()
-                ;; [ 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)))
 
               (postfix-lparen ()
                 ;; Postfix: `(' argument-list `)'