You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ag...@apache.org on 2020/05/06 00:00:54 UTC

[incubator-nuttx] branch master updated: Improve proxy/stub parameter passing for variadic OS interfaces.

This is an automated email from the ASF dual-hosted git repository.

aguettouche pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 6906853  Improve proxy/stub parameter passing for variadic OS interfaces.
6906853 is described below

commit 6906853f8e2cb12407dfc73562ad2b3cdb0b49b1
Author: Gregory Nutt <gn...@nuttx.org>
AuthorDate: Tue May 5 15:02:07 2020 -0600

    Improve proxy/stub parameter passing for variadic OS interfaces.
    
    In the past a very low effort interface was used:
    
    - All parmeters were treated as though they were type uinptr_t, and
    - The maximum number of parmeters (6) was passed in all cases.
    
    The first is potentially wrong and the second is very inefficient.  This commit improves this by:
    
    - Making tools/mksyscall.c more intelligent, and
    - Extending the syntax for variadic functions.
    
    For example, in syscall.cvs, the open() API was represened like this:
    
        "open","fcntl.h","","int","const char*","int","..."
    
    In reality, open may take only a single optional argument of type mode_t which is not the same size as uintptr_t.  And there is not reason to pass 6 parameters in that case.
    
    And this has been extended to:
    
        "open","fcntl.h","","int","const char*","int","...","mode_t"
    
    The existence of the "mode_t" tells tools/mksyscall that there is at most one optional parameter and, if present, it is of type mode_t.
---
 syscall/syscall.csv          |  10 ++--
 syscall/syscall_lookup.h     |  12 ++---
 syscall/syscall_stublookup.c |  15 ++----
 tools/csvparser.h            |  54 ++++++++++------------
 tools/mksyscall.c            | 106 +++++++++++++++++++++++--------------------
 5 files changed, 96 insertions(+), 101 deletions(-)

diff --git a/syscall/syscall.csv b/syscall/syscall.csv
index 9a048da..980dcd0 100644
--- a/syscall/syscall.csv
+++ b/syscall/syscall.csv
@@ -41,7 +41,7 @@
 "if_indextoname","net/if.h","defined(CONFIG_NETDEV_IFINDEX)","FAR char *","unsigned int","FAR char *"
 "if_nametoindex","net/if.h","defined(CONFIG_NETDEV_IFINDEX)","unsigned int","FAR const char *"
 "insmod","nuttx/module.h","defined(CONFIG_MODULE)","FAR void *","FAR const char *","FAR const char *"
-"ioctl","sys/ioctl.h","","int","int","int","..."
+"ioctl","sys/ioctl.h","","int","int","int","...","unsigned int"
 "kill","signal.h","","int","pid_t","int"
 "link","unistd.h","defined(CONFIG_PSEUDOFS_SOFTLINKS)","int","FAR const char *","FAR const char *"
 "listen","sys/socket.h","defined(CONFIG_NET)","int","int","int"
@@ -54,7 +54,7 @@
 "mq_close","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","int","mqd_t"
 "mq_getattr","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","int","mqd_t","struct mq_attr *"
 "mq_notify","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","int","mqd_t","const struct sigevent*"
-"mq_open","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","mqd_t","const char*","int","..."
+"mq_open","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","mqd_t","const char*","int","...","mode_t","FAR struct mq_attr*"
 "mq_receive","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","ssize_t","mqd_t","char*","size_t","FAR unsigned int*"
 "mq_send","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","int","mqd_t","const char*","size_t","unsigned int"
 "mq_setattr","mqueue.h","!defined(CONFIG_DISABLE_MQUEUE)","int","mqd_t","const struct mq_attr *","struct mq_attr *"
@@ -66,12 +66,12 @@
 "nx_task_spawn","nuttx/spawn.h","defined(CONFIG_LIB_SYSCALL) && !defined(CONFIG_BUILD_KERNEL)","int","FAR const struct spawn_syscall_parms_s *"
 "nx_vsyslog","nuttx/syslog/syslog.h","","int","int","FAR const IPTR char*","FAR va_list*"
 "on_exit","stdlib.h","defined(CONFIG_SCHED_ONEXIT)","int","CODE void (*)(int, FAR void *)","FAR void *"
