View mode: basic / threaded / horizontal-split · Log in · Help
July 17, 2012
K&R-style variadic functions
To my understanding this is legal C :

int foo ();

It's a K&R-style variadic functions, while their use is discouraged, 
they're still legal C.

If I, in D, declare a variadic function with C linkage that doesn't 
take, at least, one regular parameter the compiler will complain.

extern (C) int foo (...);

Error: variadic functions with non-D linkage must have at least one 
parameter

Does that mean I can't use a function like this from D?

I'm trying to figure out what my tool, DStep, should do when it 
encounters a function like this.

https://github.com/jacob-carlborg/dstep

-- 
/Jacob Carlborg
July 17, 2012
Re: K&R-style variadic functions
On Tuesday, 17 July 2012 at 06:56:17 UTC, Jacob Carlborg wrote:
> To my understanding this is legal C :
>
> int foo ();
>
> It's a K&R-style variadic functions, while their use is 
> discouraged, they're still legal C.



My eyes!! They're bleeding!!
July 17, 2012
Re: K&R-style variadic functions
On Tuesday, 17 July 2012 at 07:06:38 UTC, Mehrdad wrote:
> On Tuesday, 17 July 2012 at 06:56:17 UTC, Jacob Carlborg wrote:
>> To my understanding this is legal C :
>>
>> int foo ();
>>
>> It's a K&R-style variadic functions, while their use is 
>> discouraged, they're still legal C.
>
>
>
> My eyes!! They're bleeding!!

I had the "pleasure" to use K&R C in my early C days, around 
1992, yuck!
July 17, 2012
Re: K&R-style variadic functions
On 2012-07-17 09:06, Mehrdad wrote:

> My eyes!! They're bleeding!!

First I wanted to know if my interpretation is correct and then I was 
trying to figure out how my tool should behave if it encounters a 
function like this.

-- 
/Jacob Carlborg
July 17, 2012
Re: K&R-style variadic functions
On Tue, 17 Jul 2012 12:43:46 +0100, Jacob Carlborg <doob@me.com> wrote:

> On 2012-07-17 09:06, Mehrdad wrote:
>
>> My eyes!! They're bleeding!!
>
> First I wanted to know if my interpretation is correct and then I was  
> trying to figure out how my tool should behave if it encounters a  
> function like this.

After a bit of googling and a test with my local MSVC9 I think old-style  
variadics look like this:

#include <varargs.h>
#include <stdio.h>

void foo(va_alist)
	va_dcl
{
	va_list p;
	va_start(p);
	vprintf("%d %d %d\n", p);
}

void main()
{
	foo(1, 2, 3);
}

(the above runs and outputs "1 2 3" on the console)

The same syntax is/was supported by GNU C, see:
http://ftp.gnu.org/old-gnu/Manuals/glibc-2.2.3/html_chapter/libc_34.html#SEC676


I believe, if you see an "old-style" function declaration in a header file  
like:

	int foo ();

that you can't actually assume anything about it's parameters, it may have  
/any/ number of parameters, and may or may not be variadic.

e.g. see: http://msdn.microsoft.com/en-us/library/efx873ys.aspx

The "declaration" syntax shown there for a function with 2 arguments is  
simply:

	double old_style();

In short, I don't think you can produce a valid .di/d file for old-style  
declarations automatically, it will require a manual step where the user  
enters the function type-arguments.


However, if you see an old-style:

	int foo(void);

you can be sure it has 0 parameters and can happily produce:

extern (C) int foo();


So, I think you should assume no old-style function declarations but have  
a command line option/mode which assumes all functions declarations are  
old-style.  In this mode you would output something like..

extern (C) <return-type> <function-name>(/*TODO: add args here*/);

and require the user manually find and define these.

I can't think of any other way you could do it.

R

p.s. I found this copy of the C spec online:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf
section 6.7.5.3 appears to deal with function declarations.

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
July 17, 2012
Re: K&R-style variadic functions
On Tue, 17 Jul 2012 13:32:08 +0100, Regan Heath <regan@netmail.co.nz>  
wrote:

> On Tue, 17 Jul 2012 12:43:46 +0100, Jacob Carlborg <doob@me.com> wrote:
>
>> On 2012-07-17 09:06, Mehrdad wrote:
>>
>>> My eyes!! They're bleeding!!
>>
>> First I wanted to know if my interpretation is correct and then I was  
>> trying to figure out how my tool should behave if it encounters a  
>> function like this.
>
> After a bit of googling and a test with my local MSVC9 I think old-style  
> variadics look like this:
>
> #include <varargs.h>
> #include <stdio.h>
>
> void foo(va_alist)
> 	va_dcl
> {
> 	va_list p;
> 	va_start(p);
> 	vprintf("%d %d %d\n", p);
> }
>
> void main()
> {
> 	foo(1, 2, 3);
> }
>
> (the above runs and outputs "1 2 3" on the console)

Some follow up information, for interests sake.

1. va_dcl is defined in varargs.h as..
	#define va_dcl va_list va_alist;

So, the old-style variable args function definiton can be written:

	void foo(va_alist)
		va_list va_alist;
	{
		...	
	}

2. va_start in defined in varargs.h as..
	#define va_start(ap) ap = (va_list)&va_alist

So, it assumes a parameter called va_alist exists, and it simply takes the  
address of it.  A new style variadic uses a definition like this..

	#define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) +  
_INTSIZEOF(v) )

which takes the address of 'v' (which is the argument prior to the ...)  
then skips past it, obtaining the address of the first ... argument.

