Getting address of string constants with @ or ?

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
technicorn
Enthusiast
Enthusiast
Posts: 105
Joined: Wed Jan 18, 2006 7:40 pm
Location: Hamburg

Getting address of string constants with @ or ?

Post by technicorn »

Hi,

it would be a nice feature to be able to get the address
of a string constant with the @ or ? operator,
so you could pass them to procedures by pointer for example.

Greatings
technicorn

edit:
Just found that you can take the address of a string constant,
but only for the string itself:

a=@"Hello" ; works
#const = "Hello"
a=@#const ; gives a syntax error
Bonne_den_kule
Addict
Addict
Posts: 841
Joined: Mon Jun 07, 2004 7:10 pm

Post by Bonne_den_kule »

The only intension with constants is to make the code easier to read/understand. The compiler replaces the constants in code with it's value before compiling.
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

the adress of a constant? :shock:
oh... and have a nice day.
User avatar
tinman
PureBasic Expert
PureBasic Expert
Posts: 1102
Joined: Sat Apr 26, 2003 4:56 pm
Location: Level 5 of Robot Hell
Contact:

Re: Getting address of string constants with @ or ?

Post by tinman »

technicorn wrote:it would be a nice feature to be able to get the address
of a string constant with the @ or ? operator,
so you could pass them to procedures by pointer for example.
Until it does you could always use a macro instead of constants for strings:

Code: Select all

Macro const
"Hello"
EndMacro

Procedure.l StrAdr(addr.l)
    ProcedureReturn addr
EndProcedure

Debug StrAdr(@"Hello")
Debug StrAdr(@const)

End
If you paint your butt blue and glue the hole shut you just themed your ass but lost the functionality.
(WinXPhSP3 PB5.20b14)
technicorn
Enthusiast
Enthusiast
Posts: 105
Joined: Wed Jan 18, 2006 7:40 pm
Location: Hamburg

Post by technicorn »

Thanks tinmann,
but that doesn't help me with my problem.

To make clear what my intention was for this request,
I want to write a program that keeps track of which file and line a procedure is called from.

For lines that is simple, because #PB_Compiler_Line is a numeric constant,
And for the filename you can use #PB_Compiler_File , but it will give you a string,
which isn't very usefull, because stringhandling is to slow,
just having the address of that constant is much easier to handle and
is as unique as the string itself.

But you can't use @ or ? with #PB_Compiler_File, it will give syntax error.

Hope that makes it clearer.
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Post by ts-soft »

There is no adress to a stringconstant, the compiler sets the string direct. For this are Constants.
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
User avatar
helpy
Enthusiast
Enthusiast
Posts: 552
Joined: Sat Jun 28, 2003 12:01 am

Re: Getting address of string constants with @ or ?

Post by helpy »

Hi technicorn,
technicorn wrote:it would be a nice feature to be able to get the address
of a string constant with the @ or ? operator,
so you could pass them to procedures by pointer for example.
If you want to use string constants, than use DataSection!

cu, helpy
Windows 10 / Windows 7
PB Last Final / Last Beta Testing
technicorn
Enthusiast
Enthusiast
Posts: 105
Joined: Wed Jan 18, 2006 7:40 pm
Location: Hamburg

Post by technicorn »

@ts-soft

There is an address, see this:

Main file "StringConstants_test.pb"

Code: Select all

Define file1.s, file2.s

