Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: varargs support



This adds varargs support: it's the ancient version that even works with
K&R C.  This means you get error messages if you use it with gcc, which
I don't think is a problem since all versions of gcc since 1 million BC
support stdarg (I tested it by commenting out the stdarg support), but
also possibly with other compilers, which doesn't strike me as a big
problem since they mustn't be properly ISO compliant anyway.

It would be neater to make makepro.awk do more of the work, but I don't
understand makepro.awk well enough to do that.

I've also made dputs() use variable argument lists for debugging in case
it's useful.  The formatting done is identical to that for error
messages.  We shouldn't go overboard on this in case we get problems
with recursion (e.g. if there's an error in nicechar()).  There's a side
effect since it uses zerrmsg() which does a little extra formatting at
the start, but I don't think that's a problem for debugging.

Index: configure.ac
===================================================================
RCS file: /cvsroot/zsh/zsh/configure.ac,v
retrieving revision 1.53
diff -u -r1.53 configure.ac
--- configure.ac	30 May 2006 22:35:03 -0000	1.53
+++ configure.ac	5 Jun 2006 16:40:24 -0000
@@ -552,7 +552,7 @@
 AC_CHECK_HEADERS(sys/time.h sys/times.h sys/select.h termcap.h termio.h \
 		 termios.h sys/param.h sys/filio.h string.h memory.h \
 		 limits.h fcntl.h libc.h sys/utsname.h sys/resource.h \
-		 locale.h errno.h stdio.h stdarg.h stdlib.h \
+		 locale.h errno.h stdio.h stdarg.h varargs.h stdlib.h \
 		 unistd.h sys/capability.h \
 		 utmp.h utmpx.h sys/types.h pwd.h grp.h poll.h sys/mman.h \
 		 netinet/in_systm.h pcre.h langinfo.h wchar.h stddef.h \
Index: Src/makepro.awk
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/makepro.awk,v
retrieving revision 1.2
diff -u -r1.2 makepro.awk
--- Src/makepro.awk	2 Aug 2000 18:01:51 -0000	1.2
+++ Src/makepro.awk	5 Jun 2006 16:40:26 -0000
@@ -49,15 +49,17 @@
 	if(line ~ /\/\*/)
 	    continue
 	# If it is a function definition, note so.
-	if(line ~ /\) *[{].*$/) #}
+	if(line ~ /\) *(VA_DCL )*[{].*$/) #}
 	    isfunc = 1
 	if(sub(/ *[{;].*$/, "", line)) #}
 	    break
     }
-    # Put spaces around each identifier.
-    while(match(line, /[^_0-9A-Za-z ][_0-9A-Za-z]/) ||
-	    match(line, /[_0-9A-Za-z][^_0-9A-Za-z ]/))
-	line = substr(line, 1, RSTART) " " substr(line, RSTART+1)
+    if (!match(line, /VA_ALIST/)) {
+	# Put spaces around each identifier.
+	while(match(line, /[^_0-9A-Za-z ][_0-9A-Za-z]/) ||
+	      match(line, /[_0-9A-Za-z][^_0-9A-Za-z ]/))
+	    line = substr(line, 1, RSTART) " " substr(line, RSTART+1)
+    }
     # Separate declarations into a type and a list of declarators.
     # In each declarator, "@{" and "@}" are used in place of parens to
     # mark function parameter lists, and "@!" is used in place of commas
@@ -87,45 +89,64 @@
     exported = " " dtype " " ~ / mod_export /
     line = substr(line, RLENGTH+1) ","
     # Handle each declarator.
-    while(match(line, /^[^,]*,/)) {
-	# Separate out the name from the declarator.  Use "@+" and "@-"
-	# to bracket the name within the declarator.  Strip off any
-	# initialiser.
-	dcltor = substr(line, 1, RLENGTH-1)
-	line = substr(line, RLENGTH+1)
-	sub(/\=.*$/, "", dcltor)
-	match(dcltor, /^([^_0-9A-Za-z]| const )*/)
-	dcltor = substr(dcltor, 1, RLENGTH) "@+" substr(dcltor, RLENGTH+1)
-	match(dcltor, /^.*@\+[_0-9A-Za-z]+/)
-	dcltor = substr(dcltor, 1, RLENGTH) "@-" substr(dcltor, RLENGTH+1)
-	dnam = dcltor
-	sub(/^.*@\+/, "", dnam)
-	sub(/@-.*$/, "", dnam)
-
+    if (match(line, /VA_ALIST/)) {
+	# Already has VARARGS handling.
 	# Put parens etc. back
-	gsub(/@[{]/, " _((", dcltor)
-	gsub(/@}/, "))", dcltor)
-	gsub(/@</, "(", dcltor)
-	gsub(/@>/, ")", dcltor)
-	gsub(/@!/, ",", dcltor)
-
-	# If this is exported, add it to the exported symbol list.
-	if(exported)
-	    printf "X%s\n", dnam
+	gsub(/@[{]/, "((", line)
+	gsub(/@}/, "))", line)
+	gsub(/@</, "(", line)
+	gsub(/@>/, ")", line)
+	gsub(/@!/, ",", line)
+	sub(/,$/, ";", line)
+	gsub(/mod_export/, "mod_import_function", dtype)
+	gsub(/VA_ALIST/, "VA_ALIST_PROTO", line)
+	sub(/ VA_DCL/, "", line)
 
-	# Format the declaration for output
-	dcl = dtype " " dcltor ";"
 	if(locality ~ /E/)
-	    dcl = "extern " dcl
-	if(isfunc)
-	    gsub(/ mod_export /, " mod_import_function ", dcl)
-	else
-	    gsub(/ mod_export /, " mod_import_variable ", dcl)
-	gsub(/@[+-]/, "", dcl)
-	gsub(/ +/, " ", dcl)
-	while(match(dcl, /[^_0-9A-Za-z] ./) || match(dcl, /. [^_0-9A-Za-z]/))
-	    dcl = substr(dcl, 1, RSTART) substr(dcl, RSTART+2)
-	printf "%s%s\n", locality, dcl
+	    dtype = "extern " dtype
+
+	printf "%s%s %s\n", locality, dtype, line
+    } else {
+	while(match(line, /^[^,]*,/)) {
+		# Separate out the name from the declarator.  Use "@+" and "@-"
+		# to bracket the name within the declarator.  Strip off any
+		# initialiser.
+		dcltor = substr(line, 1, RLENGTH-1)
+		line = substr(line, RLENGTH+1)
+		sub(/\=.*$/, "", dcltor)
+		match(dcltor, /^([^_0-9A-Za-z]| const )*/)
+		dcltor = substr(dcltor, 1, RLENGTH) "@+" substr(dcltor, RLENGTH+1)
+		match(dcltor, /^.*@\+[_0-9A-Za-z]+/)
+		dcltor = substr(dcltor, 1, RLENGTH) "@-" substr(dcltor, RLENGTH+1)
+		dnam = dcltor
+		sub(/^.*@\+/, "", dnam)
+		sub(/@-.*$/, "", dnam)
+
+		# Put parens etc. back
+		gsub(/@[{]/, " _((", dcltor)
+		gsub(/@}/, "))", dcltor)
+		gsub(/@</, "(", dcltor)
+		gsub(/@>/, ")", dcltor)
+		gsub(/@!/, ",", dcltor)
+
+		# If this is exported, add it to the exported symbol list.
+		if(exported)
+		    printf "X%s\n", dnam
+
+		# Format the declaration for output
+		dcl = dtype " " dcltor ";"
+		if(locality ~ /E/)
+		    dcl = "extern " dcl
+		if(isfunc)
+		    gsub(/ mod_export /, " mod_import_function ", dcl)
+		else
+		    gsub(/ mod_export /, " mod_import_variable ", dcl)
+		gsub(/@[+-]/, "", dcl)
+		gsub(/ +/, " ", dcl)
+		while(match(dcl, /[^_0-9A-Za-z] ./) || match(dcl, /. [^_0-9A-Za-z]/))
+		    dcl = substr(dcl, 1, RSTART) substr(dcl, RSTART+2)
+		printf "%s%s\n", locality, dcl
+	}
     }
 }
 
Index: Src/system.h
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/system.h,v
retrieving revision 1.40
diff -u -r1.40 system.h
--- Src/system.h	30 May 2006 22:35:03 -0000	1.40
+++ Src/system.h	5 Jun 2006 16:40:26 -0000
@@ -153,8 +153,48 @@
 # include <stdlib.h>
 #endif
 
+/*
+ * Stuff with variable arguments.  We use definitions to make the
+ * same code work with varargs (the original K&R-style, just to
+ * be maximally compatible) and stdarg (which all modern systems
+ * should have).
+ *
+ * Ideally this should somehow be merged with the tricks performed
+ * with "_" in makepro.awk, but I don't understand makepro.awk.
+ * Currently we simply rely on the fact that makepro.awk has been
+ * hacked to leave alone argument lists that already contains VA_ALIST
+ * except for removing the VA_DCL and turning VA_ALIST into VA_ALIST_PROTO.
+ */
 #ifdef HAVE_STDARG_H
 # include <stdarg.h>
+# define VA_ALIST1(x)		x, ...
+# define VA_ALIST2(x,y)		x, y, ...
+# define VA_ALIST_PROTO1(x)	VA_ALIST1(x)
+# define VA_ALIST_PROTO2(x,y)	VA_ALIST2(x,y)
+# define VA_DCL
+# define VA_DEF_ARG(x)
+# define VA_START(ap,x)		va_start(ap, x)
+# define VA_GET_ARG(ap,x,t)
+#else
+# if HAVE_VARARGS_H
+#  include <varargs.h>
+#  define VA_ALIST1(x)		va_alist
+#  define VA_ALIST2(x,y)	va_alist
+/*
+ * In prototypes, assume K&R form and remove the variable list.
+ * This is about the best we can do without second-guessing the way
+ * varargs works on this system.  The _ trick should be able to
+ * do this for us but we've turned it off here.
+ */
+#  define VA_ALIST_PROTO1(x)
+#  define VA_ALIST_PROTO2(x,y)
+#  define VA_DCL		va_dcl
+#  define VA_DEF_ARG(x)		x
+#  define VA_START(ap,x)	va_start(ap);
+#  define VA_GET_ARG(ap,x,t)	(x = va_arg(ap, t))
+# else
+#  error "Your system has neither stdarg.h or varargs.h."
+# endif
 #endif
 
 #ifdef HAVE_ERRNO_H
Index: Src/utils.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/utils.c,v
retrieving revision 1.121
diff -u -r1.121 utils.c
--- Src/utils.c	30 May 2006 22:35:03 -0000	1.121
+++ Src/utils.c	5 Jun 2006 16:40:26 -0000
@@ -78,11 +78,14 @@
     zerrmsg(fmt, ap);
 }
 
+
 /**/
 mod_export void
-zerr(const char *fmt, ...)
+zerr(VA_ALIST1(const char *fmt))
+VA_DCL
 {
     va_list ap;
+    VA_DEF_ARG(const char *fmt);
 
     if (errflag || noerrs) {
 	if (noerrs < 2)
@@ -90,7 +93,8 @@
 	return;
     }
 
-    va_start(ap, fmt);
+    VA_START(ap, fmt);
+    VA_GET_ARG(ap, fmt, const char *);
     zwarning(NULL, fmt, ap);
     va_end(ap);
     errflag = 1;
@@ -98,14 +102,19 @@
 
 /**/
 mod_export void
-zerrnam(const char *cmd, const char *fmt, ...)
+zerrnam(VA_ALIST2(const char *cmd, const char *fmt))
+VA_DCL
 {
     va_list ap;
+    VA_DEF_ARG(const char *cmd);
+    VA_DEF_ARG(const char *fmt);
 
     if (errflag || noerrs)
 	return;
 
-    va_start(ap, fmt);
+    VA_START(ap, fmt);
+    VA_GET_ARG(ap, cmd, const char *);
+    VA_GET_ARG(ap, fmt, const char *);
     zwarning(cmd, fmt, ap);
     va_end(ap);
     errflag = 1;
@@ -113,33 +122,60 @@
 
 /**/
 mod_export void
-zwarn(const char *fmt, ...)
+zwarn(VA_ALIST1(const char *fmt))
+VA_DCL
 {
     va_list ap;
+    VA_DEF_ARG(const char *fmt);
 
     if (errflag || noerrs)
 	return;
 
-    va_start(ap, fmt);
+    VA_START(ap, fmt);
+    VA_GET_ARG(ap, fmt, const char *);
     zwarning(NULL, fmt, ap);
     va_end(ap);
 }
 
 /**/
 mod_export void
-zwarnnam(const char *cmd, const char *fmt, ...)
+zwarnnam(VA_ALIST2(const char *cmd, const char *fmt))
+VA_DCL
 {
     va_list ap;
+    VA_DEF_ARG(const char *cmd);
+    VA_DEF_ARG(const char *fmt);
 
     if (errflag || noerrs)
 	return;
 
-    va_start(ap, fmt);
+    VA_START(ap, fmt);
+    VA_GET_ARG(ap, cmd, const char *);
+    VA_GET_ARG(ap, fmt, const char *);
     zwarning(cmd, fmt, ap);
     va_end(ap);
 }
 
 
+#ifdef DEBUG
+
+/**/
+mod_export void
+dputs(VA_ALIST1(const char *message))
+VA_DCL
+{
+    va_list ap;
+    VA_DEF_ARG(const char *message);
+
+    VA_START(ap, message);
+    VA_GET_ARG(ap, message, const char *);
+    zerrmsg(message, ap);
+    va_end(ap);
+    fflush(stderr);
+}
+
+#endif /* DEBUG */
+
 #ifdef __CYGWIN__
 /*
  * This works around an occasional problem with dllwrap on Cygwin, seen
@@ -4536,18 +4572,6 @@
     return 0;
 }
 
-#ifdef DEBUG
-
-/**/
-mod_export void
-dputs(char *message)
-{
-    fprintf(stderr, "%s\n", message);
-    fflush(stderr);
-}
-
-#endif /* DEBUG */
-
 /**/
 mod_export int
 mode_to_octal(mode_t mode)

-- 
Peter Stephenson <pws@xxxxxxx>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


To access the latest news from CSR copy this link into a web browser:  http://www.csr.com/email_sig.php



Messages sorted by: Reverse Date, Date, Thread, Author