Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 18 Jul 2001 19:34:08 +0200
From:      Sheldon Hearn <sheldonh@starjuice.net>
To:        freebsd-hackers@FreeBSD.org
Subject:   Weird <stdarg.h> problem in 4.3-STABLE
Message-ID:  <11254.995477648@axl.seasidesoftware.co.za>

next in thread | raw e-mail | index | archive | help

Hi folks,

I'm busy developing a libdaemon implementation and have come unstuck on
a weird problem with functions using variable argument lists in FreeBSD
4.3-STABLE.

What I really want is a static inline void function declared in a header
file and included in various source files, looking something like this:

static inline void
xdaemonwarn(char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	if (!daemon_quiet)
		warn(fmt, ap);
	va_end(ap);

	return;
}

GCC gives "syntax error before 'void'".  Fair enough.

So obviously, this should be implemented as a macro.  But GCC warns that
ANSI C doesn't support variable arguments to macros.  Fine.

So I give up on any semblence of efficiency and settle for a real
wrapper.  This is where things get interesting.  The stdarg(3) manual
page says this:

  Unlike the varargs macros, the stdarg macros do not permit programmers to
  code a function with no fixed arguments.  This problem generates work
  mainly when converting varargs code to stdarg code, but it also creates
  difficulties for variadic functions that wish to pass all of their argu­
  ments on to a function that takes a va_list argument, such as
  vfprintf(3).

This shouldn't apply to what I'm trying to do, because I have one fixed
argument.

However, the non-static, non-inline version of the code fragment above,
although compiling flawlessly, has trouble at runtime.  I call it with
two arguments:

	/* char *path = "/var/run/progname.pid"; */
	xdaemonwarn("mkpidfile: %s", path);

I get:

	progname: mkpidfile: <ha>: permission denied

where <ha> represents some high ascii rubbish!

So far, the only way I can make this work is:

1) Declare the wrapper functions as taking a bogus, unused first
   parameter that is an int:

	void
	xdaemonwarn(int i __unused, const char *fmt, ...)
	{
	...

2) In the prototype provided to dependent code (via private.h, which
   CAN'T be included by xdaemonwarn.c), "lie" about the function as
   follows:

	void	xdaemonwarn(const char *fmt, ...);

3) In the dependent code, call the function as per the lie:

	/* char *path = "/var/run/progname.pid"; */
	xdaemonwarn("mkpidfile: %s", path);

This works as expected.  I get no warnings from GCC with -Wall -ansi
-pedantic and the dependent code prints the expected output.

So, um, what the fsck is going on here? :-)

Ciao
Sheldon.

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?11254.995477648>