file1 = #PB_Compiler_File
XIncludeFile "StringConstants.pbi"
MessageRequester("Test", file1+#LF$+file2)
Include file "StringConstants.pbi"

Code: Select all

file2 = #PB_Compiler_File
Excerpt of the resulting asm file compiled with /COMMENTED:

Program part:
; Define file1.s, file2.s
;
; file1 = #PB_Compiler_File
MOV edx,_S1
LEA ecx,[v_file1]
CALL SYS_FastAllocateStringFree
; XIncludeFile "StringConstants.pbi"
; file2 = #PB_Compiler_File
MOV edx,_S2
LEA ecx,[v_file2]
CALL SYS_FastAllocateStringFree
;
; MessageRequester("Test", file1+#LF$+file2)
PUSH dword [_PB_StringBasePosition]
MOV edx,dword [v_file1]
PUSH dword [_PB_StringBasePosition]
CALL _SYS_CopyString@0
MOV edx,_S3
CALL _SYS_CopyString@0
MOV edx,dword [v_file2]
CALL _SYS_CopyString@0
INC dword [_PB_StringBasePosition]
PUSH dword _S4
MOV edx,[PB_StringBase]
ADD [esp+4],edx
CALL _PB_MessageRequester@8
POP dword [_PB_StringBasePosition]

Data part:
public _SYS_StaticStringStart
_SYS_StaticStringStart:
_S1: db "StringConstants_Test.pb",0
_S2: db "G:\Projects\PureBasic4\Tests\StringConstants.pbi",0
_S3: db 10,0
_S4: db "Test",0
pb_public PB_NullString
db 0
public _SYS_StaticStringEnd

As you can see, _S1, _S2 are the addresses for the different replacements of #PB_Compiler_File,
_S3 is the #LF$
and _S4 is for the "Test" string used by the MessageRequester

@helpy
Sorry, but that will not solve my problem,
even using a seperate DataSection for the main and every included source
would mean, you have to give different names to labels in the DataSection,
so you can not use a simple construct like this:

TestProc(param1, param2, ..., @#PB_Compiler_File, #PB_Compiler_Line)

so that TestProc() would get it's normal parameter and the pointer to
the filename string that it was called from.
Of course I would use a Macro to call TestProc() which will be replaced
by just the normal call of TestProc() and parameters, without the filename and linenumber in the final application compilation.

I'm asking for this feature, because I want to write a library written in
pure PB (no asm) to keep track of pointer allocation/reallocation/freeing
with the PB functions AllocateMemory() and the like,
because I often use pointers in my programs and I want to make life easier by knowing where the pointer was used last time.

I already have a set of functions that keep track of that, but I want to store the filenames and linenumers with it,
to make it easier to track errors down to the root.

Sorry if that all sounds like rambling to someone else,
maybe it's just importend to me, and I have to find my
one way to solve that problem.

CU
technicorn
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Post by ts-soft »

Can't see any stringconstant, file1 and file2 are variables stored in datasection
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
User avatar
tinman
PureBasic Expert
PureBasic Expert
Posts: 1102
Joined: Sat Apr 26, 2003 4:56 pm
Location: Level 5 of Robot Hell
Contact:

Post by tinman »

How about this then? It seems to work for me, at least the value I get from the two debug statements are the same. You need to watch that you use the correct pseudotype for the string parameter otherwise PB will convert it and cause the address to be different.

I guess if this is going to be part of your own debug logging library you should be able to hide most of this hackery behind a macro in another file or something.

Code: Select all

Prototype.l StrCheat(sring.p-unicode)

Procedure.l StrAddr(str_addr.l)
    ProcedureReturn str_addr
EndProcedure

*foo.StrCheat = @StrAddr()
#const = "Foo"
Debug *foo(#const)
Debug @"Foo"
End
Obviously the best solution would be for the compiler to accept @#const, which seems reasonable if #const is supposed to be replaced with "string" during compilation.
If you paint your butt blue and glue the hole shut you just themed your ass but lost the functionality.
(WinXPhSP3 PB5.20b14)
technicorn
Enthusiast
Enthusiast
Posts: 105
Joined: Wed Jan 18, 2006 7:40 pm
Location: Hamburg

Post by technicorn »

Thanks a lot tinman!! :D
I would have never thought of "miss"-using pseudotypes that way.

Some little enhancement to show it really works:

Code: Select all

CompilerIf #PB_Compiler_Unicode
  Prototype.l StrCheat(sring.p-unicode)
CompilerElse
  Prototype.l StrCheat(sring.p-ascii)
CompilerEndIf

Procedure.l StrAddr(str_addr.l)
    ProcedureReturn str_addr
EndProcedure

*foo.StrCheat = @StrAddr()
#const = "Foo"
*p1= *foo(#PB_Compiler_File)
*p2= *foo(#PB_Compiler_File)
Debug *p1
Debug *p2
Debug PeekS(*p1)
Debug PeekS(*p2)
Debug #PB_Compiler_File
End
I can life with the small overhead of the procedure call for now,
as it is only used in testing mode of the program.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

Code: Select all

Get the address of the file name string:
Debug ?PB_Compiler_File

; Put at the end of every file:
DataSection
  PB_Compiler_File:
  Data.s #PB_Compiler_File
EndDataSection
Disadvantage: The string for the filename will be included in the final executable. This should be obvious, though (if it wasn't included you wouldn't be able to get its address, right).
technicorn
Enthusiast
Enthusiast
Posts: 105
Joined: Wed Jan 18, 2006 7:40 pm
Location: Hamburg

Post by technicorn »

Hi Trond,

and what about duplicate labels? :twisted:

And no, I can't use different labels for each file,
because that would break the automatic insertion of the right name/label!

But thanks for trying to help.

technicorn
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

Sorry. This ought to do the trick:

Code: Select all

Procedure Callback(FileAddress.l)
  Debug PeekL(FileAddress) ; Guaranteed to be different for each file
  Debug PeekS(PeekL(@FileAddress))
EndProcedure

Prototype ProtoCallbackInterface(FileAddress.s)

Function.ProtoCallbackInterface = @Callback()

Function(#PB_Compiler_File)
User avatar
tinman
PureBasic Expert
PureBasic Expert
Posts: 1102
Joined: Sat Apr 26, 2003 4:56 pm
Location: Level 5 of Robot Hell
Contact:

Post by tinman »

Trond wrote:Sorry. This ought to do the trick:
Except that it doesn't because PB is still copying your string to a local variable before you get the address. Check out your code using this:

Code: Select all

string.s = "bar"
Debug @string
Function(string)
Using the pseudotypes works because PB doesn't perform any copying - the pseudotype is for external functions that take a string pointer.
If you paint your butt blue and glue the hole shut you just themed your ass but lost the functionality.
(WinXPhSP3 PB5.20b14)
Post Reply