varargs and X

Steve Summit scs at hstbme.mit.edu
Thu Sep 7 13:39:17 AEST 1989


In article <19199 at gatech.edu> ken at gatech.edu (Ken Seefried III) writes:
>I'm trying to build a general purpose error notification routine
>for an X11/Motif application that I am writing.  I need to use
>varargs to get the error messages to the routine (printf() style).

I assume you want to call this routine with things like

	WidgetError(parentwidget, "funny name \"%s\"", name);

If you are using (old) varargs, I believe that your function's
argument list must contain only the va_alist.  You would have to
pull the widget ID out manually, as you do the printf format:

	WidgetError(va_alist)
	va_dcl
	{
	va_list	vaargs;
	Widget	parent;
	char	*fmt;
	char	buffer[1024];

	va_start(vaargs);
	parent = va_arg(args, Widget);
	fmt = va_arg(args, char *);
	vsprintf(buffer, fmt, vaargs);
	va_end(vaargs);

(Note that I have also removed a space from "Widget Error",
changed va_list in the formal parameters list to va_alist,
changed vsscanf to vsprintf, and added a "call" to va_end.)

The key is that the second argument to va_arg can be any type
descriptor.  (Actually, many implementations are buggy and break
if it's a char, but as long as sizeof(Widget) >= sizeof(int) it
should work.)

It would be worth your while to implement this in terms of the
new ANSI <stdarg.h> instead of the old <varargs.h>.  stdarg
dispenses with va_alist and va_dcl, and allows (nay, requires)
you to have fixed arguments before the variable ones.  The stdarg
implementation would look like this:

	WidgetError(parent, fmt, ...)
	Widget	parent;
	char	*fmt;
	{
	va_list	vaargs;
	char	buffer[1024];

	va_start(vaargs, fmt);
	vsprintf(buffer, fmt, vaargs);
	va_end(vaargs);

Note that, under stdarg, va_start takes the name of the last
fixed parameter as its second argument.

If you don't have an ANSI compiler, you can leave out the ", ..."
in the formals list, and va_start will (can) still work.  If you
don't have <stdarg.h>, I can supply one that should work on
"conventional," stack-based machines.  (I'd append it here, since
it's short, but the machine it's on is down.)

I don't know much about X, but it would be appropriate to provide
an Xwindowvprintf(window, fmt, ...) so that you could printf
things into windows without using the vsprintf/buffer dodge.
(Any fixed-size buffer will always be too big or too small.)
Of course, implementing Xwindowvprintf would be another story.
(From the looks of your example, you're "printing" not to a
window but to an XmString or a "dialog," so a vprintf analogue
would be appropriate for those objects as well.)

                                                Steve Summit



More information about the Comp.lang.c mailing list