So, in effect they are doing the same thing, taking the address of the  
first variable argument.  In which case, I can only assume if we can call  
new-style variadics from D, we can call old-style ones as well - provided  
any preceding arguments to the va_alist argument are defined correctly,  
.e.g.

given this old-style function declaration:

	void foo();

which actually happens to match this old-style variadic function  
definition:

	void foo(a,b,va_alist)
		int a;
		int b;
		va_list va_alist;
	{
	}

we could produce the following:

	extern (C) void foo(/*TODO: add args here*/);

and, once the user filled in the args

	extern (C) void foo(int a, int b, ...);

it should be callable from D.. in fact I just did a test (albeit with a  
slightly different test case..)

[testdll.c]
#include <varargs.h>
#include <stdio.h>

__declspec( dllexport )
void foo(va_alist)
	va_list va_alist;
{
	va_list p;
	va_start(p);
	vprintf("%d %d %d\n", p);
}

(compiled with MSVC to dll and lib, lib converted with coffimplib to OMF  
format)

[test.d]
extern (C) void foo(int a, ...);

int main(string[] args)
{
	foo(1, 3, 5);
	return 0;
}

compile with dmd test.d testdll.lib, run test.exe, outputs "1 3 5" :)

But, this highlights one issue I was unaware of.  The D extern (C)  
declaration needs at least 1 parameter before the ..., having just:

extern (C) void foo(...);

is illegal.

In my specific case I could add "int a" as the first parameter, and all  
was well.  Each case will be different, and it's conceivable there is a C  
old-style variadic which takes /any/ type of first parameter, which could  
be a problem, however the key issue is the size of the argument.  If all  
types which could be passed are 32 bits big, then "int a" is sufficient to  
get it working in all cases.

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
July 17, 2012
Re: K&R-style variadic functions
On 2012-07-17 15:05, Regan Heath wrote:

> In my specific case I could add "int a" as the first parameter, and all
> was well.  Each case will be different, and it's conceivable there is a
> C old-style variadic which takes /any/ type of first parameter, which
> could be a problem, however the key issue is the size of the argument.
> If all types which could be passed are 32 bits big, then "int a" is
> sufficient to get it working in all cases.

It could just as well be no parameters.

-- 
/Jacob Carlborg
July 17, 2012
Re: K&R-style variadic functions
On 2012-07-17 14:32, Regan Heath wrote:

>
> After a bit of googling and a test with my local MSVC9 I think old-style
> variadics look like this:
>
> #include <varargs.h>
> #include <stdio.h>
>
> void foo(va_alist)
>      va_dcl
> {
>      va_list p;
>      va_start(p);
>      vprintf("%d %d %d\n", p);
> }
>
> void main()
> {
>      foo(1, 2, 3);
> }
>
> (the above runs and outputs "1 2 3" on the console)
>
> The same syntax is/was supported by GNU C, see:
> http://ftp.gnu.org/old-gnu/Manuals/glibc-2.2.3/html_chapter/libc_34.html#SEC676
>
>
>
> I believe, if you see an "old-style" function declaration in a header
> file like:
>
>      int foo ();
>
> that you can't actually assume anything about it's parameters, it may
> have /any/ number of parameters, and may or may not be variadic.

Clang seems to interpret it as a variadic function. Then if that is 
correct or not I don't know.

-- 
/Jacob Carlborg
July 17, 2012
Re: K&R-style variadic functions
On Tue, 17 Jul 2012 15:01:02 +0100, Jacob Carlborg <doob@me.com> wrote:

> On 2012-07-17 15:05, Regan Heath wrote:
>
>> In my specific case I could add "int a" as the first parameter, and all
>> was well.  Each case will be different, and it's conceivable there is a
>> C old-style variadic which takes /any/ type of first parameter, which
>> could be a problem, however the key issue is the size of the argument.
>> If all types which could be passed are 32 bits big, then "int a" is
>> sufficient to get it working in all cases.
>
> It could just as well be no parameters.

I believe old-style no parameter function declarations MUST have "void"  
i.e.

	int foo(void);

They cannot read:

	int foo();

The latter MUST have parameters, we just can't tell what they are.

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
July 17, 2012
Re: K&R-style variadic functions
On Tue, 17 Jul 2012 15:02:44 +0100, Jacob Carlborg <doob@me.com> wrote:

> On 2012-07-17 14:32, Regan Heath wrote:
>
>>
>> After a bit of googling and a test with my local MSVC9 I think old-style
>> variadics look like this:
>>
>> #include <varargs.h>
>> #include <stdio.h>
>>
>> void foo(va_alist)
>>      va_dcl
>> {
>>      va_list p;
>>      va_start(p);
>>      vprintf("%d %d %d\n", p);
>> }
>>
>> void main()
>> {
>>      foo(1, 2, 3);
>> }
>>
>> (the above runs and outputs "1 2 3" on the console)
>>
>> The same syntax is/was supported by GNU C, see:
>> http://ftp.gnu.org/old-gnu/Manuals/glibc-2.2.3/html_chapter/libc_34.html#SEC676
>>
>>
>>
>> I believe, if you see an "old-style" function declaration in a header
>> file like:
>>
>>      int foo ();
>>
>> that you can't actually assume anything about it's parameters, it may
>> have /any/ number of parameters, and may or may not be variadic.
>
> Clang seems to interpret it as a variadic function. Then if that is  
> correct or not I don't know.

All my googling for "old style" "variadic" etc returned the use of  
va_alist and va_dcl so I can't see where/why Clang would do what it's  
doing.

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
« First   ‹ Prev
1 2 3 4
Top | Discussion index | About this forum | D home