Jump to page: 1 25  
Page
Thread overview
K&R-style variadic functions
Jul 17, 2012
Jacob Carlborg
Jul 17, 2012
Mehrdad
Jul 17, 2012
Paulo Pinto
Jul 17, 2012
Jacob Carlborg
Jul 17, 2012
Regan Heath
Jul 17, 2012
Regan Heath
Jul 17, 2012
Jacob Carlborg
Jul 17, 2012
Regan Heath
Jul 17, 2012
Jacob Carlborg
Jul 17, 2012
Regan Heath
Jul 17, 2012
Jacob Carlborg
Jul 18, 2012
Regan Heath
Jul 18, 2012
Regan Heath
Jul 18, 2012
Jacob Carlborg
Jul 17, 2012
Regan Heath
Jul 17, 2012
Paulo Pinto
Jul 17, 2012
H. S. Teoh
Jul 18, 2012
Matt Soucy
Jul 18, 2012
Paulo Pinto
Jul 18, 2012
Regan Heath
Jul 18, 2012
H. S. Teoh
Jul 17, 2012
Jacob Carlborg
Jul 17, 2012
Regan Heath
Jul 17, 2012
Jacob Carlborg
Jul 17, 2012
Regan Heath
Jul 17, 2012
Paulo Pinto
Jul 18, 2012
Regan Heath
Jul 17, 2012
Jacob Carlborg
Jul 18, 2012
Regan Heath
Jul 17, 2012
deadalnix
Jul 17, 2012
Daniel Murphy
Jul 17, 2012
Lukasz
Jul 18, 2012
Walter Bright
Jul 18, 2012
Jacob Carlborg
Jul 18, 2012
Walter Bright
Jul 18, 2012
Jacob Carlborg
Jul 18, 2012
Walter Bright
Jul 19, 2012
Jacob Carlborg
Jul 19, 2012
Paulo Pinto
Jul 19, 2012
Regan Heath
Jul 19, 2012
Jacob Carlborg
July 17, 2012
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
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
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
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
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
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
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
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
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
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 5