View Full Version : Variadic Functions
John Spikowski
30-08-2013, 18:39
Does thinBasic have the same limitation as PowerBASIC calling variadic style functions? I'm amazed this issue hasn't been address as there are tons of popular libraries out there that use variadic functions. (printf() is the most common) Jose took the Zale approach and immediately declared the process a security risk and these libraries (and I'm assuming the C language) should be ban from use. (sound familiar?)
For those unfamiliar with using variadic functions, this GNU reference (http://www.gnu.org/software/libc/manual/html_node/Variadic-Functions.html) should help.
It would seem thinBasic being an interpreter could deal with variadic functions easier than a compiler that ignores anything not PB.
@Eros - Could you you devise a method similar to this C example to handle variadic functions? Without this common function prototype support, the language is limited in it's reach.
#include <stdarg.h>
#include <stdio.h>
int
add_em_up (int count,...)
{
va_list ap;
int i, sum;
va_start (ap, count); /* Initialize the argument list. */
sum = 0;
for (i = 0; i < count; i++)
sum += va_arg (ap, int); /* Get the next argument value. */
va_end (ap); /* Clean up. */
return sum;
}
int
main (void)
{
/* This call prints 16. */
printf ("%d\n", add_em_up (3, 5, 5, 6));
/* This call prints 55. */
printf ("%d\n", add_em_up (10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
return 0;
}
ErosOlmi
31-08-2013, 10:51
Hi John,
I do not want to be negative :) because in reality such programming construct is quite interesting. But it is true that it created most of the worst buffer overflow security situations in programming history.
Anyway, no, thinBasic does not have such a construct. But it seemss quite easy to implement, native thinBasic functions like PRINTL or SUM already have any number of params.
Maybe one day if I will have nothing to do, I will think about that even without the need to pass the number of parameters and even mixing different parameters types. At the end passing an array of VARIANTS is something similar.
Ciao
Eros
ReneMiner
31-08-2013, 11:16
I think tB can do this pretty good and much better than the approach above - since this is limited to 31 parameters and one that tells number of parameters which is pretty obsolete.
This does 429496729 parameters because uses Ext-Type to get precise results.
Uses "console"
PrintL add_em_up(MKE$( 5, 5, 6 ))
PrintL add_em_up(MKE$( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ))
PrintL add_em_up(MKE$( 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5,10.5,11.5,12.5,13.5, _
14.5,15.5,16.5,17.5,18.5,19.5,20.5,21.5,22.5,23.5,24.5,25.5,26.5, _
27.5,28.5,29.5,30.5,31.5,32.5,33.5,34.5,35.5,36.5,37.5,38.5,39.5 ))
'... could continue here until fingers are bleeding...
WaitKey
Function add_em_up( ByVal sNumbers As String ) As Ext
If StrPtrLen(StrPtr(sNumbers)) < SizeOf(Ext) Then Return 0
Local eParam(StrPtrLen(StrPtr(sNumbers))/SizeOf(Ext)) As Ext At StrPtr(sNumbers)
Local eResult As Ext
Local i As Long
While i < UBound(eParam)
i += 1
eResult += eParam(i)
Wend
Function = eResult
End Function
ErosOlmi
31-08-2013, 11:26
René,
you are the King of virtual variables (DIM ... AT ...) :)
Here even shorter using thinBasic ARRAY SUM ...
Uses "console"
PrintL add_em_up(MKE$( 5, 5, 6 ))
PrintL add_em_up(MKE$( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ))
PrintL add_em_up(MKE$( 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5,10.5,11.5,12.5,13.5, _
14.5,15.5,16.5,17.5,18.5,19.5,20.5,21.5,22.5,23.5,24.5,25.5,26.5, _
27.5,28.5,29.5,30.5,31.5,32.5,33.5,34.5,35.5,36.5,37.5,38.5,39.5 ))
'... could continue here until fingers are bleeding...
WaitKey
Function add_em_up( ByVal sNumbers As String ) As Ext
If StrPtrLen(StrPtr(sNumbers)) < SizeOf(Ext) Then Return 0
Local eParam(StrPtrLen(StrPtr(sNumbers))/SizeOf(Ext)) As Ext At StrPtr(sNumbers)
Function = Array Sum eParam
End Function
ReneMiner
31-08-2013, 11:28
I knew tB can already do better than above suggested
John Spikowski
31-08-2013, 17:38
But it is true that it created most of the worst buffer overflow security situations in programming history.
And who told you that? Give me any link that says that variadic functions are the worse security nightmare of all time. Variadic fuctions are used in just about every C library I use. Personally I think you were told a line crap from Zale/Roca and they don't know what they're talking about. BASIC by design is full of potential security issues if your not careful. Calling variadic functions evil is a cop out just like Zale saying COM was a bloated mess then it became .NET is a bloated mess. His lies and technology never seemed to sync.
If you're truly interested in binary exploits, leave your OS biases at the door and have a peek at this document.
Mayhem Project Site (http://forallsecure.com/mayhem.html)
FYI Linux open source projects are being tested for free and I have submitted a request for ScriptBasic to be tested with Mayhem.
John Spikowski
31-08-2013, 18:13
Rene,
Thanks for your attempt at a variadic like function. It looks like it might work (for integers) if staying within the bounds of TB. Sorry to say that it doesn't help me calling IUP or any of the other C libraries that use variadic style functions.
I think using ScriptBasic's scriba_CallArgEX() is a good foundation to start with and maybe looking at stdarg.h may also be helpful.
This is a surprise. It looks like OxygenBasic and ScriptBasic are the only ANSI C complaint BASIC languages. (not counting BASIC to C translators like QB64, BaCon and MBC)
John
John Spikowski
05-09-2013, 07:19
I was browsing through Jose's SQLite3.inc file and noticed that the following functions haven't been properly translated. (nonFUNCTIONal) Should we assume all C related PowerBASIC/Jose include files will be much of the same?
'SQLITE_API int sqlite3_config(int, ...);
DECLARE FUNCTION sqlite3_config CDECL IMPORT "SQLITE3.DLL" ALIAS "sqlite3_config" ( _
BYVAL op AS LONG _ ' int
, OPTIONAL BYREF ANY _ ' optional parameters
, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY _
, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY _
) AS LONG ' int
'SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
DECLARE FUNCTION sqlite3_db_config CDECL IMPORT "SQLITE3.DLL" ALIAS "sqlite3_db_config" ( _
BYVAL hDbc AS DWORD _ ' sqlite3*
, BYVAL op AS LONG _ ' int op
, OPTIONAL BYREF ANY _ ' optional parameters
, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY _
, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY _
) AS LONG ' int
'SQLITE_API char *sqlite3_mprintf(const char*,...);
DECLARE FUNCTION sqlite3_mprintf CDECL IMPORT "SQLITE3.DLL" ALIAS "sqlite3_mprintf" ( _
BYREF szFormat AS ASCIIZ _ ' const char*
, OPTIONAL BYREF ANY _ ' optional parameters
, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY _
, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY _
) AS DWORD ' char *
'SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...);
DECLARE FUNCTION sqlite3_snprintf CDECL IMPORT "SQLITE3.DLL" ALIAS "sqlite3_snprintf" ( _
BYVAL bufLen AS LONG _ ' int
, BYREF szBuffer AS ASCIIZ _ ' const char*
, BYREF szFormat AS ASCIIZ _ ' const char*
, OPTIONAL BYREF ANY _ ' optional parameters
, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY _
, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY _
) AS DWORD ' char *
'SQLITE_API int sqlite3_test_control(int op, ...);
*** No translated PowerBASIC function DECLARE ***
'SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...);
DECLARE SUB sqlite3_log CDECL IMPORT "SQLITE3.DLL" ALIAS "sqlite3_log" ( _
BYVAL iErrCode AS LONG _ ' int iErrCode
, BYREF szFormat AS ASCIIZ _ ' const char *zFormat
, OPTIONAL BYREF ANY _ ' optional parameters
, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY _
, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY _
)
'SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
DECLARE FUNCTION sqlite3_vtab_config CDECL IMPORT "SQLITE3.DLL" ALIAS "sqlite3_vtab_config(" ( _
BYVAL hDbc AS DWORD _ ' sqlite3 *
, BYVAL op AS LONG _ ' int op
, OPTIONAL BYREF ANY _ ' optional parameters
, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY _
, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY, BYREF ANY _
) AS LONG ' int
John Spikowski
05-09-2013, 19:45
Sorry, but C++ clases can't be used with PB.
Another one to add to the list. :confused:
José Roca
05-09-2013, 20:10
> I was browsing through Jose's SQLite3.inc file and noticed that the following functions haven't been properly translated. (nonFUNCTIONal)
Do you mean that you don't know how to use them?
> Another one to add to the list.
Can SB or O2 use them? SB can't even call standard DLLs without a cane.
José Roca
05-09-2013, 20:33
Another one: SB only supports strings, longs and doubles.
Can you imagine what John will be saying if PB only supported these three types?
John Spikowski
05-09-2013, 20:41
Do you mean that you don't know how to use them?
Not your crippled, hand manipulated, multi-aliased versions of them. Don't convert headers to libraries PB can't support. As Bob would say, that's being silly.
Can SB or O2 use them? SB can't even call standard DLLs without a cane.
What part of SB is an embeddable multi-platform scripting API don't you get? The embedder determines what feature set and extension to enable based on their applications. You must be desperate to compare a hand crafted compiler to scripting engine.
José Roca
05-09-2013, 21:10
You can use them with PB. What happens is that you are too ignorant to do it.
I have also mentioned O2. Can O2 call these C++ classes?
Petr Schreiber
05-09-2013, 21:21
I am sorry, this thread got me back to highschool, this has no value for anyone.
To answer original question:
If you need thinBasic function with unlimited number of parameters of single type, pass array as last param
If you like the C approach, thinBasic module SDK allows to read params in loop as long as you want, so you can implement it that way via module (like PrintL does)
Abracadabra, thread closed.
Petr