[Search for users]
[Overall Top Noters]
[List of all Conferences]
[Download this site]
Title: | DEC Pascal Notes |
Notice: | See note 1 for kits. Bug reports to CLT::DEC_PASCAL_BUGS |
Moderator: | TLE::REAGAN |
|
Created: | Sat Jan 25 1986 |
Last Modified: | Tue Jun 03 1997 |
Last Successful Update: | Fri Jun 06 1997 |
Number of topics: | 2675 |
Total number of notes: | 13409 |
2664.0. "Pascal V5.5 ACCVIO with SUBSTR() function" by CSC32::D_SANFORD () Tue Mar 18 1997 12:55
Pascal V5.5-52, OpenVMS Alpha V6.2, V7.1 - ACCVIO with SUBSTR()
Pascal V5.4, OpenVMS Alpha V6.2 ok
Pascal V5.4-41, OpenVMS VAX V6.0 ok
SUBSTR() fails with an ACCVIO after upgrading to Pascal V5.5-52 on OpenVMS
Alpha.
Included below is a command file to duplicate the problem along with
notes from the customer.
Regards, Drew Sanford
Customer Support Center
C970225-6728
$ !
$ ! We have just switched from Pascal V5.3-35 (on an Alpha 3000/400,
$ ! running OpenVMS V6.2) to Pascal V5.5-55 (on an Alphastation 255/233,
$ ! running OpenVMS V7.1). (We had the same problem when we tried
$ ! Pascal V5.5 on the older Alpha and OpenVMS V6.2.)
$ !
$ ! I'm including a reproducer at the end of this message. It
$ ! comprises two source files, A.FOR and B.PAS. The call tree is:
$ !
$ ! A (Fortran)
$ ! |
$ ! |--hlk$new_protect_rest (Pascal) (externally called protectrest)
$ ! |
$ ! |--hlk$protect_dataset (Fortran)
$ !
$ ! The Pascal function's arguments are all character strings, but it
$ ! is designed to handle a variable number of actual arguments. For
$ ! that reason, each formal argument is defined as a somewhat
$ ! generic character string descriptor (with an array of length
$ ! 65535 to cover all possible actual strings). The intention is
$ ! that we will use the length of each actual parameter to copy the
$ ! actual string to a fixed-length string inside the function.
$ !
$ ! Historically, this worked fine. With Pascal 5.5, however, there
$ ! is an accvio when processing the following statement, which
$ ! copies the actual argument to the fixed-length string.
$ !
$ ! ustatus := str$trim (
$ ! d_name ,
$ ! substr( dataset.strptr^, 1, dataset.length ) ,
$ ! d_len
$ ! ) ;
$ !
$ ! I found that the accvio is due to the program trying to copy 65535
$ ! characters from the actual argument to someplace else, probably a
$ ! temporary location on the stack. I believe it is doing it as
$ ! part of the substr function. In Pascal 5.3, it simply copied
$ ! either the size of the substring or the size of the destination
$ ! string. (I'm not sure which and can test it if you need me to.)
$ !
$ ! My main question is whether there is some other idiom we should
$ ! be using to provide the functionality of the CHARACTER*(*) type
$ ! declaration in Fortran and the ability to have some formal
$ ! arguments that have no corresponding actual arguments. I believe
$ ! I could write my own loop to copy the first n characters from
$ ! each passed string to each destination string, but that could be
$ ! many places in our code and I'd like to avoid doing that, if
$ ! possible.
$ !
$ create call-pascal.for
PROGRAM A
IMPLICIT NONE
INTEGER*4 PROTECTREST
INTEGER*4 STATUS
STATUS = PROTECTREST ( 'RESTNAME', 'APPNAME',
1 'FAMILY', 'NOWAIT' )
PRINT *, 'Status = ', STATUS
END
INTEGER*4 FUNCTION HLK$PROTECT_DATASET ( FAMILY,
1 APPLICATION,
1 DATASET )
IMPLICIT NONE
CHARACTER*(*) FAMILY
CHARACTER*(*) APPLICATION
CHARACTER*(*) DATASET
PRINT *, 'Family: ', FAMILY, ' Application: ',
1 APPLICATION, ' Dataset: ', DATASET
HLK$PROTECT_DATASET = 1
RETURN
END
$ create test.pas
[INHERIT( 'sys$library:pascal$lib_routines',
'sys$library:pascal$str_routines' )]
MODULE b (input, output);
CONST
maxint_uword = 65535 ;
TYPE
uword = [WORD(1)] 0..65535 ;
ubyte = [BYTE(1)] 0..255 ;
string$max = packed array [ 1..maxint_uword ] of char ;
string$ptr = ^string$max ;
string$descr =
[QUAD(1)] RECORD
length : [POS(0)] uword;
dtype : [POS(16)] ubyte;
class : [POS(24)] ubyte;
strptr : [POS(32)] string$ptr
END;
VAR
str$_tru : [VALUE, EXTERNAL] UNSIGNED ;
[ EXTERNAL, UNBOUND ] function hlk$protect_dataset (
family : [ class_s ] packed array [ l1..u1 : integer ] of char ;
application : [ class_s ] packed array [ l2..u2 : integer ] of char ;
dataset : [ class_s ] packed array [ l3..u3 : integer ] of char
) : unsigned ; EXTERNAL;
[GLOBAL(protectrest), UNBOUND]
FUNCTION hlk$new_protect_rest
(VAR dataset : [READONLY, TRUNCATE, UNSAFE] string$descr;
VAR application : [READONLY, TRUNCATE, UNSAFE] string$descr;
VAR family : [READONLY, TRUNCATE, UNSAFE] string$descr;
VAR waitmode : [READONLY, TRUNCATE, UNSAFE] string$descr)
:UNSIGNED;
{
FUNCTIONAL DESCRIPTION:
This function is designed solely for the support of
existing FORTRAN and MACRO programs which rely upon
the use of 'optional' arguments that may place a 0
into the argument list.
FORMAL PARAMETERS:
dataset : fixed-length string, input.
The dataset to be protected.
application : fixed-length string, input.
The application context of the dataset.
family : fixed-length string, input.
The family context of the dataset.
waitmode : fixed-length string, input.
Indicates whether the caller wants to
wait until the request can be granted.
Supported values are: 'WAIT' and 'NOWAIT'.
ROUTINE VALUE:
Returns an unsigned integer indicating the overall completion
status of the request.
SIDE EFFECTS:
Any unexpected errors are signaled immediately.
}
var
d_name : packed array [ 1..40 ] of char ;
a_name : packed array [ 1..8 ] of char ;
f_name : packed array [ 1..8 ] of char ;
w_mode : packed array [ 1..6 ] of char ;
d_len, a_len, f_len, w_len : uword ;
ustatus : unsigned ;
begin
ESTABLISH( lib$sig_to_stop );
d_name := ' ' ;
d_len := 1 ;
if present( dataset )
then
begin
if iaddress( dataset ) <> 0
then
begin
ustatus := str$trim (
d_name ,
substr( dataset.strptr^, 1, dataset.length ) ,
d_len
) ;
if not odd(ustatus)
then
begin
if ustatus = str$_tru
then
lib$signal( 2 )
else
lib$signal( ustatus ) ;
end ;
end ;
end ;
a_name := ' ' ;
a_len := 1 ;
if present( application )
then
begin
if iaddress( application ) <> 0
then
begin
ustatus := str$trim (
a_name ,
substr( application.strptr^, 1, application.length ) ,
a_len
) ;
if not odd(ustatus)
then
begin
if ustatus = str$_tru
then
lib$signal( 3 )
else
lib$signal( ustatus ) ;
end ;
end ;
end ;
f_name := ' ' ;
f_len := 1 ;
if present( family )
then
begin
if iaddress( family ) <> 0
then
begin
ustatus := str$trim (
f_name ,
substr( family.strptr^, 1, family.length ) ,
f_len
) ;
if not odd(ustatus)
then
begin
if ustatus = str$_tru
then
lib$signal( 4 )
else
lib$signal( ustatus ) ;
end ;
end ;
end ;
w_mode := 'NOWAIT' ;
w_len := 6 ;
if present( waitmode )
then
begin
if iaddress( waitmode ) <> 0
then
begin
ustatus := str$trim (
w_mode ,
substr( waitmode.strptr^, 1, waitmode.length ) ,
w_len
) ;
if not odd(ustatus)
then
begin
if ustatus = str$_tru
then
lib$signal( 5 )
else
lib$signal( ustatus ) ;
end ;
end ;
end ;
hlk$new_protect_rest := hlk$protect_dataset (
dataset := substr( d_name, 1, d_len ),
application := substr( a_name, 1, a_len ),
family := substr( f_name, 1, f_len )
) ;
REVERT;
end ;
end { module } .
$ !
$ fortran call-pascal
$ pascal test
$ link call-pascal,test
$ run call-pascal
T.R | Title | User | Personal Name | Date | Lines |
---|
2664.1 | | TLE::REAGAN | All of this chaos makes perfect sense | Tue Mar 18 1997 15:32 | 3 |
| I'm moving this to CLT::DEC_PASCAL_BUGS so I can track it.
-John
|