Redimensioning formal parameter arrays in OpenVMS BASIC

Skip to first unread message

T. Kurt Bond

May 8, 2003, 4:11:28 PM5/8/03
The BASIC for OpenVMS Reference Manual says, in the fifth item of the
Remarks section:

The executable DIM statement cannot be used to dimension virtual arrays,
arrays received as formal parameters, or arrays declared in COMMON, MAP,
or nonexecutable DIM statements.

The "no formal parameters" rule is inconvienent. It means that you
can't pass an array to a function, redimension it, fill it with values,
and then use LBOUND and UBOUND in the caller to find out its new size.

Presumably it is illegal because there is no way at compile time to
know if the function will be called with a dynamic array created with
the executable DIM statement or a static array created with a
non-executable DIM statement.

However, the programmer *can* know, so it ought to be safe to
redimension the array directly when the programmer knows it was
created by an executable DIM statement.

Using Alpha BASIC V1.4-000 under OpenVMS V7.2 and looking at the
listing of some code with some executable dimension statements
compiled with /LIST/MACHINE revealed the existance of DBASIC$RT_DIM
and after a little experimentation lead to a program that used
DBASIC$RT_DIM directly to redimension dynamically dimensioned arrays
in functions, included below.

DBASIC$RT_DIM is not documented for users (probably by design) and
could *theoretically* lead to flying monkeys and access violations,
and is probably bad style. However, are there any *practical*
reasons why this wouldn't work safely? Are there any
conditions under which this hack would fail to work?

Here is an example program:

program redim
option type = explicit, constant type = integer, &
size = integer long, size = real double

external sub redim_in_sub (string dim())
external long function my_redim (string dim(), long)

declare long i, r

i = 10
dim string vs(i) ! has to be a variable to make it an executable dim.

r = my_redim (vs(), 30)
print "ubound(vs):"; ubound(vs)
for i = lbound(vs) to ubound(vs) \ vs(i) = "vs 30-" + num1$(i) \ next i
gosub print_vs

call redim_in_sub (vs())
print "ubound(vs):"; ubound(vs)
gosub print_Vs

exit program

for i = lbound(vs) to ubound(vs) \ print i; ": "; vs(i) \ next i
return ! from print_vs

end program ! redim

function long my_redim (long s by value, long n)
option type = explicit, constant type = integer, &
size = integer long, size = real double
declare long r
external long function dbasic$rt_dim (long by value, long by value)
r = dbasic$rt_dim (s, n)
end function r ! my_redim

sub redim_in_sub (string s())
option type = explicit, constant type = integer, &
size = integer long, size = real double
external sub set_strings (string dim(), string)
declare long i
call my_redim (s(), 40)
for i = 0 to 40 \ s(i) = "redim in sub " + num1$(i) \ next i
end sub ! redim_in_sub

(Interestingly, a slightly different approach was necessary using VAX
BASIC V3.5 under VMS V5.5-2: using BY VALUE in function
definition statements is not allowed by this version of VAX BASIC,
and BAS$RT_DIM had to be used instead of DBASIC$RT_DIM, of course.)

T. Kurt Bond,

Reply all
Reply to author
0 new messages