-"open","fcntl.h","","int","const char*","int","..."
+"open","fcntl.h","","int","const char*","int","...","mode_t"
 "opendir","dirent.h","","FAR DIR*","FAR const char*"
 "pgalloc", "nuttx/arch.h", "defined(CONFIG_BUILD_KERNEL)", "uintptr_t", "uintptr_t", "unsigned int"
 "poll","poll.h","","int","FAR struct pollfd*","nfds_t","int"
 "ppoll","poll.h","","int","FAR struct pollfd*","nfds_t","FAR const struct timespec *","FAR const sigset_t *"
-"prctl","sys/prctl.h", "CONFIG_TASK_NAME_SIZE > 0","int","int","..."
+"prctl","sys/prctl.h", "CONFIG_TASK_NAME_SIZE > 0","int","int","...","uintptr_t"
 "pread","unistd.h","","ssize_t","int","FAR void*","size_t","off_t"
 "pselect","sys/select.h","","int","int","FAR fd_set*","FAR fd_set*","FAR fd_set*","FAR const struct timespec *","FAR const sigset_t *"
 "pwrite","unistd.h","","ssize_t","int","FAR const void*","size_t","off_t"
@@ -133,7 +133,7 @@
 "select","sys/select.h","","int","int","FAR fd_set*","FAR fd_set*","FAR fd_set*","FAR struct timeval*"
 "sem_close","semaphore.h","defined(CONFIG_FS_NAMED_SEMAPHORES)","int","FAR sem_t*"
 "sem_destroy","semaphore.h","","int","FAR sem_t*"
-"sem_open","semaphore.h","defined(CONFIG_FS_NAMED_SEMAPHORES)","FAR sem_t*","FAR const char*","int","..."
+"sem_open","semaphore.h","defined(CONFIG_FS_NAMED_SEMAPHORES)","FAR sem_t*","FAR const char*","int","...","mode_t","unsigned int"
 "sem_post","semaphore.h","","int","FAR sem_t*"
 "sem_setprotocol","nuttx/semaphore.h","defined(CONFIG_PRIORITY_INHERITANCE)","int","FAR sem_t*","int"
 "sem_timedwait","semaphore.h","","int","FAR sem_t*","FAR const struct timespec *"
diff --git a/syscall/syscall_lookup.h b/syscall/syscall_lookup.h
index 2f23a23..845ddc5 100644
--- a/syscall/syscall_lookup.h
+++ b/syscall/syscall_lookup.h
@@ -77,7 +77,7 @@ SYSCALL_LOOKUP(sem_setprotocol,            2, STUB_sem_setprotocol)
 /* Named semaphores */
 
 #ifdef CONFIG_FS_NAMED_SEMAPHORES
-SYSCALL_LOOKUP(sem_open,                   6, STUB_sem_open)
+SYSCALL_LOOKUP(sem_open,                   4, STUB_sem_open)
 SYSCALL_LOOKUP(sem_close,                  1, STUB_sem_close)
 SYSCALL_LOOKUP(sem_unlink,                 1, STUB_sem_unlink)
 #endif
@@ -197,7 +197,7 @@ SYSCALL_LOOKUP(up_assert,                  2, STUB_up_assert)
  */
 
   SYSCALL_LOOKUP(close,                    1, STUB_close)
-  SYSCALL_LOOKUP(ioctl,                    6, STUB_ioctl)
+  SYSCALL_LOOKUP(ioctl,                    3, STUB_ioctl)
   SYSCALL_LOOKUP(read,                     3, STUB_read)
   SYSCALL_LOOKUP(write,                    3, STUB_write)
   SYSCALL_LOOKUP(pread,                    4, STUB_pread)
@@ -234,7 +234,7 @@ SYSCALL_LOOKUP(up_assert,                  2, STUB_up_assert)
   SYSCALL_LOOKUP(fcntl,                    6, STUB_fcntl)
   SYSCALL_LOOKUP(lseek,                    3, STUB_lseek)
   SYSCALL_LOOKUP(mmap,                     6, STUB_mmap)
-  SYSCALL_LOOKUP(open,                     6, STUB_open)
+  SYSCALL_LOOKUP(open,                     3, STUB_open)
   SYSCALL_LOOKUP(opendir,                  1, STUB_opendir)
   SYSCALL_LOOKUP(readdir,                  1, STUB_readdir)
   SYSCALL_LOOKUP(rewinddir,                1, STUB_rewinddir)
