ken@gatech.edu (Ken Seefried III) (09/07/89)
--- 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). There is, however a catch. I also need to pass the parent widget ID to this routine. None of the several FM's that I have give any clue as to how I might do this. More or less, this is what I want to do (sans declarations, etc.): /*--------------------------------------------------------------------------*/ Widget Error( parent, va_list ) Widget parent; va_dcl { va_list vaargs; char *fmt; unsigned int foo = 0; Arg xmargs[ 24 ]; XmString msgStr_xm; Widget error_dialog; char buffer[ 1024 ]; va_start( vaargs ); fmt = va_arg( args, char * ); vsscanf( buffer, fmt, vaargs ); msgStr_xm = XmStringCreate( buffer, CS ); XtSetArgs( xmargs[ foo ], XmNmessageString, MsgStr_xm ); foo++; error_dialog = XmCreateErrorDialog( parent, "Error", xmargs, foo ); . . . /*-------------------------------------------------------------------------*/ Anyone have any insight into the deep dark mysteries of varargs? Any help would be greatly appreciated... ...ken seefried iii ...!<anywhere>!gatech!ken ken@gatech.edu
scs@hstbme.mit.edu (Steve Summit) (09/07/89)
In article <19199@gatech.edu> ken@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
gwyn@smoke.BRL.MIL (Doug Gwyn) (09/07/89)
In article <19199@gatech.edu> ken@gatech.edu (Ken Seefried III) writes: >Widget Error( parent, va_list ) > Widget parent; > va_dcl >{ >va_list vaargs; >char *fmt; > va_start( vaargs ); > fmt = va_arg( args, char * ); > vsscanf( buffer, fmt, vaargs ); >Anyone have any insight into the deep dark mysteries of varargs? Yes. There are several problems here. The first is that correct usage of varargs requires that the function definition start off like: Widget Error( va_alist ) va_dcl { va_list vaargs; Widget parent; char *fmt; va_start( vaargs ); parent = va_arg( vaargs, Widget ); fmt = va_arg( vaargs, char * ); Notice several differences, especially the use of va_alist (NOT va_list!). The second problem is that vsscanf() doesn't normally exist in C libraries. Therefore you'll have to provide one..