[comp.unix.wizards] calling one varargs routine from another

mark@spider.co.uk (Mark Valentine) (10/28/89)

[If I had USENET postability this would be in comp.lang.c.  But I don't think
 it's entirely a waste of bandwidth here...]

Q:  Is there a portable way, both in ANSI and traditional C, to call a
    varargs function such as

	void error(char *message, ...)

    from another such as

	void fatal(char *message, ...)

    ?  For traditional C, my best guess would be something like

	#include <varargs.h>

	void
	fatal(va_alist)
	va_dcl
	{
		error(va_alist);
		exit(1);
	}

    (which actually worked for my test prog on a MIPS box, but not on a VAX).

    For ANSI C, the nearest I can get to expressing what I want is

	#include <stdarg.h>

	void
	fatal(char *message, ...)
	{
		va_list	args;

		va_start(args, message);
		error(message, args);
		va_end(args);
		exit(1);
	}

    which doesn't work on either the MIPS or VAX!  My test was

	main()
	{
		fatal("%d... %d... %d... bye!\n", 3, 2, 1);
	}

    I feel I'm missing something, but...  It would niggle me to expand a
    six-line error routine in each of a handful of wrappers!  On the other
    hand I guess if this were possible we wouldn't have v*printf().

#if 0
A:
#endif

		Mark.

-- 
Mark Valentine, Spider Systems <mark@spider.co.uk>            /\oo/\

gwyn@smoke.BRL.MIL (Doug Gwyn) (10/28/89)

In article <21293@adm.BRL.MIL> mark@spider.co.uk (Mark Valentine) writes:
-Q:  Is there a portable way, both in ANSI and traditional C, to call a
-    varargs function such as
-	void error(char *message, ...)
-    from another such as
-	void fatal(char *message, ...)

No, the best you can do is for the called function to accept a va_list
parameter that the caller initializes via va_start() from its own list.
Even then, I've heard of implementations that would do the wrong thing.

chris@mimsy.umd.edu (Chris Torek) (10/28/89)

[followups redirected to comp.lang.c]

In article <21293@adm.BRL.MIL> mark@spider.co.uk (Mark Valentine) writes:
>[If I had USENET postability this would be in comp.lang.c.  But I don't think
> it's entirely a waste of bandwidth here...]
>Q:  Is there a portable way, both in ANSI and traditional C, to call a
>    varargs function such as
>	void error(char *message, ...)
>    from another such as
>	void fatal(char *message, ...)

No.  However, it is easy to do without.  Viz:

void error(char *fmt, ...) {
	va_list ap;
	va_start(fmt, ap);
	verror(0, fmt, ap);
	va_end(ap);
}

void fatal(char *fmt, ...) {
	va_list ap;
	va_start(fmt, ap);
	verror(1, fmt, ap);
	va_end(ap);
}

void verror(int is_fatal, char *fmt, va_list ap) {
	static int errors;

	(void) vfprintf(stderr, fmt, ap);
	(void) putc('\n', stderr);
	if (++errors >= MAX_ERRORS) {
		(void) fprintf(stderr,
		    "(that makes %d errors; please try again)\n",
		    errors);
		is_fatal = 1;
	}
	if (is_fatal) {
		remove_temporary_files();
		unlock_resources();
		exit(EXIT_FAILURE);
	}
}
-- 
`They were supposed to be green.'
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris