PDA

View Full Version : 6 thinBasic_ParseString calls: VariableGetInfoEx nulls



Charles Pegge
23-08-2008, 10:43
Hi Eros

re: thinCore module sdk / Freebasic

This problem turned up when I started combining Asmosphere test programs, which involve 1 assembly pass for each test using o2_Asmo(src)

I trace the problem down to thinBasic_ParseString causing VariableGetInfoEx to yield a null pointer to a variable which definitely exists in the script. This happens after 6 thinBasic_ParseSring calls corresponfing to 6 Asmo calls in the TB script.

This is the first time I have used multiple Asmo calls which explains why the problem has gone undetected until now.

The problem does not occur with thinBasic_ParseLong

Using a FreeBasic module complicates matters but if the bug remains hidden I can try to simulate using PB.

Any way here is the TB script:



Uses "Oxygen"
Uses "File"

dim dd as double
dim vv as long
dim ss as string
ss=string$(256," ")
dim zz as asciiz*256


dim src as string


' INSERT THESE LINES TO REGRESS THE FAILURE POINT
o2_asmo "ret"
'o2_asmo "ret"
'o2_asmo "ret"
'o2_asmo "ret"


src = "

symbols {}``^;>

>this is comment
^this is a quoted string^
mov eax,3
mov ecx,3
> using curly braces instead of round brackets
> for block scoping etc
{
inc eax
dec ecx
jge repeat
}
ret
"
o2_asmo src
if len(o2_error) then
'msgbox 0,o2_exec
msgbox 0,"ZM1: "+o2_error()+o2_view (src)
stop
end if

'------------------------------------------------------

src= "

nop

