- Community Home
- >
- Servers and Operating Systems
- >
- Operating Systems
- >
- Operating System - OpenVMS
- >
- Using small helper function
Categories
Company
Local Language
Forums
Discussions
Forums
- Data Protection and Retention
- Entry Storage Systems
- Legacy
- Midrange and Enterprise Storage
- Storage Networking
- HPE Nimble Storage
Discussions
Forums
Discussions
Discussions
Discussions
Forums
Discussions
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
- BladeSystem Infrastructure and Application Solutions
- Appliance Servers
- Alpha Servers
- BackOffice Products
- Internet Products
- HPE 9000 and HPE e3000 Servers
- Networking
- Netservers
- Secure OS Software for Linux
- Server Management (Insight Manager 7)
- Windows Server 2003
- Operating System - Tru64 Unix
- ProLiant Deployment and Provisioning
- Linux-Based Community / Regional
- Microsoft System Center Integration
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Community
Resources
Forums
Blogs
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-13-2011 09:09 PM
09-13-2011 09:09 PM
Get function address in BASIC
I am fixing bugs in a 17 year old application written in VAX Basic (oh how deep did I sink). The program passes the address of an external function as:
EXTERNAL INTEGER FUNCTION ast
CALL sub(..., LOC(astfunc),...)
...which procedure sub stores in a data structure.
In another function it tries to compare the function address - retrieved from the structure - with the address of the function ast:
SELECT astadr
CASE LOC(ast)
I stepped through the machine code (Itanium/V8.4) and found that astadr had the right address for function ast but the LOC(ast) gives the address of where ast's address is stored. So it never takes this case statement. A comment in the code gave a - desperate - hint that 'something with that ast doesn't work right'. Sure, with this problem it never canceled an outstanding timer AST.
I couldn't find a BASIC construct that would return the function address in the CASE statement. Like a dereference something.
I have an idea how to modify the code taking a different approach but out of curiosity...anyone with an idea?
Thanks,
Guenther
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-14-2011 01:38 AM
09-14-2011 01:38 AM
Re: Get function address in BASIC
I can't really help with Basic, but ...
>>> address of an external function
On Integrity, the address of a function is the address of a function descriptor, FD, which (ignore the /nonative stuff) consists of two quadwords: the code address and the GP value. There can be official FDs, definitions of functions in an image, and local FDs, references to functions external to an image. Whenever the address of a function is used, the address of the official FD is taken, no matter whether it is within the same image or in another (shareable) image. For compiled and linked code, relocations produced by the compilers and the processing of them by the linker make sure that this is the case.
When debugging the code, you can identify what's stored in the data structure: it should be the address of the official FD, not a code address. The linker creates all the FDs in the short data segment, that is separate from all your (compiler generated) PSECTs.
>>> LOC(ast) gives the address of where ast's address is stored
LOC should return the address of the official FD, which may be the case, if I interpret the "ast's address" as code address.
On Integrity it is important to have all externals correctly declared, as function/procedure or data. I don't know how you do this in Basic, but the linker should complain if you don't.
In the shown code, ast is declared but astfunc is passed to sub. It's not obvious whether this is a cut&paste problem, or part of the error.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-14-2011 08:04 AM
09-14-2011 08:04 AM
Re: Get function address in BASIC
Hi Hartmut!
Correction to my code sample:
EXTERNAL INTEGER FUNCTION ast
CALL sub(..., LOC(ast) BY VALUE,...)
What puzzles me is that the value received by the called function 'sub' differs from the value returned by LOC(ast) in an assignment. Looks to me like BASIC stored the address of function 'sub' somewhere and returns the pointer to this location. I am not sure if this is a FD where it points to. If I use plain 'ast' w/o LOC() in the assignment it calls that function right away - BUMMER!
I think this is a bug in the way LOC() is used by the BASIC compiler. But then maybe not:
DBG> exam SC_DO_TIMAST
%DEBUG-I-NOUNIQ, symbol 'SC_DO_TIMAST' is not unique
data SC_DO_TIMAST\SC_DO_TIMAST\SC_DO_TIMAST
routine SC_DO_TIMAST\SC_DO_TIMAST
It seems there are two entities in use: a data and a function definition for the ast function. Why would that be?
Thanks,
Guenther
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-14-2011 11:25 AM
09-14-2011 11:25 AM
Re: Get function address in BASIC
Do a:
$ lib/extract=$pdscdef/output=pdscdef.bas sys$library:basic$starlet.tlb
and see if it has the clues you need to sort out the procedure descriptors. There is some discussion in the calling standard:
http://h71000.www7.hp.com/doc/82final/5973/5973pro_012.html#index_x_373
and elsewhere.
I had a simpler version of this problem when we moved to Itanium because we had an AST routine we used for SMG broadcast trapping and were sloppy about whether we considered it to be a subroutine or a function. As Hartmut said, a function is a different animal on IA64 and you have to declare it as such. We came by our sloppiness honestly as we were doing exactly what was in the example in the SMG manual at:
http://h71000.www7.hp.com/doc/73final/5935/5935pro_015.html#5935disable_broadcast_trapping
That example does not work on Itanium without the following changes:
$ gdiff -pu trapping.bas;-0 trapping.bas --- trapping.bas;-0 2009-09-30 10:07:25 -0500 +++ trapping.bas 2009-10-03 18:45:00 -0500 @@ -32,8 +32,8 @@ !GET_INPUT is the routine which spawns the subprocess !- - EXTERNAL INTEGER GET_MSG - EXTERNAL INTEGER GET_INPUT + EXTERNAL INTEGER FUNCTION GET_MSG + EXTERNAL INTEGER FUNCTION GET_INPUT DECLARE LONG pb_id, ret_status, display_id, display2_id, display3_id, & key_id, key_tab_id, counter @@ -238,7 +238,7 @@ !are disabled. !- - SUB GET_INPUT (paste_id, param, nl_1, nl_2, nl_3, nl_4) + FUNCTION INTEGER GET_INPUT (paste_id, param, nl_1, nl_2, nl_3, nl_4) MAP (params) LONG disp_info(2), LONG keyboard_info(4), LONG done_flag @@ -252,8 +252,8 @@ %INCLUDE "LIB$ROUTINES" %FROM %LIBRARY "SYS$LIBRARY:BASIC$STARLET" %INCLUDE "$SMGMSG" %FROM %LIBRARY "SYS$LIBRARY:BASIC$STARLET" - EXTERNAL INTEGER GET_MSG - EXTERNAL INTEGER GET_INPUT + EXTERNAL INTEGER FUNCTION GET_MSG + EXTERNAL INTEGER FUNCTION GET_INPUT !+ !Assign to the local variables the values that were stored from @@ -371,7 +371,7 @@ done_flag = 1 Out_of_sub: - END SUB + END FUNCTION 30 !+ !Start of AST routine GET_MSG. This AST is called whenever there @@ -379,7 +379,7 @@ !MESSAGES virtual display. !- - SUB GET_MSG (paste_id, nl_1, nl_2, nl_3, nl_4) + FUNCTION INTEGER GET_MSG (paste_id, nl_1, nl_2, nl_3, nl_4) DECLARE LONG status1, pasteboard, second_disp DECLARE WORD msg_len DECLARE STRING msg @@ -421,6 +421,5 @@ END IF NEXT Exitloop: - END SUB - + END FUNCTION
Guenther seems to be declaring things right, so it's not exactly the same problem we had. We never had to worry about how to invoke the call-back function since SMG does that. Hopefully $PDSCDEF will offer something to go on for how to unpack the descriptor.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-14-2011 02:52 PM
09-14-2011 02:52 PM
Re: Get function address in BASIC
Guenther,
From what you've posted, you don't really care about the address, what you're really trying to do is compare objects to see if they're the same. For that you just need some kind of "fingerprint" which can be reliably and consistently derived. I'd hide the details. Something like this (note - I've probably got the Basic syntax wrong!):
function FingerPrint(rtn) perform whatever seems necessary here FingerPrint=some manipulation of rtn end ... EXTERNAL INTEGER FUNCTION ast somestrucure.IDField=FingerPrint(LOC(ast) BY VALUE) ... SELECT somestructure.IDField CASE FingerPrint(LOC(ast) BY VALUE)
Depending on what you do in FingerPrint, you may find you can call it as FingerPrint(ast). If necessary, implement the fingerprint function in MACRO so you have full control over how the argument is treated.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-14-2011 02:57 PM
09-14-2011 02:57 PM
Using small helper function
Doesn't look like a FD where the LOC() is pointing to. Just a plain LONG.
I made a small helper function:
FUNCTION INTEGER SC_RET_FUNC_ADDR( INTEGER ADDR )
SC_RET_FUNC_ADDR = ADDR
FUNCTIONEND
And use it like this:
case sc_ret_func_addr(loc(sc_do_timast) by value)
/Guenther