Format string with some values like sprintf (C) - Update

Share your advanced PureBasic knowledge/code with the community.
User avatar
mk-soft
Always Here
Always Here
Posts: 5409
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Format string with some values like sprintf (C) - Update

Post by mk-soft »

Thanks for answers,

No Bug, because the parameter is from type Word (uVal) but %8X read type Long.

Code: Select all


IncludeFile "Format-v207.pbi"

aVal.a = $FF
uVal.u = $E0E0
lVal.l = $AAAAAAAA
qVal.q = $00EE00EE00EE00EE
temp.s = "Result:\n"
temp + "Hex2 = %2X\nHex4 = %4X\nHex8 = %8X\nHex16 = %16X\n\n"
temp + "Invalid read Hex8 on uVal = %8x"

result.s = format(temp, @aVal, @uVal, @lVal, @qVal, @uVal)
MessageRequester("Format like sprintf", result)
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
mk-soft
Always Here
Always Here
Posts: 5409
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Format string with some values like sprintf (C) - Update

Post by mk-soft »

Update v2.08
- Removed null character '\0' (It does not work)

Example

Code: Select all

IncludeFile "Format.pbi"

bVal.b = 100
wVal.w = 200
lVal.l = 300
iVal.i = 400
fVal.f = 500.0
dVal.d = -600.0
sVal.s = "Hello World"
aVal.a = 255
uVal.u = 65535

temp.s = "Result: \nByte = %b, \nWord = %w, \nLong = %l, \nInteger = %i, \nFloat = %10.2f, \nDouble = %-+10.2d, \n"
temp + "String = %s, \nUnsigned Byte = %a, \nUnsigned Word = %u,\n"
temp + "Hex = %2x, \nHex = %4X"

result.s = format(temp, @bVal, @wVal, @lVal, @iVal, @fVal, @dVal, @sVal, @aVal, @uVal, @aVal, @uVal)
MessageRequester("Format like sprintf", result)
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
pthien
Enthusiast
Enthusiast
Posts: 145
Joined: Sun Jun 29, 2003 9:39 pm

Re: Format string with some values like sprintf (C) - Update

Post by pthien »

Sorry to resurrect an old post.

But I'm trying to use this format function to help make my SQL commands.

But I cannot do a format("Test number %s",str(x)) because the format function wants me to pass by reference and I don't know how to pass the results of a function like Str() as a reference.

I can make an intermediate variable and it works:

number.s = str(x)
format("Test number %s",@number)

But I'd like to skip the extra steps.

Any ideas?

Also, is this format function still the way to go? When I compile I get a "Deprecated Str(Q)" message.

Thanks for all the help!
User avatar
mk-soft
Always Here
Always Here
Posts: 5409
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Format string with some values like sprintf (C) - Update

Post by mk-soft »

It´s only work with pointer to variable, but you don´t need Str(Number).

Code: Select all

Define number.q = 12345678
r1.s = format("Test quat number %q", @number)
Debug r1
SQL

Code: Select all

myTable$ = "Data1"
myNumber.q = 12345678
query$ = format("SELECT * FROM %s WHERE MyValue >= %q", @myTable$, @myNumber)
Debug query$
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
luis
Addict
Addict
Posts: 3876
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: Format string with some values like sprintf (C) - Update

Post by luis »

Did anyone ever tried this on x64 Linux ?

This test

Code: Select all

v1 = 1
v2 = 2
v3 = 3
v4 = 4
v5 = 5
v6 = 6
v7 = 7
v8 = 8
v9 = 9
v10 = 10
v11 = 11

t$ = Format("test %i, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i", @v1, @v2, @v3, @v4, @v5, @v6, @v7, @v8, @v9, @v10, @v11)

Debug t$

crashes for me with IMA on

Code: Select all

    Case 'i'
              If *value : help = Str ( *value\i ) : EndIf : IsValue = #True             
Tested with PB5.62 on Linux Mint x64
"Have you tried turning it off and on again ?"
A little PureBasic review
User avatar
luis
Addict
Addict
Posts: 3876
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: Format string with some values like sprintf (C) - Update

Post by luis »

I saw the code assumes it can move on the next parameter by adding the size of an integer to the pointer to the first parameter.
It works for the first param but crashes for the second.

OK, I looked at the stack, it seems the parameters on x64 Linux are 16 bits aligned and so are separated by 8 bytes.
In fact, if I change the line

Code: Select all

  *args + SizeOf ( Integer ) 
            Break
to

Code: Select all

  *args + SizeOf ( Integer ) * 2
            Break
the code works again.

Is this actually how it is supposed to be ? On x64 Windows the params are on the stack simply one after another.

UPDATE:
Maybe I found it. Looks like it's the Purifier.
Yes, it really looks like it's that. With the Purifier enabled the offset becomes 16 bytes instead of 8, but ONLY under Linux x64, everywhere else does not have any effect (?).
This is a problem because I can't enable the Purifier if the source is using this code. Maybe it's possible to disable it around the procedure, but I'm not crazy about it.
Last edited by luis on Wed Jul 18, 2018 10:54 pm, edited 3 times in total.
"Have you tried turning it off and on again ?"
A little PureBasic review
User avatar
idle
Always Here
Always Here
Posts: 5097
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Format string with some values like sprintf (C) - Update

Post by idle »