@@ -333,7 +333,7 @@ SYSCALL_LOOKUP(up_assert,                  2, STUB_up_assert)
   SYSCALL_LOOKUP(mq_close,                 1, STUB_mq_close)
   SYSCALL_LOOKUP(mq_getattr,               2, STUB_mq_getattr)
   SYSCALL_LOOKUP(mq_notify,                2, STUB_mq_notify)
-  SYSCALL_LOOKUP(mq_open,                  6, STUB_mq_open)
+  SYSCALL_LOOKUP(mq_open,                  4, STUB_mq_open)
   SYSCALL_LOOKUP(mq_receive,               4, STUB_mq_receive)
   SYSCALL_LOOKUP(mq_send,                  4, STUB_mq_send)
   SYSCALL_LOOKUP(mq_setattr,               3, STUB_mq_setattr)
@@ -379,7 +379,7 @@ SYSCALL_LOOKUP(up_assert,                  2, STUB_up_assert)
 /* The following is defined only if CONFIG_TASK_NAME_SIZE > 0 */
 
 #if CONFIG_TASK_NAME_SIZE > 0
-  SYSCALL_LOOKUP(prctl,                    5, STUB_prctl)
+  SYSCALL_LOOKUP(prctl,                    2, STUB_prctl)
 #endif
 
 /* The following is defined only if entropy pool random number generator
@@ -387,7 +387,7 @@ SYSCALL_LOOKUP(up_assert,                  2, STUB_up_assert)
  */
 
 #ifdef CONFIG_CRYPTO_RANDOM_POOL
-  SYSCALL_LOOKUP(getrandom,               2, STUB_getrandom)
+  SYSCALL_LOOKUP(getrandom,                2, STUB_getrandom)
 #endif
 
 /****************************************************************************
diff --git a/syscall/syscall_stublookup.c b/syscall/syscall_stublookup.c
index 1a6a47f..4c23470 100644
--- a/syscall/syscall_stublookup.c
+++ b/syscall/syscall_stublookup.c
@@ -81,8 +81,7 @@ uintptr_t STUB_getgid(int nbr);
 uintptr_t STUB_sem_close(int nbr, uintptr_t parm1);
 uintptr_t STUB_sem_destroy(int nbr, uintptr_t parm1);
 uintptr_t STUB_sem_open(int nbr, uintptr_t parm1, uintptr_t parm2,
-            uintptr_t parm3, uintptr_t parm4, uintptr_t parm5,
-            uintptr_t parm6);
+            uintptr_t parm3, uintptr_t parm4);
 uintptr_t STUB_sem_post(int nbr, uintptr_t parm1);
 uintptr_t STUB_sem_setprotocol(int nbr, uintptr_t parm1, uintptr_t parm2);
 uintptr_t STUB_sem_timedwait(int nbr, uintptr_t parm1, uintptr_t parm2);
@@ -190,8 +189,7 @@ uintptr_t STUB_nx_vsyslog(int nbr, uintptr_t parm1, uintptr_t parm2,
 
 uintptr_t STUB_close(int nbr, uintptr_t parm1);
 uintptr_t STUB_ioctl(int nbr, uintptr_t parm1, uintptr_t parm2,
-            uintptr_t parm3, uintptr_t parm4, uintptr_t parm5,
-            uintptr_t parm6);
+            uintptr_t parm3);
 uintptr_t STUB_read(int nbr, uintptr_t parm1, uintptr_t parm2,
             uintptr_t parm3);
 uintptr_t STUB_write(int nbr, uintptr_t parm1, uintptr_t parm2,
@@ -245,8 +243,7 @@ uintptr_t STUB_mmap(int nbr, uintptr_t parm1, uintptr_t parm2,
             uintptr_t parm6);
 uintptr_t STUB_munmap(int nbr, uintptr_t parm1, uintptr_t parm2);
 uintptr_t STUB_open(int nbr, uintptr_t parm1, uintptr_t parm2,
-            uintptr_t parm3, uintptr_t parm4, uintptr_t parm5,
-            uintptr_t parm6);
+            uintptr_t parm3);
 uintptr_t STUB_opendir(int nbr, uintptr_t parm1);
 uintptr_t STUB_readdir(int nbr, uintptr_t parm1);
 uintptr_t STUB_rewinddir(int nbr, uintptr_t parm1);
@@ -344,8 +341,7 @@ uintptr_t STUB_mq_close(int nbr, uintptr_t parm1);
 uintptr_t STUB_mq_getattr(int nbr, uintptr_t parm1, uintptr_t parm2);
 uintptr_t STUB_mq_notify(int nbr, uintptr_t parm1, uintptr_t parm2);
 uintptr_t STUB_mq_open(int nbr, uintptr_t parm1, uintptr_t parm2,
-            uintptr_t parm3, uintptr_t parm4, uintptr_t parm5,
-            uintptr_t parm6);
+            uintptr_t parm3, uintptr_t parm4);
 uintptr_t STUB_mq_receive(int nbr, uintptr_t parm1, uintptr_t parm2,
             uintptr_t parm3, uintptr_t parm4);
 uintptr_t STUB_mq_send(int nbr, uintptr_t parm1, uintptr_t parm2,
@@ -403,8 +399,7 @@ uintptr_t STUB_socket(int nbr, uintptr_t parm1, uintptr_t parm2,
 
 /* The following is defined only if CONFIG_TASK_NAME_SIZE > 0 */
 