; divert symbols then create macro definitions of
; brackets and comments
; (quote marks cannot be defined in this way)
symbols ///////
def begin (
def end )
def cmt ;
symbols ()```;;
; symbols now restored
; begin end cmt are now available for use

cmt this is a comment
mov eax,3
mov ecx,3
begin
inc eax
dec ecx
jge repeat
end
ret
"

o2_asmo src
if len(o2_error) then
'msgbox 0,o2_exec
msgbox 0,"ZM2: "+o2_error()+o2_view (src)
stop
end if

'------------------------------------------------------

src="
def show
(
copy0 #zz, `%1 %2 %3 %4`
)

; invoke macro but prevent %params
; from being interpreted by using incl.

incl show

ret
"

o2_asmo src
if len(o2_error) then
'msgbox 0,o2_exec
msgbox 0,"ZM3: "+o2_error()+o2_view (src)
stop
end if

'------------------------------------------------------

src="
; using %% to hide parms
def show copy0 #zz, `%e %%ok%%`
show % params
ret
"

o2_asmo src
if len(o2_error) then
'msgbox 0,o2_exec
msgbox 0,"ZM4: "+o2_error()+o2_view (src)
stop
end if

'------------------------------------------------------

src="
; the strd and vald functions
edx=data nd 42.25
strd #zz,edx
vald #dd,#zz
ret
"

o2_asmo src

if len(o2_error) then
'msgbox 0,o2_exec
msgbox 0,"ZM5: "+o2_error()+o2_view (src)
stop
end if

'------------------------------------------------------


src="
mov eax,[#vv]
; note * pointer for reading dynamic string
vald #dd,*#ss
fld qword [#dd]
fsqrt
fstp qword [#dd]

ret
"

o2_asmo src
if len(o2_error) then
'msgbox 0,o2_exec
msgbox 0,"ZM6: "+o2_error()+o2_view (src)
stop
end if

'------------------------------------------------------

Charles Pegge
23-08-2008, 14:15
Got it!

The problem arises because thinBasicParseString returns a floating point value (EXT) on the FPU stack. If this is not popped, the acummulation of values messes up the FPU stack registers which are shared by other processes.

PB deals with this transparently but because EXT numbers are not native to FB, a workaround must be provided.

I will explore the cleanest way to do this.

ErosOlmi
23-08-2008, 18:34
Hi Charles. I'm just back from my last (for the moment) holiday week. Now I can reply with more time.

Sorry you found such a situation "thinBasic_ParseString". The reason why it returns an EXT value is because the same function can be used in many different situations where (for example) the value of the parse string is needed. It is also used for string logical comparisons. So if it find a string comparison (for example "str1 = str2" or "mid$(str1) = whatever"), it will return the logical value in the EXT return param.

You should use instead "thinBasic_Parse1String" function that just return a BSTR string.

What do you think?
Eros

Charles Pegge
23-08-2008, 20:11
Hi Eros,

All we need is a little Theology. If we declare this set of functions to return double instead of extended. Then Freebasic and C will be very happy, at least on the x86. The result is held in the FPU with full 80 bit precision. The SINGLE, DOUBLE or EXTENDED only determines the precision of the number when it is stored to memory. This gives us the cleanest implementation.

If the full precision is required, module side, then it can be pulled from the FPU using inline assembler instead of being handled directly in BASIC.

I am using this macro to handle thinBasic_ParseString. It does more than I need, capturing the result in a global variable 'ev' of type EXT. But the result could just as well be 'popped' off and discarded.



#macro ParseString(kBSTR)
pBSTR=@kBSTR
asm
push eax ' [pBSTR]
call thinBasic_ParseString
lea eax,[ev]
.byte &hdb, &h38
end asm
#endmacro


For most applications, I am sure that receiving the function result into a DOUBLE will be satisfactory, then there is no need to depart from conventional FreeBasic. So in my latest thinCore.bi, I uchanges these functions to

... ) AS DOUBLE 'EXT

ErosOlmi
23-08-2008, 21:03
1st) I say to use "thinBasic_Parse1String" but I was wrong.
"thinBasic_Parse1String" and "thinBasic_ParseString" are very different in what they do so they cannot be interchanged. In particular "thinBasic_Parse1String" also parse for possible "(" and ")" surrounding the string expression. Sorry.


2nd) about to change "thinBasic_ParseString" to return a DOUBLE instead of a EXT
I have to better study the situation and see the impact. As first sight I would like to say OK because we will bring wider compatibility without the need to personalize different versions of the same function. But because things are a bit more complex that the one we can discuss here, I would like to get some time to study where and in which situations will this change impact. I will give you back very soon.


Eros

ErosOlmi
23-08-2008, 21:05
Post moved to thinBasic SDK for Basic languages forum.

ErosOlmi
23-08-2008, 22:27
Ok, I've checked.
"thinBasic_ParseString" is exported by an internal function used in many places where a string expression may occurs. It is also used when there is a logical expression where one or more strings are involved. But the main reason why I cannot change the return type (EXT) is because it is used in all string to number conversions (in thinBasic you mix strings/numbers in expressions and thinBasic will make the necessary conversions). Changing from EXt to DOUBLE the return type we will lose EXT precision while converting a string to a number.

For the above reason(s) I think the best is to have 3 different ways to parse a string expression:


'---
' Parse one string expression including possible "(" and ")" before and after the string
' This function is the equavalent of the numeric thinBasic_Parse1Number
Declare Function thinBasic_Parse1StringLib "thinCore.DLL" Alias "thinBasic_Parse1String" () As String

'---
' Parse one string expression. It also returns the numeric representation of the parsed string in case it represents a valid number
Declare Function thinBasic_ParseStringLib "thinCore.DLL" Alias "thinBasic_ParseString" (ByRef sResult As String) As Ext

'---
' Parse one string expression.
Declare Sub thinBasic_ParseStrLib "thinCore.DLL" Alias "thinBasic_ParseStr"(ByRef sResult As String)



So, for example, FreeBasic can use "thinBasic_ParseStr" in order to deal just with a BSTR.

What do you think?
Eros

Charles Pegge
23-08-2008, 23:26
Yes that would be fine for strings Eros, if it is easy for you to implement, though we would still need to receive EXT numbers from the other functions and be able to deal with them appropriately.

Understanding what is being passed is the most important thing. - So I personally have no problem in using the thincore interface with FB as it is now.

With numbers returned on the FPU, there is in reality only 80 bit precision numbers and it is up to the programmer how to store a number from the FPU whether single, double, extended , short long or quad integer or packed BCD.

Similarly general integer types returned in the eax register can be handled as 8, 16 or 32 bit values - signed or unsigned. It is only the BASIC syntax which imposes a particular interpretation.

ErosOlmi
24-08-2008, 01:17
Perfect Charles.

For me it is very easy to implement the 3 mentioned functions. In reality I've already done them and I will send you very soon with the first new preview out in few days.
I agree with you: I need to improve documentation and details in SDK allowing precise info about what are parameters, parameters types, returning values/types. And this is what I'm doing right now: move all SDK functions into official help file with detailed info on how they work. It is a massive job writing all those stuffs in help but worth and needed to do. Maybe I will stop some new development I'm doing and will dedicate more time on this activity.

Eros