you could also try import a c function, if you get stuck, but it's not the same

Code: Select all

;d Or i	Signed decimal integer	392
;u	Unsigned decimal integer	7235
;o	Unsigned octal	610
;x	Unsigned hexadecimal integer	7fa
;X	Unsigned hexadecimal integer (uppercase)	7FA
;f	Decimal floating point, lowercase	392.65
;F	Decimal floating point, uppercase	392.65
;e	Scientific notation (mantissa/exponent), lowercase	3.9265e+2
;E	Scientific notation (mantissa/exponent), uppercase	3.9265E+2
;g	Use the shortest representation: %e Or %f	392.65
;G	Use the shortest representation: %E Or %F	392.65
;a	Hexadecimal floating point, lowercase	-0xc.90fep-2
;A	Hexadecimal floating point, uppercase	-0XC.90FEP-2
;c	Character	a
;s	String of characters	sample
;p	Pointer address	b8000000

ImportC ""
  swprintf(*str.string,format.s,*args,*args1=0,*args2=0,*args3=0,*args4=0,*args5=0,*args6=0,*args7=0,*args8=0) 
EndImport 

Global  str.s{128}   
Global *pointer=@str

swprintf(@str,"<h2>This is the address of the output string %p!!!</h2><p>This is a string, %s</p>",*pointer,@"hello")

Debug str 
Debug Hex(@str) 
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
mk-soft
Always Here
Always Here
Posts: 5409
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Format string with some values like sprintf (C) - Update

Post by mk-soft »

I can't confirm it on Ubuntu 18.04 X64. Here is an 8 byte align to the next parameter.

Have once a beta version created with calculate the align to next parameter.
Please check the value 'param_align'.

Beta v2.09

Code: Select all

...
Removed
...
Last edited by mk-soft on Wed Jul 18, 2018 11:23 pm, edited 1 time in total.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
luis
Addict
Addict
Posts: 3876
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: Format string with some values like sprintf (C) - Update

Post by luis »

@mk-soft

Can you confirm my findings enabling the Purifier ? See my edited post.

The version you just posted where the offset is calculated works with the Purifier on or off, thanks. :)
I hope this is reliable enough and the size of the "cookies" used by the Purifier is not going to change in some strange way where this calculation is not going to work anymore but I doubt it.
Last edited by luis on Wed Jul 18, 2018 10:58 pm, edited 1 time in total.
"Have you tried turning it off and on again ?"
A little PureBasic review
User avatar
luis
Addict
Addict
Posts: 3876
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: Format string with some values like sprintf (C) - Update

Post by luis »

@idle

Thanks, I tried to import sprintf from the C lib but afaik it doesn't work with floats and doubles, just integers and strings.
If you got it working I would like to see how, because it has the advantage you can pass literal values and values returned from functions instead of just addresses of variables :)

This one in PB it's very nice, but you have to store values in temporary variables sometimes, even when it shouldn't be necessary.
"Have you tried turning it off and on again ?"
A little PureBasic review
User avatar
mk-soft
Always Here
Always Here
Posts: 5409
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Format string with some values like sprintf (C) - Update

Post by mk-soft »

luis wrote:@mk-soft

Can you confirm my findings enabling the Purifier ? See my edited post.

The version you just posted where the offset is calculated works with the Purifier on or off, thanks. :)
I hope this is reliable enough and the size of the "cookies" used by the Purifier is not going to change in some strange way where this calculation is not going to work anymore but I doubt it.
I can confirm with compiler option Purifier.

Update v2.09
- Fixed compiler option Purifier
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
luis
Addict
Addict
Posts: 3876
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: Format string with some values like sprintf (C) - Update

Post by luis »

Thanks.
And thanks for the code :wink:
"Have you tried turning it off and on again ?"
A little PureBasic review
User avatar
idle
Always Here
Always Here
Posts: 5097
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Format string with some values like sprintf (C) - Update

Post by idle »

luis wrote:@idle

Thanks, I tried to import sprintf from the C lib but afaik it doesn't work with floats and doubles, just integers and strings.
If you got it working I would like to see how, because it has the advantage you can pass literal values and values returned from functions instead of just addresses of variables :)

This one in PB it's very nice, but you have to store values in temporary variables sometimes, even when it shouldn't be necessary.
I've got no idea why it doesn't work with floats or doubles really weird.
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
skywalk
Addict
Addict
Posts: 4003
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: Format string with some values like sprintf (C) - Update

Post by skywalk »

The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Format string with some values like sprintf (C) - Update

Post by wilbert »

idle wrote:
luis wrote:@idle

Thanks, I tried to import sprintf from the C lib but afaik it doesn't work with floats and doubles, just integers and strings.
If you got it working I would like to see how, because it has the advantage you can pass literal values and values returned from functions instead of just addresses of variables :)

This one in PB it's very nice, but you have to store values in temporary variables sometimes, even when it shouldn't be necessary.
I've got no idea why it doesn't work with floats or doubles really weird.
Probably the x64 calling convention.
On Windows, the first four floating point arguments are passed through XMM0 - XMM3.
On Linux and MacOS it's the first eight floating point arguments (XMM0 - XMM7).
Therefore you need to specify already in the import statement the correct type for the arguments.
Windows (x64)
Raspberry Pi OS (Arm64)
Post Reply