-uintptr_t STUB_prctl(int nbr, uintptr_t parm1, uintptr_t parm2,
-            uintptr_t parm3, uintptr_t parm4, uintptr_t parm5);
+uintptr_t STUB_prctl(int nbr, uintptr_t parm1, uintptr_t parm2);
 
 /* The following is defined only if entropy pool random number generator
  * is enabled.
diff --git a/tools/csvparser.h b/tools/csvparser.h
index 1605f46..9f09d9d 100644
--- a/tools/csvparser.h
+++ b/tools/csvparser.h
@@ -1,35 +1,20 @@
 /****************************************************************************
  * tools/csvparser.h
  *
- *   Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
- *   Author: Gregory Nutt <gn...@nuttx.org>
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ *   http://www.apache.org/licenses/LICENSE-2.0
  *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- *    used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
  *
  ****************************************************************************/
 
@@ -51,6 +36,7 @@
 
 #define MAX_FIELDS    16
 #define MAX_PARMSIZE  256
+
 #define NAME_INDEX    0
 #define HEADER_INDEX  1
 #define COND_INDEX    2
@@ -58,13 +44,19 @@
 #define PARM1_INDEX   4
 
 /****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+typedef char csvparm_t[MAX_PARMSIZE];
+
+/****************************************************************************
  * Public Data
  ****************************************************************************/
 
-extern bool g_debug;
-extern char g_line[LINESIZE+1];
-extern char g_parm[MAX_FIELDS][MAX_PARMSIZE];
-extern int  g_lineno;
+extern bool      g_debug;
+extern char      g_line[LINESIZE + 1];
+extern csvparm_t g_parm[MAX_FIELDS];
+extern int       g_lineno;
 
 /****************************************************************************
  * Public Function Prototypes
diff --git a/tools/mksyscall.c b/tools/mksyscall.c
index 26f018d..ac8860b 100644
--- a/tools/mksyscall.c
+++ b/tools/mksyscall.c
@@ -1,35 +1,20 @@
 /****************************************************************************
  * tools/mksyscall.c
  *
- *   Copyright (C) 2011-2013 Gregory Nutt. All rights reserved.
- *   Author: Gregory Nutt <gn...@nuttx.org>
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ *   http://www.apache.org/licenses/LICENSE-2.0
  *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- *    used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
  *
  ****************************************************************************/
 
@@ -47,10 +32,6 @@
 #include "csvparser.h"
 
 /****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/****************************************************************************
  * Private Data
  ****************************************************************************/
 
@@ -221,7 +202,7 @@ static FILE *open_proxy(void)
   return stream;
 }
 
