[comp.lang.c] varargs

chris@mimsy.UUCP (04/06/87)

In article <2285@ncoast.UUCP> allbery@ncoast.UUCP (Brandon Allbery) writes:
>Note that varargs is defined such that it will work even on machines such as
>the Pyramid which pass arguments in registers (common on RISC machines).

Or on the MIPS machines.

>You MUST declare only one argument -- va_alist -- and include the type of it
>as "va_dcl" without a semicolon.

`va_alist' and `va_dcl' are often (always?) macros.  It is conceivable
that on a machine that passes the first two arguments in registers and
the third through nth on the stack, these might be

	#define va_alist  _p1, _p2, _p3
	#define va_dcl int _p1, _p2, _p3;

in which case va_start might be

	#define va_start(l) { \
		struct _va_info _va; \
		_va.reg = 2; _va.r[1] = _p1; _va._r[0] = _p2; \
		_va.addr = &_p3; \
		(l) = &_va;

and va_arg then

	#define va_arg(l, t) \
		(sizeof(t) == 8 ? \	/* size always 8 or 4 in this arch. */
		 (ugly code to handle double float with spanning &c) : \
		 (--(l)->reg >= 0 ? *(t *)&(l)->r[(l)->reg] : \
		  ((l)->addr++, ((t *)((l)->addr))[-1])))

(and va_end would simply be defined as `}').

This would indeed preclude usage like

	f(fmt, va_alist)
		char *fmt;
		va_dcl
	{
		...

The reason I mention this is that in fact, on the Pyramid, Sun,
and Vax (all implementations of which I am aware), usages such as
that above in fact work.  I wonder, then, if this has been guaranteed
anywhere.  Has it?  (I know, I should dig out a copy of the X3J11
draft....)

>(C compilers can then recognize this directly to do any special
>processing needed, as for the Pyramid.)

Actually, Pyramid manages it without compiler hooks.  I believe
MIPS uses compiler hooks, though.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
UUCP:	seismo!mimsy!chris	ARPA/CSNet:	chris@mimsy.umd.edu

allbery@ncoast.UUCP (04/08/87)

As quoted from <6152@mimsy.UUCP> by chris@mimsy.UUCP (Chris Torek):
+---------------
| In article <2285@ncoast.UUCP> allbery@ncoast.UUCP (Brandon Allbery) writes:
| >Note that varargs is defined such that it will work even on machines such as
| >the Pyramid which pass arguments in registers (common on RISC machines).
| 
| Or on the MIPS machines.
+---------------

All I know about the MIPS machines is that Plexus supposedly makes one of them
(Plexus calls it the P/95, I think; no idea what MIPS calls it or what archi-
tecture it uses, but it's Plexus's only BSD machine.  Sigh.)

+---------------
| >You MUST declare only one argument -- va_alist -- and include the type of it
| >as "va_dcl" without a semicolon.
| 
| The reason I mention this is that in fact, on the Pyramid, Sun,
| and Vax (all implementations of which I am aware), usages such as
| that above in fact work.  I wonder, then, if this has been guaranteed
| anywhere.  Has it?  (I know, I should dig out a copy of the X3J11
| draft....)
+---------------

Dunno about X3J11, POSIX, /usr/group, etc., but the System V.2 docs state that
varargs must be used with va_alist as the ONLY argument.  Sure, it works on
stack machines where typecasting is mostly size changing or punning; but the
va_alist-only stuff is the only way to be compatible with all machines.

+---------------
| >(C compilers can then recognize this directly to do any special
| >processing needed, as for the Pyramid.)
| 
| Actually, Pyramid manages it without compiler hooks.  I believe
| MIPS uses compiler hooks, though.
+---------------

I've never used a Pyramid, so I was guessing.  However, it makes sense that
varargs should be set up so a compiler can recognize va_alist etc. as tokens
and generate the appropriate code.  I would guess that some architectures
might still not work; the ANSI C standard would fix this by allowing the
function's varargs status to be pre-declared.  (I hope; I know it was under
consideration once, but varargs might not be supported in a pre-declaration
in the current version of P1003.1.)

++Brando
-- 
 ____   ______________
/    \ / __   __   __ \   Brandon S. Allbery		|  QUOTE OF THE DAY:
 ___  | /__> /  \ /  \    aXcess Company		|
/   \ | |    `--, `--,    6615 Center St. #A1-105	|	  `
|     | \__/ \__/ \__/    Mentor, OH 44060-4101		|
\____/ \______________/   +1 216 974 9210		|
cbatt!cwruecmp!ncoast!allbery ncoast!allbery%case.CSNET@relay.CS.NET BALLBERY
	    (UUCP)                      (CSNET/Internet)             (MCIMail)

mash@mips.UUCP (04/09/87)

In article <2321@ncoast.UUCP> allbery@ncoast.UUCP (Brandon Allbery) writes:
>All I know about the MIPS machines is that Plexus supposedly makes one of them
>(Plexus calls it the P/95, I think; no idea what MIPS calls it or what archi-
>tecture it uses, but it's Plexus's only BSD machine.  Sigh.)

re: facts on MIPS machines
1) There's an M/500 that's been out a while, and a recently-announced M/800
(5X 11/780 & 8X, respectively). See comp.arch, <252@winchester.mips.UUCP>
2) In classic Silicon Valley style, where you often contract out manufacturing
early before you have the volume to do it inhouse, Plexus builds the
physical box & peripherals to our spec; we add our CPU & memories and
do the integration, test, software, etc.
Plexus does NOT sell this box, and it is definitely NOT called a P/95,
since it is not a Plexus system.
3) It uses a MIPS R2000 RISC CPU and R2010 FPU.
4) There are 2 UNIX ports: 1 is 4.3BSD, the other is SVR3.
-- 
-john mashey	DISCLAIMER: <generic disclaimer, I speak for me only, etc>
UUCP: 	{decvax,ucbvax,ihnp4}!decwrl!mips!mash, DDD:  	408-720-1700, x253
USPS: 	MIPS Computer Systems, 930 E. Arques, Sunnyvale, CA 94086

