[Search for users]
[Overall Top Noters]
[List of all Conferences]
[Download this site]
Title: | DEC Pascal Bug Reports |
Notice: | New kit announcement in TURRIS::Pascal conference |
Moderator: | TLE::GARRISON |
|
Created: | Wed Sep 09 1992 |
Last Modified: | Fri May 30 1997 |
Last Successful Update: | Fri Jun 06 1997 |
Number of topics: | 838 |
Total number of notes: | 3659 |
834.0. "Pascal V5.5 ACCVIO with SUBSTR()" by TLE::REAGAN (All of this chaos makes perfect sense) Tue Mar 18 1997 15:32
<<< TURRIS::DISK$NOTES_PACK:[NOTES$LIBRARY]PASCAL.NOTE;2 >>>
-< DEC Pascal Notes >-
================================================================================
Note 2664.0 Pascal V5.5 ACCVIO with SUBSTR() function 1 reply
CSC32::D_SANFORD 301 lines 18-MAR-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 |
---|
834.1 | | TLE::REAGAN | All of this chaos makes perfect sense | Tue Apr 15 1997 11:46 | 142 |
| OK, first of all, I'm still not sure why the code for SUBSTR() got
a little worse (making a local copy versus using the pointer directly),
but I think the customer realizes that since they "lied" to the
compiler about the type of the pointer.
You can use the [TRUNCATE] attribute to support optional parameters
like they want. With [TRUNCATE] and conformant arrays and varying
strings, you can get the compiler to do all the length computation
for you. So you can use the PRESENT builtin with TRUNCATE and compute
the defaults yourself.
Here's the rewritten code to give back to the customer:
PROGRAM A
IMPLICIT NONE
INTEGER*4 PROTECTREST
INTEGER*4 STATUS
STATUS = PROTECTREST ( 'RESTNAME', 'APPNAME',
1 'FAMILY', 'NOWAIT' )
STATUS = PROTECTREST ( 'RESTNAME', 'APPNAME',
1 'FAMILY' )
STATUS = PROTECTREST ( 'RESTNAME', 'APPNAME')
STATUS = PROTECTREST ( 'RESTNAME')
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
[INHERIT( 'sys$library:pascal$lib_routines',
'sys$library:pascal$str_routines' )]
MODULE b (input, output);
[ 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
( dataset : [class_s, truncate] packed array [l1..u1:integer] of char;
application : [class_s, truncate] packed array [l2..u2:integer] of char;
family : [class_s, truncate] packed array [l3..u3:integer] of char;
waitmode : [class_s, truncate] packed array [l4..u4:integer] of char)
: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 : varying [40] of char;
a_name : varying [8] of char;
f_name : varying [8] of char;
w_mode : varying [6] of char;
begin
if present(dataset)
then
d_name := dataset
else
d_name := ' ';
if present(application)
then
a_name := application
else
a_name := ' ';
if present(family)
then
f_name := family
else
f_name := ' ';
if present(waitmode)
then
w_mode := waitmode
else
w_mode := 'NOWAIT';
hlk$new_protect_rest := hlk$protect_dataset ( d_name, a_name, f_name );
end ;
end { module } .
|
834.2 | | TLE::REAGAN | All of this chaos makes perfect sense | Tue Apr 15 1997 12:23 | 9 |
| I just checked and the next baselevel of GEM is somewhat better than
the code for SUBSTR you saw with the V5.5-55, but isn't quite a good as
it was back with V5.3-35. I'll try to track it down and work with GEM
to see if we can get back to what we used to generate.
However, the code still is technically broken and the rewritten code
I provided should be much better with any of the compilers.
-John
|