-static void generate_proxy(int nparms)
+static void generate_proxy(int nparms, csvparm_t *vartypes, int nvartypes)
 {
   FILE *stream = open_proxy();
   char formal[MAX_PARMSIZE];
@@ -315,20 +296,21 @@ static void generate_proxy(int nparms)
        * the varargs.
        */
 
-      if (nparms < 7)
+      if (nvartypes > 0)
         {
           fprintf(stream, "  va_list ap;\n");
 
-          for (i = nparms; i < 7; i++)
+          for (i = 0; i < nvartypes; i++)
             {
-              fprintf(stream, "  uintptr_t parm%d;\n", i);
+              fprintf(stream, "  %s parm%d;\n", vartypes[i], nparms + i);
             }
 
           fprintf(stream, "\n  va_start(ap, parm%d);\n", nparms - 1);
 
-          for (i = nparms; i < 7; i++)
+          for (i = 0; i < nvartypes; i++)
             {
-              fprintf(stream, "  parm%d = va_arg(ap, uintptr_t);\n", i);
+              fprintf(stream, "  parm%d = va_arg(ap, %s);\n",
+                      nparms + i, vartypes[i]);
             }
 
           fprintf(stream, "  va_end(ap);\n\n");
@@ -343,7 +325,12 @@ static void generate_proxy(int nparms)
    * are special cases.
    */
 
-  nactual = bvarargs ? 6 : nparms;
+  nactual = nformal;
+  if (bvarargs)
+    {
+      nactual += nvartypes;
+    }
+
   if (strcmp(g_parm[RETTYPE_INDEX], "void") == 0)
     {
       fprintf(stream, "  (void)sys_call%d(", nactual);
@@ -441,7 +428,7 @@ static void stub_close(FILE *stream)
     }
 }
 
-static void generate_stub(int nparms)
+static void generate_stub(int nparms, csvparm_t *vartypes, int nvartypes)
 {
   FILE *stream = open_stub();
   char formal[MAX_PARMSIZE];
@@ -487,11 +474,9 @@ static void generate_stub(int nparms)
 
       if (is_vararg(g_parm[PARM1_INDEX + i], i, nparms))
         {
-          /* Always receive six arguments in this case */
-
-          for (j = i + 1; j <= 6; j++)
+          for (j = 0; j < nvartypes; j++)
             {
-              fprintf(stream, ", uintptr_t parm%d", j);
+              fprintf(stream, ", uintptr_t parm%d", nparms + j);
             }
         }
       else
@@ -542,11 +527,9 @@ static void generate_stub(int nparms)
 
           if (is_vararg(actual, i, nparms))
             {
-              /* Always pass six arguments */
-
-              for (j = i + 1; j <= 6; j++)
+              for (j = 0; j < nvartypes; j++)
                 {
-                  fprintf(stream, ", parm%d", j);
+                  fprintf(stream, ", (%s)parm%d", vartypes[j], i + j + 1);
                 }
             }
           else
@@ -618,6 +601,7 @@ int main(int argc, char **argv, char **envp)
   FILE *stream;
   char *ptr;
   int ch;
+  int i;
 
   /* Parse command line options */
 
@@ -684,6 +668,9 @@ int main(int argc, char **argv, char **envp)
 
   while ((ptr = read_line(stream)) != NULL)
     {
+      csvparm_t *vartypes = NULL;
+      int nvartypes = 0;
+
       /* Parse the line from the CVS file */
 
       int nargs = parse_csvline(ptr);
@@ -693,14 +680,35 @@ int main(int argc, char **argv, char **envp)
           exit(8);
         }
 
+      /* Search for an occurrence of "...".  This is followed by the list
+       * types in the variable arguments.  The number of types is the
+       * maximum number of variable arguments.
+       */
+
+      for (i = PARM1_INDEX; i < nargs; i++)
+        {
+          if (strcmp(g_parm[i], "...") == 0)
+            {
+              nvartypes = nargs - i - 1;
+              nargs     = i + 1;
+
+              if (nvartypes > 0)
+                {
+                  vartypes = &g_parm[i + 1];
+                }
+
+              break;
+            }
+        }
+
       if (proxies)
         {
-          generate_proxy(nargs - PARM1_INDEX);
+          generate_proxy(nargs - PARM1_INDEX, vartypes, nvartypes);
         }
       else
         {
           g_stubstream = NULL;
-          generate_stub(nargs - PARM1_INDEX);
+          generate_stub(nargs - PARM1_INDEX, vartypes, nvartypes);
           if (g_stubstream != NULL)
             {
               fprintf(g_stubstream, "\n#endif /* __STUB_H */\n");