Redimensioning formal parameter arrays in OpenVMS BASIC

57 views
Skip to first unread message

T. Kurt Bond

unread,
May 8, 2003, 4:11:28 PM5/8/03
to
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.

http://h71000.www7.hp.com/doc/73final/cobol/bas_ref_013.htm#noisn

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

print_vs:
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, t...@tkb.mpl.com

T. Kurt Bond

unread,
Feb 5, 2022, 3:56:27 PMFeb 5
to
On Thursday, May 8, 2003 at 4:11:28 PM UTC-4, T. Kurt Bond wrote:
> 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.
> http://h71000.www7.hp.com/doc/73final/cobol/bas_ref_013.htm#noisn
> 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[.]

> (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, t...@tkb.mpl.com

I needed this again for a program I was writing on a VAX. (The VAX is running VMS V5.5-2; It's like I am in 1992 all over again!)

Anyway, I ended up figuring out how to pass the lower bound (call BAS$RT_DIM_BOUNDS instead) and how to use the same redim procedure with different types, plus simplified things a little. Here's my new version:

program vax_redim_best
option type = explicit, constant type = integer, &
size = integer long, size = real double
record rec
string s = 13
long i
end record rec

! Don't declare the parameters, and everything works, even passing
! different types.
external sub redim

declare long stat, i
i = 1
dim rec rec(1 to i)
print "lbound (rec) at start: "; lbound (rec)
print "ubound (rec) at start: "; ubound (rec)
call redim (rec(), 3, 10)
print "lbound (rec) after redim: "; lbound (rec)
print "ubound (rec) after redim: "; ubound (rec)

dim string s(1 to i)
print "lbound (s) at start: "; lbound (s)
print "ubound (s) at start: "; ubound (s)
call redim (s(), 3, 10)
print "lbound (s) after redim: "; lbound (s)
print "ubound (s) after redim: "; ubound (s)

dim long l(1 to i)
print "lbound (l) at start: "; lbound (l)
print "ubound (l) at start: "; ubound (l)
call redim (l(), 3, 10)
print "lbound (l) after redim: "; lbound (l)
print "ubound (l) after redim: "; ubound (l)


end program ! vax_redim_best

function long redim (long s, long low, long high)
option type = explicit, constant type = integer, &
size = integer long, size = real double
external long function bas$rt_dim_bounds (long by value, long by value, long by value)
declare long r
r = bas$rt_dim_bounds (loc (s), low, high)
end function r ! redim

Reply all
Reply to author
Forward
0 new messages