Path: utzoo!mnetor!uunet!lll-winken!lll-lcc!lll-tis!ames!rutgers!clyde!cbosgd!mandrill!hal!ncoast!allbery From: allbery@ncoast.UUCP (Phil Smith) Newsgroups: comp.unix.wizards Subject: Re: (simple?) varargs question Message-ID: <6911@ncoast.UUCP> Date: 27 Dec 87 18:37:52 GMT References: <10937@brl-adm.ARPA> Reply-To: allbery@ncoast.UUCP (Brandon Allbery) Followup-To: comp.unix.wizards Organization: Cleveland Public Access UN*X, Cleveland, Oh Lines: 64 As quoted from <10937@brl-adm.ARPA> by mrose@twg.arpa (Marshall Rose): +--------------- | Each of these routines starts with a fixed number of arguments, | followed by a format string and then a variable number of | arguments. Ultimately asprintf will call vsprintf or _doprnt to | format a string. The trick here is figuring out the declaration | and calling sequences of each of these routines since asprintf can | be called either 2 or 3 levels deep from the routine which actually made | a call with variable arguments. +--------------- My personal opinion is that nested varargs is a portability nightmare, but I admit that I don't know everything. (Still... how the *heck* do they pass a magic va_list in a tagged architecture?) Here's how I'd do it; it's guaranteed to work on byte-addressable machines, at least, and possibly on more "exotic" architectures if someone addressed the va_list portability. The information comes from varargs(3) and vprintf(3). foobar(va_alist) va_dcl { int level; char *fmt; va_list args; va_start(args); level = va_arg(args, int); fmt = va_arg(args, char *); _domsg(MT_LOG, level, fmt, args); va_end(args); } barbaz(va_alist) va_dcl { char *fmt; va_list args; va_start(args); fmt = va_arg(args, char *); _domsg(MT_DISP, 0, fmt, args); va_end(args); } _domsg(type, level, fmt, args) char *fmt; va_list args; { static char buf[20480]; if (level < msglevel[type]) return; vsprintf(buf, fmt, args); switch (type) { /* ... handle each type of message */ } } Basically, you pass the "opened" va_list to the function, just as with the vprintf(3) functions; the called function should then be able to va_arg() off the list. My portability worry is that e.g. Pyramids have a "hidden" state variable which will NOT be passed with the va_list, but is required for the va_arg() macro to work properly. -- Brandon S. Allbery, Moderator of comp.sources.misc {hoptoad,harvard!necntc,cbosgd,sun!mandrill!hal,uunet!hnsurg3}!ncoast!allbery [This space reserved for future quotes and similar brain twisters.]