d90-pan@sm.luth.se (Per Andersson) (02/07/91)

I have a big problem using the varargs library.

What I want to do is to write a function that takes a variable number of
arguments and simply passes them on to another function like this:

	a_func( va_alist )
	va_dcl

	{
		...
		b_func( va_alist );
		...
	};

With this definition I would be able to write something like:

	a_func( "Hello world!", 42, &buf, 0 );

wich would result in b_func being called whith the same arguments.

Unfortunatley, this doesn't work to well.
The only thing I want to do is to pass ALL arguments on to b_func. It should
work like an indirect call to b_func.

Please help me!

By the way, I'm using a Sun 3-60 with SunOs V4.

| Per Andersson        | c/o Boman       | Voice natl.  0920 - 164 47   |
| University of Luleaa | Kungsgatan 16   |       intl. +46 920 164 47   |
| SWEDEN               | S-951 32 Luleaa | Internet: d90-pan@sm.luth.se |

gwyn@smoke.brl.mil (Doug Gwyn) (02/08/91)

In article <1428@tau.sm.luth.se> d90-pan@sm.luth.se (Per Andersson) writes:
>I have a big problem using the varargs library.

True.

>What I want to do is to write a function that takes a variable number of
>arguments and simply passes them on to another function like this:
>	a_func( va_alist )
>	va_dcl
>	{
>		b_func( va_alist );
>	};

	a_func( va_alist )
		va_dcl
		{
		va_list	ap;
		va_start( ap );
		b_func( ap );
		va_end( ap );
		}

	b_func( ap )
		va_list ap;
		{
		char *fmt = va_arg( ap, char * );
		...
		}