On 28 Feb 2005, 15:31:48, Rick Engebretson wrote:
OK, I've updated gpc and begun to probe for "clarification."
I'm glad an automated c-header translator is being discussed. The fpc people have such a tool and have translated libc. A terrific pascal development.
[...]
There is something else which has been exercising me, in respect of imports from Windows DLLs. In gcc, I can do something like this:
FARPROC foo; /*pointer to DLL function "char *foo (char *x, char * y, int z)" */
void main(){ char *str; HINSTANCE h = LoadLibrary ("myfoo.dll"); if (h > 0) { foo = GetProcAddress (h, "foo@12"); str = foo ("foo", "bar", 24); } }
In GPC, this kind of thing will (naturally) not work, because the (function) pointer "foo" cannot be passed arbitrary parameters like that. gcc happily accepts it (now, of course, if the parameters are wrong, then the program will GPF at the call "str = foo ...", and if the parameters are correct, then everything works correctly).
The question is: since GPC is based on gcc, is the capacity to accept something like this present in GPC? (the question whether it should be accepted of is of course a different thing). I personally would find it very useful (not for translating c headers, but for automated parsing of DLLs and automated imports of their exported symbols), although I can hear all the cries of "Pascal is a safe language and therefore should never accept something like this".
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
Prof A Olowofoyeku wrote:
There is something else which has been exercising me, in respect of imports from Windows DLLs. In gcc, I can do something like this:
FARPROC foo; /*pointer to DLL function "char *foo (char *x, char * y, int z)" */
void main(){ char *str; HINSTANCE h = LoadLibrary ("myfoo.dll"); if (h > 0) { foo = GetProcAddress (h, "foo@12"); str = foo ("foo", "bar", 24); } }
In GPC, this kind of thing will (naturally) not work, because the (function) pointer "foo" cannot be passed arbitrary parameters like that. gcc happily accepts it (now, of course, if the parameters are wrong, then the program will GPF at the call "str = foo ...", and if the parameters are correct, then everything works correctly).
The question is: since GPC is based on gcc, is the capacity to accept something like this present in GPC? (the question whether it should be accepted of is of course a different thing). I personally would find it very useful (not for translating c headers, but for automated parsing of DLLs and automated imports of their exported symbols), although I can hear all the cries of "Pascal is a safe language and therefore should never accept something like this".
GPC allows the following:
program foo; type fsi = function(s : string): integer; var fp : fsi; i : integer; function GetProcAddress : pointer; begin GetProcAddress := nil end; begin fp := fsi(GetProcAddress); i := fp('') end .
Of course, since my `GetProcAddress' return nil it will crash at runtime. However, with proper external declaration of `GetProcAddress' and `LoadLibrary' and assuming that fsi is correct it should work. On Windows you have to remember to use correct calling convention, but that is not different that calling external functions via import librarires.
So, AFAICS you can not entiterly omit info about arguments, but you can declare function variable of correct type and assign (casted) result of `GetProcAddress' to it.
On 4 Mar 2005 at 18:43, Waldek Hebisch wrote:
[...]
GPC allows the following:
program foo; type fsi = function(s : string): integer; var fp : fsi; i : integer; function GetProcAddress : pointer; begin GetProcAddress := nil end; begin fp := fsi(GetProcAddress); i := fp('') end .
Of course, since my `GetProcAddress' return nil it will crash at runtime. However, with proper external declaration of `GetProcAddress' and `LoadLibrary' and assuming that fsi is correct it should work. On Windows you have to remember to use correct calling convention, but that is not different that calling external functions via import librarires.
So, AFAICS you can not entiterly omit info about arguments
[...]
So, how come gcc can do it? Is this a peculiarity of C compilers, or is it something unique to gcc than cannot possibly be enabled in gpc?
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
Prof A Olowofoyeku wrote:
On 4 Mar 2005 at 18:43, Waldek Hebisch wrote:
[...]
GPC allows the following:
program foo; type fsi = function(s : string): integer; var fp : fsi; i : integer; function GetProcAddress : pointer; begin GetProcAddress := nil end; begin fp := fsi(GetProcAddress); i := fp('') end .
Of course, since my `GetProcAddress' return nil it will crash at runtime. However, with proper external declaration of `GetProcAddress' and `LoadLibrary' and assuming that fsi is correct it should work. On Windows you have to remember to use correct calling convention, but that is not different that calling external functions via import librarires.
So, AFAICS you can not entiterly omit info about arguments
[...]
So, how come gcc can do it? Is this a peculiarity of C compilers, or is it something unique to gcc than cannot possibly be enabled in gpc?
1) All parameters in C are passed by value. Pascal has both "by value" and "var" parameters, and the compiler needs declarations to correctly pass arguments. Also, Pascal constants represent values, and parameter types allow to
2) AFAIK even on Windows you need to specify correct calling convention, otherwise if it is different then the default the program will crash
3) Declaring functions without giving parameter types is considered bad practice in C. You _are_ allowed to declare function having variable parameters (number of parameters and their types vary), but that is different then no declaration
4) You can define variable argument functions in Pascal:
type fsi = function(...): integer;
The call will be performed as C call. Note that calling convention must match, and that constant arguments may go wrong (gpc tries to do what C compiler will do, but has less information).
On 4 Mar 2005 at 20:16, Waldek Hebisch wrote:
[...]
So, AFAICS you can not entiterly omit info about arguments
[...]
So, how come gcc can do it? Is this a peculiarity of C compilers, or is it something unique to gcc than cannot possibly be enabled in gpc?
- All parameters in C are passed by value. Pascal has both "by value" and "var" parameters, and the compiler needs declarations to correctly pass arguments. Also, Pascal constants represent values, and parameter types allow to
Yes.
- AFAIK even on Windows you need to specify correct calling convention, otherwise if it is different then the default the program will crash
Yes, I am aware of that. My original example was simply to illustrate that, with gcc, you can simply declare something as "FARPROC foo", and then use "foo" in any manner you wish (including passing it an arbitrary number of parameters). The success of such an exercise naturally depends on everything else being correct.
- Declaring functions without giving parameter types is considered bad practice in C. You _are_ allowed to declare function having variable parameters (number of parameters and their types vary), but that is different then no declaration
Yes.
You can define variable argument functions in Pascal:
type fsi = function(...): integer;
Ok. I believe it used to be that there wasn't any way to use this (other than to import C library routines that have variable arguments). It seems now that it can be used.
The call will be performed as C call. Note that calling convention must match, and that constant arguments may go wrong (gpc tries to do what C compiler will do, but has less information).
Ok. This is quite helpful. Thanks.
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
Prof A Olowofoyeku (The African Chief) wrote:
- AFAIK even on Windows you need to specify correct calling convention, otherwise if it is different then the default the program will crash
Yes, I am aware of that. My original example was simply to illustrate that, with gcc, you can simply declare something as "FARPROC foo", and then use "foo" in any manner you wish (including passing it an arbitrary number of parameters). The success of such an exercise naturally depends on everything else being correct.
`FARPROC' it not a standard C name. I suppose it's defined in some system header as something like:
int (far *) ()
or
int (far *) (...)
You can define variable argument functions in Pascal:
type fsi = function(...): integer;
Ok. I believe it used to be that there wasn't any way to use this (other than to import C library routines that have variable arguments). It seems now that it can be used.
Yes, that mostly corresponds to the C declaration above. Note that in both C and Pascal (GPC), the argument types and number are variable, but the return type must be given. (In C, if omitted in the declaration, it defaults to `int', which should be `CInteger' in GPC now, BTW.)
But this calling style is really only useful when the function really takes different kinds of arguments (like `printf' & co. do in C).
In this case, however, you want to import a specific routine from a dynamic library, and this routine usually does have a fixed number and types of arguments (unless it happens to be something like `printf', but that's the exception).
Therefore, it's better to declare the argument types in Pascal as Waldek showed in this first answer. The same would apply in C, BTW. Probably the C programmers are just a bit lazy, saving some declarations, but actually making the code less safe.
E.g., for the original example:
char *str;
str = foo ("foo", "bar", 24);
the correct corresponding GPC type would be:
type fsi = function (a, b: CString; c: CInteger): CString;
(Or `^function' does also work, but I suppose you prefer the BP style without `^'.)
Frank
On 5 Mar 2005 at 1:35, Frank Heckenbach wrote:
Prof A Olowofoyeku (The African Chief) wrote:
- AFAIK even on Windows you need to specify correct calling
convention, otherwise if it is different then the default the program will crash
Yes, I am aware of that. My original example was simply to illustrate that, with gcc, you can simply declare something as "FARPROC foo", and then use "foo" in any manner you wish (including passing it an arbitrary number of parameters). The success of such an exercise naturally depends on everything else being correct.
`FARPROC' it not a standard C name. I suppose it's defined in some system header as something like:
int (far *) ()
or
int (far *) (...)
It is described as a pointer. This is how it is defined: #define WINAPI __stdcall typedef int (WINAPI *FARPROC)();
You can define variable argument functions in Pascal:
type fsi = function(...): integer;
Ok. I believe it used to be that there wasn't any way to use this (other than to import C library routines that have variable arguments). It seems now that it can be used.
Yes, that mostly corresponds to the C declaration above. Note that in both C and Pascal (GPC), the argument types and number are variable, but the return type must be given. (In C, if omitted in the declaration, it defaults to `int', which should be `CInteger' in GPC now, BTW.)
But this calling style is really only useful when the function really takes different kinds of arguments (like `printf' & co. do in C).
In this case, however, you want to import a specific routine from a dynamic library, and this routine usually does have a fixed number and types of arguments (unless it happens to be something like `printf', but that's the exception).
Therefore, it's better to declare the argument types in Pascal as Waldek showed in this first answer. The same would apply in C, BTW. Probably the C programmers are just a bit lazy, saving some declarations, but actually making the code less safe.
E.g., for the original example:
char *str;
str = foo ("foo", "bar", 24);
the correct corresponding GPC type would be:
type fsi = function (a, b: CString; c: CInteger): CString;
Yes, that is the best way. However, the lazy way is sometimes useful for some quick&dirty stuff ...
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
Prof A Olowofoyeku (The African Chief) wrote:
`FARPROC' it not a standard C name. I suppose it's defined in some system header as something like:
int (far *) ()
or
int (far *) (...)
It is described as a pointer. This is how it is defined: #define WINAPI __stdcall typedef int (WINAPI *FARPROC)();
Basically my first guess. (I thought `far' was necessary since it's called `FARPROC', but apparently the naming is only a remnant for 16 bit times. And I didn't think of `__stdcall'.)
Frank
On 6 Mar 2005 at 8:17, Frank Heckenbach wrote:
Prof A Olowofoyeku (The African Chief) wrote:
`FARPROC' it not a standard C name. I suppose it's defined in some system header as something like:
int (far *) ()
or
int (far *) (...)
It is described as a pointer. This is how it is defined: #define WINAPI __stdcall typedef int (WINAPI *FARPROC)();
Basically my first guess. (I thought `far' was necessary since it's called `FARPROC', but apparently the naming is only a remnant for 16 bit times.
Indeed. This existed under 16-bit Windows as well.
And I didn't think of `__stdcall'.)
Which gives a warning under GPC - and I am not sure what the warning means. The declaration:
TYPE TDllFunc = FUNCTION : Pointer attribute(stdcall);
gives this warning: "warning: `stdcall' attribute only applies to function types"
I thought I was applying the attribute to a function type? So what's with the warning?
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
Prof A Olowofoyeku wrote:
Which gives a warning under GPC - and I am not sure what the warning means. The declaration:
TYPE TDllFunc = FUNCTION : Pointer attribute(stdcall);
gives this warning: "warning: `stdcall' attribute only applies to function types"
I thought I was applying the attribute to a function type? So what's with the warning?
Internally there is no variables of function type. Pascal function type is really a "reference" and was not recgnized by attribute handling code. The attribute was ignored, so the call would go wrong. The following should fix the problem:
--- p/declarations.c.bb 2005-03-08 03:21:43.209468768 +0100 +++ p/declarations.c 2005-03-08 03:21:49.310541264 +0100 @@ -2089,7 +2089,10 @@ } else tt = &TREE_CHAIN (*tt); - pascal_decl_attributes (d, attributes); + if (TREE_CODE (*d) == POINTER_TYPE || TREE_CODE (*d) == REFERENCE_TYPE) + pascal_decl_attributes (&(TREE_TYPE (*d)), attributes); + else + pascal_decl_attributes (d, attributes); }
void
Waldek Hebisch wrote:
Prof A Olowofoyeku wrote:
Which gives a warning under GPC - and I am not sure what the warning means. The declaration:
TYPE TDllFunc = FUNCTION : Pointer attribute(stdcall);
gives this warning: "warning: `stdcall' attribute only applies to function types"
I thought I was applying the attribute to a function type? So what's with the warning?
Internally there is no variables of function type. Pascal function type is really a "reference" and was not recgnized by attribute handling code. The attribute was ignored, so the call would go wrong. The following should fix the problem:
--- p/declarations.c.bb 2005-03-08 03:21:43.209468768 +0100 +++ p/declarations.c 2005-03-08 03:21:49.310541264 +0100 @@ -2089,7 +2089,10 @@ } else tt = &TREE_CHAIN (*tt);
- pascal_decl_attributes (d, attributes);
- if (TREE_CODE (*d) == POINTER_TYPE || TREE_CODE (*d) == REFERENCE_TYPE)
- pascal_decl_attributes (&(TREE_TYPE (*d)), attributes);
- else
- pascal_decl_attributes (d, attributes);
}
void
OK (chief56.pas), though I think we should add this:
--- p/declarations.c.orig Tue Mar 8 04:50:42 2005 +++ p/declarations.c Tue Mar 8 04:51:37 2005 @@ -2190,8 +2190,12 @@ } else tt = &TREE_CHAIN (*tt); - if (TREE_CODE (*d) == POINTER_TYPE || TREE_CODE (*d) == REFERENCE_TYPE) - pascal_decl_attributes (&(TREE_TYPE (*d)), attributes); + if ((TREE_CODE (*d) == POINTER_TYPE || TREE_CODE (*d) == REFERENCE_TYPE) + && TREE_CODE (TREE_TYPE (*d)) == FUNCTION_TYPE) + { + TREE_TYPE (*d) = build_type_copy (TREE_TYPE (*d)); + pascal_decl_attributes (&(TREE_TYPE (*d)), attributes); + } else pascal_decl_attributes (d, attributes); }
I'm not sure if the type copy is really necessary, but checking the target type is, otherwise such an attribute would go wrong:
{ FLAG -g0 }
program fjf1039 (Output);
type a = ^Byte attribute (aligned = 64);
begin if AlignOf (a) = 64 then WriteLn ('OK') else WriteLn ('failed ', AlignOf (a)) end.
(The `-g0' is there because dwarf2out seems to fail with this type ...)-:
Frank
On 8 Mar 2005 at 4:59, Frank Heckenbach wrote:
Waldek Hebisch wrote:
Prof A Olowofoyeku wrote:
Which gives a warning under GPC - and I am not sure what the warning means. The declaration:
TYPE TDllFunc = FUNCTION : Pointer attribute(stdcall);
gives this warning: "warning: `stdcall' attribute only applies to function types"
I thought I was applying the attribute to a function type? So what's with the warning?
Internally there is no variables of function type. Pascal function type is really a "reference" and was not recgnized by attribute handling code. The attribute was ignored, so the call would go wrong. The following should fix the problem:
--- p/declarations.c.bb 2005-03-08 03:21:43.209468768 +0100 +++ p/declarations.c 2005-03-08 03:21:49.310541264 +0100 @@ -2089,7 +2089,10 @@ } else tt = &TREE_CHAIN (*tt);
- pascal_decl_attributes (d, attributes);
- if (TREE_CODE (*d) == POINTER_TYPE || TREE_CODE (*d) ==
- REFERENCE_TYPE)
- pascal_decl_attributes (&(TREE_TYPE (*d)), attributes);
- else
- pascal_decl_attributes (d, attributes);
}
void
OK (chief56.pas), though I think we should add this:
--- p/declarations.c.orig Tue Mar 8 04:50:42 2005 +++ p/declarations.c Tue Mar 8 04:51:37 2005 @@ -2190,8 +2190,12 @@ } else tt = &TREE_CHAIN (*tt);
- if (TREE_CODE (*d) == POINTER_TYPE || TREE_CODE (*d) ==
REFERENCE_TYPE) - pascal_decl_attributes (&(TREE_TYPE (*d)), attributes); + if ((TREE_CODE (*d) == POINTER_TYPE || TREE_CODE (*d) == REFERENCE_TYPE) + && TREE_CODE (TREE_TYPE (*d)) == FUNCTION_TYPE) + { + TREE_TYPE (*d) = build_type_copy (TREE_TYPE (*d)); + pascal_decl_attributes (&(TREE_TYPE (*d)), attributes); + } else pascal_decl_attributes (d, attributes); }
I'm not sure if the type copy is really necessary, but checking the target type is, otherwise such an attribute would go wrong:
[...]
Both patches work ok. Problem fixed. Thanks.
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
Prof A Olowofoyeku (The African Chief) wrote:
There is something else which has been exercising me, in respect of imports from Windows DLLs. In gcc, I can do something like this:
FARPROC foo; /*pointer to DLL function "char *foo (char *x, char * y, int z)" */
void main(){ char *str; HINSTANCE h = LoadLibrary ("myfoo.dll"); if (h > 0) { foo = GetProcAddress (h, "foo@12"); str = foo ("foo", "bar", 24); } }
In GPC, this kind of thing will (naturally) not work, because the (function) pointer "foo" cannot be passed arbitrary parameters like that. gcc happily accepts it (now, of course, if the parameters are wrong, then the program will GPF at the call "str = foo ...", and if the parameters are correct, then everything works correctly).
The question is: since GPC is based on gcc, is the capacity to accept something like this present in GPC? (the question whether it should be accepted of is of course a different thing). I personally would find it very useful (not for translating c headers, but for automated parsing of DLLs and automated imports of their exported symbols), although I can hear all the cries of "Pascal is a safe language and therefore should never accept something like this".
Best regards, The Chief
Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
I'm not going to pretend expertise here.
But one irony comes to mind. Early Windows(eg; 3.0) passed "pascal parameters" to C lib functions and required their declaration as such. So we have come full circle.
Reading more of the "old" GPC manual finds mention of using the "CString" type in place of the "PChar" type. To me (GPC newbie) this is a necessary link between the two languages.
Rick Engebretson wrote:
Reading more of the "old" GPC manual finds mention of using the "CString" type in place of the "PChar" type. To me (GPC newbie) this is a necessary link between the two languages.
In GPC `CString' and `PChar' are equivalent. According to the usual naming convention `PChar' would mean a pointer to a char. Therefore I recommend using `CString' when it's meant as a C-style string, i.e. pointer to a sequence of characters terminated by a NUL character. (The fact that C doesn't distinguish between pointers to single elements and arrays doesn't have to mislead us.)
Frank
Frank Heckenbach wrote:
Rick Engebretson wrote:
Reading more of the "old" GPC manual finds mention of using the "CString" type in place of the "PChar" type. To me (GPC newbie) this is a necessary link between the two languages.
In GPC `CString' and `PChar' are equivalent. According to the usual naming convention `PChar' would mean a pointer to a char. Therefore I recommend using `CString' when it's meant as a C-style string, i.e. pointer to a sequence of characters terminated by a NUL character. (The fact that C doesn't distinguish between pointers to single elements and arrays doesn't have to mislead us.)
Frank
It is a good step towards less ambiguity in the pascal language.
Rick Engebretson wrote:
Prof A Olowofoyeku (The African Chief) wrote:
There is something else which has been exercising me, in respect of imports from Windows DLLs. In gcc, I can do something like this:
FARPROC foo; /*pointer to DLL function "char *foo (char *x, char * y, int z)" */
void main(){ char *str; HINSTANCE h = LoadLibrary ("myfoo.dll"); if (h > 0) { foo = GetProcAddress (h, "foo@12"); str = foo ("foo", "bar", 24); } }
In GPC, this kind of thing will (naturally) not work, because the (function) pointer "foo" cannot be passed arbitrary parameters like that. gcc happily accepts it (now, of course, if the parameters are wrong, then the program will GPF at the call "str = foo ...", and if the parameters are correct, then everything works correctly). The question is: since GPC is based on gcc, is the capacity to accept something like this present in GPC? (the question whether it should be accepted of is of course a different thing). I personally would find it very useful (not for translating c headers, but for automated parsing of DLLs and automated imports of their exported symbols), although I can hear all the cries of "Pascal is a safe language and therefore should never accept something like this".
Best regards, The Chief
Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
I'm not going to pretend expertise here.
But one irony comes to mind. Early Windows(eg; 3.0) passed "pascal parameters" to C lib functions and required their declaration as such. So we have come full circle.
To quote from "Charles Petzold; Programming Windows 3.1," 1992, Microsoft Press, page 12.
/* You use these Windows functions in your Windows program the same way you use C library functions such as "strlen." However, there are some differences between the Windows functions and the standard C library functions. Windows functions are always declared as "far pascal" functions. The "far" keyword... The "pascal" keyword indicates the functions calling sequence is different than the normal C calling sequence. ... The "pascal" calling sequence is used in Windows because it is more efficient.*/
I don't know if later Windows is the same or not.
On 7 Mar 2005 at 8:11, Rick Engebretson wrote:
Rick Engebretson wrote:
[...]
But one irony comes to mind. Early Windows(eg; 3.0) passed "pascal parameters" to C lib functions and required their declaration as such. So we have come full circle.
To quote from "Charles Petzold; Programming Windows 3.1," 1992, Microsoft Press, page 12.
/* You use these Windows functions in your Windows program the same way you use C library functions such as "strlen." However, there are some differences between the Windows functions and the standard C library functions. Windows functions are always declared as "far pascal" functions. The "far" keyword... The "pascal" keyword indicates the functions calling sequence is different than the normal C calling sequence. ... The "pascal" calling sequence is used in Windows because it is more efficient.*/
I don't know if later Windows is the same or not.
Win32 API functions mainly use the stdcall convention. But while this is an interesting discussion, none of this is what I was referring to in my original mail ;-). I was talking about gcc's (and now GPC's) ability to pass an arbitrary number of parameters to certain function pointers.
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
"Prof A Olowofoyeku (The African Chief)" wrote:
... snip ...
Win32 API functions mainly use the stdcall convention. But while this is an interesting discussion, none of this is what I was referring to in my original mail ;-). I was talking about gcc's (and now GPC's) ability to pass an arbitrary number of parameters to certain function pointers.
I certainly hope you are misinterpreting the built in expansion for read, write, readln, writeln, and with. Variadic functions are one of the fundamental insecurities of C, and simply cannot be made secure. They have no place in a grown up language.
CBFalconer wrote:
I certainly hope you are misinterpreting the built in expansion for read, write, readln, writeln, and with. Variadic functions are one of the fundamental insecurities of C, and simply cannot be made secure. They have no place in a grown up language.
I completely agree. There is a language hierarchy, and pascal is the grown-up language.
C was introduced to replace assembler for systems programmers. It is a simple language that depends on simple calls to simple functions. C function calls get used, then dumped. The C library is nicely broken up for us. I think the FPC monolithic libc unit is a mistake. My interest is not graphics (as it might have seemed), but instrumentation.
I have a lot to learn about GPC, and like reading my "old" printed manual. I am learning many new high level pascal constructs. Fun reading, thanks.
On 7 Mar 2005 at 10:44, CBFalconer wrote:
"Prof A Olowofoyeku (The African Chief)" wrote:
... snip ...
Win32 API functions mainly use the stdcall convention. But while this is an interesting discussion, none of this is what I was referring to in my original mail ;-). I was talking about gcc's (and now GPC's) ability to pass an arbitrary number of parameters to certain function pointers.
I certainly hope you are misinterpreting the built in expansion for read, write, readln, writeln, and with.
No, I am not. I was talking about something different (pointers to functions).
Variadic functions are one of the fundamental insecurities of C, and simply cannot be made secure. They have no place in a grown up language.
Perhaps.
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/