comp.lang.ada
 help / color / mirror / Atom feed
From: "David Thompson" <david.thompson1@worldnet.att.net>
Subject: Re: Variable arguments magic in Ada to C code
Date: Fri, 16 Aug 2002 19:41:37 GMT
Date: 2002-08-16T19:41:37+00:00	[thread overview]
Message-ID: <Rzc79.15430$Ep6.1212452@bgtnsc05-news.ops.worldnet.att.net> (raw)
In-Reply-To: 87vg6nj8jd.fsf@almroth.com

Andreas Almroth <andreas-nntp@almroth.com> wrote :
> lutz@iks-jena.de (Lutz Donnerhacke) writes:
[ calling C variable-argument functions ]
> Well, I'm merely interfacing to an existing C library. I do heaps of type-
> and value checking before passing on to the C function, and thus trying to
> limit the consequences of incorrect arguments.
...
> > >When using VA in C, you build a list of pointers (System.Address) to your
> > >arguments, and terminate the list with NULL (Null_Ptr).
> >
Not true, at least not in general.  The actual argument-passing
mechanism(s), for both vararg and non-vararg functions, are not
defined by the C standard only by implementation(s) (so in principle
you need to say not "in C" but "in MSVC++6" or "in gcc 3.0" etc.),
but in practice at least varargs are passed in consecutive memory
(modulo padding needed for alignment) usually on the stack or
possibly in other "standard" (for the platform/architecture) places
like the VAX AP-addressed arglist or S/370 R1->caller memory.

For _some_ functions, some or even all of these arguments
are pointers, e.g. the *scanf family and in Unix/POSIX execl*.
The latter are terminated by a null pointer; the former are not.
For other functions, like *printf, (most of) the arguments are
not pointers at all.

There is an important distinction however between a function
which actually takes variable arguments, and a function which
takes a va_list (or pointer thereto), which is a single, fixed,
but opaque and implementation-dependent type that allows
the callee to access the variable-arguments of the _caller_.

> > No. You pass a controlling argument which is parsed and interpreted by the
> > called function. In my previous example it was simply a count value.
> >
Usually but not necessarily.  What is absolutely true is that
the called function must (be able to) determine the number
and type(s) of arguments somehow _before_ accessing them --
no checking or conversion is provided by the varargs mechanism.
This _may_ be the format specifier substrings in *printf/*scanf,
a null or other sentinel value as in execl*, a count,
or anything else you care to code that works for your data.
It _could_ be global/shared data, or a callback function,
or something even more bizarre, although if you do such things
don't expect anyone else to accept or reuse your code.

> > Inband-terminated arrays are used to pass arrays in C. In Ada you pass the
> > array bounds out of band, so you never need this data manipulation.
> >
Actually inband termination is mostly used in C for array of
character representing a string.  Arrays of other types are
(more?) commonly dimensioned by counts passed explicitly
or implicit in e.g. global state, and sentinel values IME rather
rarer though certainly used in some cases.

> > >You then pass the pointer to the list, as the last argument to the C
> > >function. With the VA_* macros you then traverse the pointers and type
> > >cast to whatever suitable (as in printf, you know by the format string
> > >what to expect).
> >
> > No, this is not the way stdarg works. You access the first few arguments of
> > the function and the iterativly get the next argument. There is no problem
> > in causing strange errors by calling a function with the wrong number of
> > arguments. The called function will reinterpret the stack as arguments or
> > crash or do something much more strange.
> >
>
To be a bit more specific:
The callee accesses all fixed arguments (parameters) as normal,
and the variable arguments iteratively using a va_list whose initialization
(by va_start) requires specifying the last fixed parameter (which must not
be of a type that gets automatically "adjusted") -- in practice this
(always?) accesses varargs which are passed in consecutive memory
either just after that last fixed argument or in a location determined by
the calling mechanism independent of the fixed argument(s),
and the va_list is really just a pointer that scans across that memory,
but that mechanism is not required.

Yes, if the callee does try to "receive" argument types that don't match
those the caller actually passed, except for a few minor variations
allowed by the default argument promotions and (arguably) type
compatibility rules, you get Undefined Behavior (= Ada erroneous)
which will typically do something Weird or Very Bad or both.

A vararg-callee can further pass its varargs (or a suffix of them)
as a block to lower-level routines, by passing the va_list.  It is
not defined whether va_list is an array type, and thus is effectively
passed by reference and shared rather than by value, so if you
need copy semantics -- that is you need to access the varargs
in both the direct-callee and a further-callee -- in C89 you can
and theoretically must create and destroy (va_end) separate or
disjoint va_list's, although in practice just copying the va_list
works, and C99 makes this official (va_copy).  For example,
printf can be implemented by just passing its arguments to
vprintf (or perhaps vfprintf) which does the actual work; you
can write your own vararg function which includes (modified)
printf semantics that also calls vprintf etc. etc.

(Aside:  saying that there is 'no problem' with something normally
connotes that it is OK, good, satisfactory, manageable.  I assume
you meant "there is no difficulty in causing (trouble)", but it is simpler
and IMO clearer to use the positive "it is easy to cause (trouble)".)

--
- David.Thompson 1 now at worldnet.att.net






      parent reply	other threads:[~2002-08-16 19:41 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-08-05 23:47 Variable arguments magic in Ada to C code Andreas Almroth
     [not found] ` <slrnakv5v0.p2.lutz@taranis.iks-jena.de>
2002-08-14 10:01   ` Florian Weimer
2002-08-14 11:34     ` Lutz Donnerhacke
2002-08-14 13:13       ` Dale Stanbrough
2002-08-14 13:59       ` Florian Weimer
2002-08-14 14:02         ` Lutz Donnerhacke
2002-08-15 10:09           ` Florian Weimer
2002-08-18 22:43             ` David Thompson
     [not found]   ` <87ptww7yj6.fsf@almroth.com>
     [not found]     ` <slrnal1l8s.pj.lutz@taranis.iks-jena.de>
     [not found]       ` <dstanbro-CDC252.20502007082002@news-server.bigpond.net.au>
2002-08-14  9:05         ` Lutz Donnerhacke
     [not found]       ` <87vg6nj8jd.fsf@almroth.com>
2002-08-16 19:41         ` David Thompson [this message]
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox