OpenVMS Source Code Demos
BASIC_PEEK_DEMO
1024 %title "BASIC-PEEK-DEMO" ! never change this line number :-)
%ident "105.3" !
declare string constant k_version = "105.3" , ! &
k_program = "BASIC-PEEK-DEMO" !
!========================================================================================================================
! Title : DEC-BASIC-Peek_Demo_xxx.bas
! Author : Neil Rieck (Waterloo, Ontario, Canada)
! : (https://neilrieck.net) (mailto:[email protected])
! Notes : 1) This program allows DEC-BASIC to peek at a memory location in a way similar to DEC-C
! (the difference being that DEC-C can do it without the creation of an external function)
! 2) Compile this program with cli switches "/list/machine" then look for the BASIC line numbers
! converted to hex
! History:
! ver who when what
! --- --- ------ --------------------------------------------------------------------------------------------------------
! 100 NSR 001022 1. original program
! 101 NSR 070629 1. cleanup for publishing to public domain
! 102 NSR 110409 1. added three dump routines
! 2. added a demo for a fixed string array
! NSR 110410 3. added a demo for variable string arrays
! 103 NSR 130105 1. another cleanup
! 104 NSR 141001 1. added a few lines of code to foil compiler optimization
! 105 NSR 170520 1. added code to peek at a 2-dimension array (created at run-time)
! NSR 170521 2. added code to peek at 1 and 3 dimension arrays (created at run-time)
! 3. wrote a function to peek at an array descriptor (DSC$K_CLASS_NCA)
!========================================================================================================================
! 32-bit Descriptor Prototype (from dump of sys$library:BASIC$STARLET.TLB)
!
! Each class of 32-bit descriptor consists of at least 2 longwords in the following format:
!
! +-------+-------+---------------+
! | CLASS | DTYPE | LENGTH | :Descriptor
! +-------+-------+---------------+
! | POINTER |
! +-------------------------------+
!
! DSC$W_LENGTH A one-word field specific to the descriptor
! <0,15:0> class/* typically a 16-bit (unsigned) length.
!
! DSC$B_DTYPE A one-byte atomic data type code
! <0,23:16>
!
! DSC$B_CLASS A one-byte descriptor class code (see below)
! <0,31:24>
!
! DSC$A_POINTER A longword pointing to the first byte of the
! <1,31:0> data element described.
!========================================================================================================================
! Enabling either "when error use" or "on error" trapping (and including any BASIC code which references ERL)
! has been known to add more code, and therefore, more human-readable references to the machine code listings.
! Disabling compiler optimization will stop the compiler from unrolling loops (and other stuff) as well as
! leaving target labels in the machine code listings.
! Try any one of these commands just for fun:
! bas/list/machine/nooptim BASIC-PEEK-DEMO_105
! bas/list/machine/optim=level=0 BASIC-PEEK-DEMO_105
! bas/list/machine/optim=level=0/cross/show=all BASIC-PEEK-DEMO_105
! then inspect file BASIC-PEEK-DEMO_105.lis
!========================================================================================================================
option type=explicit ! no kid stuff
set no prompt ! no '?' after input prompt
%include "starlet" %from %library "sys$library:basic$starlet" ! system services (and basic$quadword)
%include "$dscdef" %from %library "sys$library:basic$starlet" ! mostly descriptor constants
%include "$iledef" %from %library "sys$library:basic$starlet" ! Item List Entry structures
!
on error goto my_error_trap !
!
! note: for this little trick to work, we must...
!
! 1. declare LONG BY VALUE passing mechanisms here (we are passing 32-bit addresses)
! 2. declare BY REF passing mechanisms in the receiving functions
!
external long function my_peek_L( long by value ) !
external word function my_peek_W( long by value ) !
external byte function my_peek_B( long by value ) !
external basic$quadword function my_peek_Q( long by value ) !
external long function my_loc( any by ref ) !
external DSCDEF6 function my_array_details (any by desc ) !
!
external sub dump_long(long , long ) !
external sub dump_word(long , long ) !
external sub dump_byte(long , long , long) !
!
declare long i% , &
ptr1 , &
ptr2 , &
length , &
temp , &
test123 , &
last_subscr , &
x ,y ,z , &
x2,y2,z2 , &
subtest , &
junk , &
string dynamic_str$ , &
junk$ , &
default$ !
map(m1)string mapped_str$ = 10 ! a little larger than required
map(m2)long mapped_long% !
!
! support for: fixed-string array
! variable string array
!
! note: 1) the BASIC view of how these arrays are data-filled, then referenced, appears identical
! but the binary code behind it is totally different. For example, a mapped string produces
! a descriptor. Some people assume (falsely) that a mapped long will produce a long
! descriptor.
! 2) you may wish to compile with switches "/list/machine" for more information
!
declare long constant k_max_subscr = 2 !
declare long constant k_max_size = 5 !
!
map(m3)string fs_array$(k_max_subscr) = k_max_size ! fixed string array; subscripts 0->k_max_subscr
!
! This array is built at compile-time. The Alpha-BASIC compiler "knows" boundary limits (because
! I used a constant) and will simulate appropriate conditions when an array boundary is exceeded.
!
dim string vs_array_ct$(k_max_subscr) ! variable string array; subscripts 0->k_max_subscr
!
!=======================================================================
! main
!=======================================================================
2048 main:
print k_program +"_"+ k_version !
print string$(len(k_program +"_"+ k_version), asc("=")) ! what will the optimizer do with this?
!
!-----------------------------------------------------------------------
! initialize test data (for most tests)
!-----------------------------------------------------------------------
print "-i-initializing test data" !
test123 = 123% ! stand-alone long
mapped_long% = 124% ! mapped long
dynamic_str$ = "HELLO" !
!
for i% = 0 to k_max_subscr !
fs_array$(i%) = "FS"+str$(i%) ! fixed string array
vs_array_ct$(i%) = "VSC"+str$(i%) ! variable string compile-time
next i% !
!
! This array is built at run-time and behaves the way you would expect
! The whole purpose of this code is to do something the compiler can't ever optimize
!
yada0: ! find this label in machine code listing
when error in !
Print "-i-run-time array init" !
print "last subscript? (enter any number between 2 and 5) ";!
input last_subscr !
use !
last_subscr = 0 !
end when !
select last_subscr !
case 2 to 99 !
case else !
last_subscr = 2 !
end select !
print "-i-last subscript will be: "+ str$(last_subscr) !
yada1: ! find this label in machine code listing
dim string vs_array_rt$(last_subscr) ! create array at run time
yada2: ! find this label in machine code listing
!
! now load the array with data
!
print "initializing test data (continue)" !
for i% = 0 to last_subscr !
vs_array_rt$(i%) = "VSR"+str$(i%) ! variable string run-time
next i% !
!-----------------------------------------------------------------------
! example #1 (LONG INTEGER)
!-----------------------------------------------------------------------
4096 test1:
print
print "-i-Test-1 "+ string$(65,asc("#")) !
print "Long Integer=";test123 !
ptr1 = loc( test123 ) ! ptr1 is a pointer to a long integer
print "addr ="; ptr1 ! display the address
call dump_byte(ptr1, 4, 0) ! 4-bytes (32-bit long)
print "hack="; my_peek_L( loc(test123) ) !
print "-i-end of hack 1. Hit <enter>"; !
input junk$ !
!-----------------------------------------------------------------------
! example #1b (MAPPED INTEGER)
!-----------------------------------------------------------------------
test1b:
print
print "-i-Test-1b" !
print "Mapped Integer=";mapped_long% !
ptr1 = loc( mapped_long% ) ! ptr1
print "addr ="; ptr1 ! display the address
call dump_byte(ptr1, 4, 0) ! 4-bytes (32-bit long)
print "hack="; my_peek_L( loc(mapped_long%) ) !
print "-i-end of hack 1b. Hit <enter>"; !
input junk$ !
!-----------------------------------------------------------------------
! example #2 (DYNAMIC STRING)
!-----------------------------------------------------------------------
8192 test2:
print !
print "-i-Test-2 "+ string$(65,asc("#")) !
print "Dynamic String=";dynamic_str$ !
ptr1 = loc( dynamic_str$ ) ! ptr1 is a pointer to string descriptor
print "addr "; ptr1 ! display the descriptor address
call dump_word(ptr1 , 1) !
call dump_byte(ptr1+2, 2, 0) !
call dump_long(ptr1+4, 1) !
print "a=(length ) "; my_peek_W( ptr1 ) ! DATA LENGTH
print "b=(type ) "; my_peek_B( ptr1+2 ) ! DESCRIPTOR TYPE
print "c=(class ) "; my_peek_B( ptr1+3 ) ! DESCRIPTOR CLASS
print "d=(address) "; my_peek_L( ptr1+4 ) ! DATA ADDRESS
!
ptr2 = my_peek_L( ptr1+4 ) ! get the address (again)
length = my_peek_W( ptr1 ) ! get the LENGTH (again)
call dump_byte(ptr2, length, 1) !
print "-i-end of hack 2. Hit <enter>"; !
input junk$ !
!-----------------------------------------------------------------------
! example #3 (MAPPED STRING)
!-----------------------------------------------------------------------
16384 test3:
print
print "-i-Test-3 "+ string$(65,asc("#")) !
mapped_str$ = "GOOD BYE" !
print "Mapped String=";mapped_str$ !
print "-?-enter some text or just hit <enter> for the default"; ! -+- foil compiler optimization
input junk$ ! -+
mapped_str$ = junk$ if edit$(junk$ ,2) <> "" ! -+
ptr1 = loc( mapped_str$ ) ! ptr1 is a pointer to data
length = len( mapped_str$ ) ! be sure to check equiv machine code
print "addr "; ptr1 ! display the string address
print "length "; length ! display the string length
call dump_byte(ptr1, length, 1) !
print "-i-end of hack 3. Hit <enter>"; !
input junk$ !
!-----------------------------------------------------------------------
! example #4 (fs array)
!-----------------------------------------------------------------------
16385 test4:
print !
print "-i-Test-4 "+ string$(65,asc("#")) !
print "fs array (fixed length strings - no descriptors)"
print "array data"
for i% = 0 to k_max_subscr !
print " ";i%;" ";fs_array$(i%) !
next i% !
print "declared max size: "+ str$(k_max_size) ! be sure to check equiv machine code
print "declared max subs: "+ str$(k_max_subscr) ! be sure to check equiv machine code
ptr1 = loc( fs_array$(0) ) ! ptr1 is a pointer to string data
length = len( fs_array$(0) ) ! the compiler knew this value
print "addr-0 "; ptr1 ! display the string address
print "length "; length ! display the max string length
call dump_byte(ptr1, length, 1) !
print "-i-end of hack 4. Hit <enter>"; !
input junk$ !
!-----------------------------------------------------------------------
! example #5 (vs array)
!-----------------------------------------------------------------------
16386 test5:
print
print "-i-Test-5 "+ string$(65,asc("#")) !
print "vs array (compile-time - variable length strings - descriptors)"
print "array data" !
for i% = 0 to k_max_subscr !
print " ";i%;" ";vs_array_ct$(i%) !
next i% !
ptr1 = loc( vs_array_ct$(0) ) ! ptr1 is a pointer to string descriptor
print "addr-0 "; ptr1 ! display the descriptor address
call dump_word(ptr1 , 1 ) !
call dump_byte(ptr1+2, 2, 0) !
call dump_long(ptr1+4, 1 ) !
print "a=(length ) "; my_peek_W( ptr1 ) ! DATA LENGTH
print "b=(type ) "; my_peek_B( ptr1+2 ) ! DESCRIPTOR TYPE
print "c=(class ) "; my_peek_B( ptr1+3 ) ! DESCRIPTOR CLASS
print "d=(address) "; my_peek_L( ptr1+4 ) ! DATA ADDRESS
!
ptr2 = my_peek_L( ptr1+4 ) ! get the address (again)
length = my_peek_W( ptr1 ) ! get the LENGTH (again)
call dump_byte(ptr2, length, 1) !
print "hit <enter> to continue "; !
input junk$ !
!
ptr1 = loc( vs_array_ct$(1) ) ! ptr1 is a pointer to string descriptor
print "addr-1 "; ptr1 ! display the descriptor address
call dump_word(ptr1 , 1 ) !
call dump_byte(ptr1+2, 2, 0) !
call dump_long(ptr1+4, 1 ) !
print "a=(length ) "; my_peek_W( ptr1 ) ! DATA LENGTH
print "b=(type ) "; my_peek_B( ptr1+2 ) ! DESCRIPTOR TYPE
print "c=(class ) "; my_peek_B( ptr1+3 ) ! DESCRIPTOR CLASS
print "d=(address) "; my_peek_L( ptr1+4 ) ! DATA ADDRESS
!
ptr2 = my_peek_L( ptr1+4 ) ! get the address (again)
length = my_peek_W( ptr1 ) ! get the LENGTH (again)
call dump_byte(ptr2, length, 1) !
!
print "-i-end of hack 5. Hit <enter>"; !
input junk$ !
!-----------------------------------------------------------------------
! example #6 (vs array)
!-----------------------------------------------------------------------
record switcheroo
variant
case
group one !
basic$quadword my_quad ! unsigned quad word (system calls)
end group !
case !
group two !
word my_len !
byte my_typ !
byte my_class !
long my_addr !
end group
case
group three !
DSCDEF1 my_descriptor ! defined in $dscdef in sys$library:basic$starlet
end group !
end variant !
end record !
!
declare switcheroo my_dsc ! declare a variable to match the new record
!
16387 test6:
print
print "-i-Test-6 "+ string$(65,asc("#")) !
print "vs array (run-time - variable length strings - descriptors)"
print "array data" !
for i% = 0 to last_subscr !
print " ";i%;" ";vs_array_rt$(i%) !
next i% !
ptr1 = my_loc( vs_array_rt$() ) ! here, ptr1 is a pointer to array descriptor (maybe not)
print "addr "; ptr1 ! display the descriptor address
ptr1 = loc( vs_array_rt$(0) ) ! ptr1 is a pointer to string descriptor
print "addr-0 "; ptr1 ! display the descriptor address
call dump_word(ptr1 , 1 ) !
call dump_byte(ptr1+2, 2, 0) !
call dump_long(ptr1+4, 1 ) !
print "a=(length ) "; my_peek_W( ptr1 ) ! DATA LENGTH
print "b=(type ) "; my_peek_B( ptr1+2 ) ! DESCRIPTOR TYPE
print "c=(class ) "; my_peek_B( ptr1+3 ) ! DESCRIPTOR CLASS
print "d=(address) "; my_peek_L( ptr1+4 ) ! DATA ADDRESS
!
print
print "-i-Test-6a "+ string$(65,asc("#")) !
ptr2 = my_peek_L( ptr1+4 ) ! get the address (again)
length = my_peek_W( ptr1 ) ! get the LENGTH (again)
call dump_byte(ptr2, length, 1) !
print "hit <enter> to continue "; !
input junk$ !
!
! use a different technique to pull the next string
!
print
print "-i-Test-6b "+ string$(65,asc("#")) !
ptr1 = loc( vs_array_rt$(1) ) ! ptr1 is a pointer to string descriptor
my_dsc::my_quad = my_peek_Q( ptr1 ) ! stuff our switcheroo
ptr2 = my_dsc::my_addr !
length = my_dsc::my_len !
call dump_byte(ptr2, length, 1) !
!
! use a different technique to pull the next string
!
! note: I did this to show it is possible to write code by reverse-engineering (hacking) the STARLET library.
! But since there appears to be a tiny bug in module $dscdef in sys$library:basic$starlet the
! technique shown above in Test-6b is preferable to this one.
!
print
print "-i-Test-6c "+ string$(65,asc("#")) !
ptr1 = loc( vs_array_rt$(2) ) ! ptr1 is a pointer to string descriptor
my_dsc::my_quad = my_peek_Q( ptr1 ) ! stuff our switcheroo
ptr2 = my_dsc::DSC$A_POINTER ! using DSCDEF1
!~~~ length = my_dsc::DSC$W_LENGTH x using DSCDEF1; this should work but will not compile
length = my_dsc::DSC$W_MAXSTRLEN ! using DSCDEF1; this should not work but does
call dump_byte(ptr2, length, 1) !
!
print "-i-end of hack 6. Hit <enter>"; !
input junk$ !
!=======================================================================
! OpenVMS String Array Notes:
!
! 1) It appears that when BASIC declares a run-time array of strings with dimensions of 2x3, then OpenVMS declares a
! contiguous list of 3x4+1=13 string descriptors with the last one only containing nulls which signifies "no-more"
! 2) When you pass an array by of strings reference (I like to use "any by reference") the compiler passes the address of
! the first descriptor
! 3) Excerpt from: HP BASIC for OpenVMS Reference Manual (January 2005)
! When passing an entire array by descriptor, VAX BASIC creates a DSC$K_CLASS_A descriptor; I64 BASIC/Alpha BASIC
! creates a DSC$K_CLASS_NCA descriptor. For most BASIC applications, this is not noticeable because both the calling
! program and the called subprogram use NCA descriptors. However, a program that relies on individual descriptor
! fields may have to be modified to work with descriptors produced by I64 BASIC/Alpha BASIC. For more information
! about DSC$K_CLASS_A and DSC$K_CLASS_NCA descriptors, see the OpenVMS Calling Standard.
!
! 0 1 2 3
! +--------
! 0 | d d d d
! 1 | d d d d
! 2 | d d d d <-- demo(2,3)
! | d <-- internal end-of-list marker
!
!=======================================================================
! array of 1-dimension
!=======================================================================
test71:
print
print "-i-Test-71 "+ string$(65,asc("#")) !
subtest = 1 !
x2 = last_subscr !
sleep 1
!
test71_reentry_point: ! spaghetti zone :-)
print "-i-beginning subtest:";subtest !
select subtest !
case 1 ! only populate array on first pass
dim string array71(x2) !
for x = 0 to x2 !
array71(x) = "x:"+str$(x) !
next x !
case 2 !
array71(1) = "this is a test" ! change one location to something longer
case 3 !
x2 = 0 !
dim string array71(x2) !
case 4 !
mat array71 = nul$ !
case else !
goto test71_done
end select !
print "-i-note: declared dimensions are ";x2 !
print "-i-note: actual dimensions are ";x2+1 !
sleep 1
declare DSCDEF6 hack !
hack = my_array_details( array71() ) ! just fooling around
!~~~ ptr1 = loc( array71() ) x compiler throws: %BASIC-E-ENTARRNOT
!~~~ ptr1 = loc( array71(0)) x works on Itanium (provides addr of 1st descriptor)
ptr1 = my_loc( array71() ) ! my custom alternate (provides addr of 1st descriptor)
print "addr "; ptr1 ! display 1st descriptor address
call dump_byte(ptr1, (x2+1+1)*8, 1) ! just hacking (part 1)
print "-----------"
if subtest=1 then
junk = (x2+1+1)*8
print "----------- start of before" ! let's see about 50 bytes before
call dump_byte(ptr1-junk, junk, 1) ! just hacking (part 2)
print "----------- end of before" !
end if
!
get71_next:
print "a=(length ) "; my_peek_W( ptr1 ) ! DATA LENGTH
print "b=(type ) "; my_peek_B( ptr1+2 ) ! DESCRIPTOR TYPE
print "c=(class ) "; my_peek_B( ptr1+3 ) ! DESCRIPTOR CLASS
print "d=(address) "; my_peek_L( ptr1+4 ) ! DATA ADDRESS
my_dsc::my_quad = my_peek_Q( ptr1 ) ! stuff our switcheroo
length = my_dsc::DSC$W_MAXSTRLEN ! using DSCDEF1; this should not work but does
ptr2 = my_peek_L( ptr1+4 ) ! prep to extract
if ptr2 <> 0 then !
call dump_byte(ptr2, length, 1) !
print "-i-advancing address by 8-bytes" !
ptr1 = ptr1 + 8 ! advance 8-bytes
goto get71_next !
else
print "-i-address is null so done"
end if !
!
print string$(50,asc("-")) !
subtest = subtest + 1 !
goto test71_reentry_point !
test71_done:
!
print "-i-end of hack 71. Hit <enter>"; !
input junk$ !
!=======================================================================
! array of 2-dimensions
!=======================================================================
test72:
print
print "-i-Test-72 "+ string$(65,asc("#")) !
x2 = last_subscr !
y2 = last_subscr + 1 !
!
! BASIC traditionally declares array dimensions from zero to declared value
!
print "-i-note: declared dimensions are ";x2;"x";y2 !
print "-i-note: actual dimensions are ";x2+1;"x";y2+1 !
sleep 1
dim string array72(x2,y2) !
hack = my_array_details( array72(,) ) ! just fooling around
ptr1 = my_loc( array72(,) ) !
print "addr "; ptr1 ! display the descriptor address
for x = 0 to x2 !
for y = 0 to y2 !
array72(x, y) = "data-x:"+str$(x)+";y:"+str$(y)
next y !
next x !
!~~~ ptr1 = loc( array72(,) ) x this will not work
ptr1 = my_loc( array72(,) ) !
print "addr "; ptr1 ! display the descriptor address
call dump_byte(ptr1,(((x2+1)*(y2+1)+1)*8), 1) ! just hacking
print "------"
call dump_word(ptr1 , 1 ) !
call dump_byte(ptr1+2, 2, 0) !
call dump_long(ptr1+4, 1 ) !
print "a=(length ) "; my_peek_W( ptr1 ) ! DATA LENGTH
print "b=(type ) "; my_peek_B( ptr1+2 ) ! DESCRIPTOR TYPE
print "c=(class ) "; my_peek_B( ptr1+3 ) ! DESCRIPTOR CLASS
print "d=(address) "; my_peek_L( ptr1+4 ) ! DATA ADDRESS
print "------"
ptr2 = my_peek_L( ptr1+4 ) !
length = my_dsc::DSC$W_MAXSTRLEN ! using DSCDEF1; this should not work but does
call dump_byte(ptr2, length, 1) !
!
print "-i-end of hack 72. Hit <enter>"; !
input junk$ !
!=======================================================================
! array of 3-dimensions
!=======================================================================
test73:
print
print "-i-Test-73 "+ string$(65,asc("#")) !
x2 = last_subscr !
y2 = last_subscr + 1 !
z2 = last_subscr + 2 !
!
! BASIC traditionally declares array dimensions from zero to declared value
!
print "-i-note: declared dimensions are ";x2;"x";y2;"x";z2 !
print "-i-note: actual dimensions are ";x2+1;"x";y2+1;"x";z2+1
sleep 1
dim string array73(x2,y2,z2) !
hack = my_array_details( array73(,,) ) ! just fooling around
ptr1 = loc( array73(0,0,0) ) !
print ptr1
ptr1 = my_loc( array73(,,) ) !
print ptr1
print "addr "; ptr1 ! display the descriptor address
for x = 0 to x2 !
for y = 0 to y2 !
for z = 0 to z2 !
array73(x,y,z) = "x:"+str$(x)+";y:"+str$(y)+";z:"+str$(z)
next z
next y !
next x !
!~~~ ptr1 = loc( array73(,,) ) x this will not work
ptr1 = my_loc( array73(,,) ) !
print "addr "; ptr1 ! display the descriptor address
call dump_byte(ptr1,(((x2+1)*(y2+1)*(z2+1)+1)*8) , 1) ! just hacking
print "------"
call dump_word(ptr1 , 1 ) !
call dump_byte(ptr1+2, 2, 0) !
call dump_long(ptr1+4, 1 ) !
print "a=(length ) "; my_peek_W( ptr1 ) ! DATA LENGTH
print "b=(type ) "; my_peek_B( ptr1+2 ) ! DESCRIPTOR TYPE
print "c=(class ) "; my_peek_B( ptr1+3 ) ! DESCRIPTOR CLASS
print "d=(address) "; my_peek_L( ptr1+4 ) ! DATA ADDRESS
print "------"
ptr2 = my_peek_L( ptr1+4 ) !
length = my_dsc::DSC$W_MAXSTRLEN ! using DSCDEF1; this should not work but does
call dump_byte(ptr2, length, 1) !
!
print "-i-end of hack 73. Hit <enter>"; !
input junk$ !
!
goto fini
!-----------------------------------------------------------------------
! common error trap
!-----------------------------------------------------------------------
my_error_trap:
print
print "==============================="
print " common error trap"
print "==============================="
print "-i-error : "; err
print "-e-text : "; ert$(err)
print "-i-line : "; erl
print "-i-module: "; ern$
print "==============================="
resume fini !
!=======================================================================
! adios
!=======================================================================
31000 fini: !
print "Adios..." !
end program 1 ! VMS-s-
!#######################################################################
!
! External functions
!
!-----------------------------------------------------------------------
! peek L(ong)
!-----------------------------------------------------------------------
32000 function long my_peek_L(long incoming by ref) ! long function receives long address
option type=explicit !
my_peek_L = incoming ! exit with this value
end function !
!-----------------------------------------------------------------------
! peek W(ord)
!-----------------------------------------------------------------------
32010 function word my_peek_W(word incoming by ref) ! word function receives word address
option type=explicit !
my_peek_W = incoming ! exit with this value
end function !
!-----------------------------------------------------------------------
! peek B(yte)
!-----------------------------------------------------------------------
32020 function byte my_peek_B(byte incoming by ref) ! byte function receives byte address
option type=explicit !
my_peek_B = incoming ! exit with this value
end function !
!-----------------------------------------------------------------------
! peek Q/uadword
!-----------------------------------------------------------------------
32030 function basic$quadword my_peek_Q(basic$quadword incoming by ref) ! byte function receives quad address
option type=explicit !
%include "starlet" %from %library "sys$library:basic$starlet" ! system services (and basic$quadword)
my_peek_Q = incoming ! exit with this value
end function !
!-----------------------------------------------------------------------
! my_loc
!
! This function was needed to get around a compiler restriction with Alpha-BASIC-3.7 on OpenVMS-8.4
! I'm do not know if the restriction existed with earlier Alpha BASIC compilers
!-----------------------------------------------------------------------
32040 function long my_loc(long incoming by value) ! this function receives an address
option type=explicit !
!
my_loc = incoming ! exit with this value
end function !
!-----------------------------------------------------------------------
! my_array_details
!-----------------------------------------------------------------------
32041 function DSCDEF6 my_array_details(DSCDEF6 incoming)
option type=explicit
%include "$dscdef" %from %library "sys$library:basic$starlet" ! mostly descriptor constants
!
print "-i-DSC$L_V0 ";incoming::DSC$L_V0 ! addr
print "-i-DSC$L_S1 ";incoming::DSC$L_S1
print "-i-DSC$L_S2 ";incoming::DSC$L_S2
!
my_array_details = incoming ! pass the whole thing back
end function !
!-----------------------------------------------------------------------
! dump long data
!-----------------------------------------------------------------------
32050 sub dump_long(long ptr1, long count%) !
option type=explicit !
!
external long function my_peek_L( long by value ) !
declare long i%, temp !
print "Long Peek:" !
for i% = 0 to (count%*4 -1) step 4 !
temp = ptr1 + i% !
print using " ########## = ##########";temp;my_peek_L(temp) !
next i% !
end sub !
!-----------------------------------------------------------------------
! dump_word
!-----------------------------------------------------------------------
32060 sub dump_word(long ptr1, long count%) !
option type=explicit !
external long function my_peek_W( long by value ) !
declare long i%, temp !
print "Word Peek:" !
for i% = 0 to (count%*2 -1) step 2 !
temp = ptr1 + i% !
print using " ########## = ##########";temp;my_peek_W(temp) !
next i% !
end sub !
!-----------------------------------------------------------------------
! dump_byte (with ASCII display)
!-----------------------------------------------------------------------
32070 sub dump_byte(long ptr1, long count%, long extra%) !
option type=explicit !
external byte function my_peek_B( long by value ) !
declare long i%, temp, eightbit%, sevenbit% !
declare string a$ !
print "Byte Peek:" !
for i% = 0 to count% - 1 !
temp = ptr1 + i% !
eightbit% = my_peek_B(temp) !
if extra% = 1 then !
if eightbit% >= 128 then !
sevenbit% = eightbit% - 128 !
else !
sevenbit% = eightbit% !
end if !
select sevenbit% !
case < 32, 127 !
a$ = "." !
case else !
a$ = chr$(sevenbit%) !
end select !
a$ = " = "+ a$ !
else !
a$ = "" !
end if !
print using " ########## = ########## 'LLLLL";temp;eightbit%; a$ !
next i% !
end sub !