forums.silverfrost.com
Welcome to the Silverfrost forums

Author Message
EKruck

Joined: 09 Jan 2010
Posts: 176
Location: Aalen, Germany

Posted: Wed Sep 28, 2016 10:46 am    Post subject: EQUIVALENCE Problem

In the first case i1Data and c1Data are not the same; in the second case well. What can I do?

 Code: :     iLength = 32     CALL Calculate (iLength)           :     SUBROUTINE Calculate (iLength)     INTEGER               iLength     INTEGER*1            i1Data(iLength)     CHARACTER*(iLength)  c1Data     EQUIVALENCE         (c1Data, i1Data(1))           : !----------------------------------------------                 :     CALL Calculate ()           :     SUBROUTINE Calculate ()     INTEGER, PARAMETER :: iLength = 32     INTEGER*1            i1Data(iLength)     CHARACTER*(iLength)  c1Data     EQUIVALENCE         (c1Data, i1Data(1))           :
wahorger

Joined: 13 Oct 2014
Posts: 427
Location: Morrison, CO, USA

 Posted: Wed Sep 28, 2016 8:41 pm    Post subject: Can you be a little more specific; what do you mean by "not the same"? If you look at LOC(i1Data(1)) and LOC(c1Data), are the results the same? If so, then the beginning address of the two items is the same physical memory location!
EKruck

Joined: 09 Jan 2010
Posts: 176
Location: Aalen, Germany

Posted: Thu Sep 29, 2016 7:12 am    Post subject:

You are right! I was expecting that. Run the attached program and you see the printed three groups should be but are not the same.
IF you activate the lines with !** the printed result is o.k.
Or alternatively:
Activate the lines with !++ instead of their neighbors, then the printed result is as well the same.
 Code: !-----------------------------------------------------------------------     PROGRAM cTest     IMPLICIT NONE     CHARACTER*400 inString     INTEGER       iLength     inString = ' 32  202020060103092042676F46756C6C20'     READ (inString, '(BN,I5)') iLength         CALL Calculate (iLength, inString) !++ CALL Calculate (inString)     END PROGRAM cTest !-----------------------------------------------------------------------     SUBROUTINE Calculate (iLength, inString) !++ SUBROUTINE Calculate (inString)     IMPLICIT NONE     CHARACTER*400         inString     INTEGER               iLength !++ INTEGER, PARAMETER :: iLength = 32     INTEGER               iOK, LTX, I     CHARACTER*(iLength)   cBuffer     INTEGER*1           i1Data(iLength)     CHARACTER*(iLength) c1Data     EQUIVALENCE        (c1Data, i1Data(1))     INTEGER, EXTERNAL :: CallTest     READ (inString, '(BN,I5,A)')  iLength, cBuffer !++ READ (inString, '(BN,5X,A)')  cBuffer     READ (cBuffer,  '(BN,160Z2)') i1Data   ! Read string to crypt !** DO I= 1, iLength !**    c1Data(I:I) = CHAR (i1Data(I)) !** ENDDO     LTX    = iLength / 2     WRITE  (*, *) ' '     WRITE  (*, '(''String lenghth  > '', I12)')    iLength     WRITE  (*, '(''Input  in HEX   > '',160Z2.2)') (i1Data(I), I=1,LTX)     WRITE  (*, '(''Input  in Int*1 > '', 16i4)')   (i1Data(I), I=1,LTX)     iOK  = CallTest (c1Data, iLength)     WRITE  (*, *) ' '     WRITE  (*, '(''Input  in HEX   > '',160Z2.2)') (i1Data(I), I=1,LTX)     WRITE  (*, '(''Input  in Int*1 > '', 16i4)')   (i1Data(I), I=1,LTX)     RETURN     END SUBROUTINE Calculate !-----------------------------------------------------------------------     INTEGER FUNCTION CallTest (c1Data, iLength)     IMPLICIT NONE     INTEGER        iLength     CHARACTER*32   c1Data     INTEGER*1      i1Data(32)     INTEGER        I, LTX     DO I= 1, iLength        i1Data(I) = ICHAR (c1Data(I:I))     ENDDO     LTX    = iLength / 2     WRITE  (*, *) ' '     WRITE  (*, '(''Parameter HEX   > '',160Z2.2)') (i1Data(I), I=1,LTX)     WRITE  (*, '(''Parameter Int*1 > '', 16i4)')   (i1Data(I), I=1,LTX)     CallTest = 0     RETURN     END FUNCTION CallTest !-----------------------------------------------------------------------

Last edited by EKruck on Sat Oct 08, 2016 8:17 am; edited 1 time in total
wahorger

Joined: 13 Oct 2014
Posts: 427
Location: Morrison, CO, USA

 Posted: Thu Sep 29, 2016 3:00 pm    Post subject: As coded and compiled using the DEBUG option, the results was that the conversion of ICHAR(c1Data(I:I)) in function CallTest fails. The Value of c1Data(I:I) is 128, which is the default value for an undefined (uninitialized) variable. Looking back in Calculate, c1Data is never given an initial value; it is "undefined" at run time. Which means every character is set to 128 (80 hex) by default). This is because the EQUIVALENCE statement is commented out.
EKruck

Joined: 09 Jan 2010
Posts: 176
Location: Aalen, Germany

 Posted: Thu Sep 29, 2016 5:08 pm    Post subject: Sorry, my mistake in a hurry. Please activate the EQUIVALENCE statement and you will see: It's still not running correct.
wahorger

Joined: 13 Oct 2014
Posts: 427
Location: Morrison, CO, USA

Posted: Thu Sep 29, 2016 7:47 pm    Post subject:

Yes, I see what you mean! Putting the LOC function in shows that the data locations are NOT the same, so the EQUIVALENCE is not actually working as one would have expected. It would appear you have found a bug, but I hesitate to say what kind of bug (error not given when it should, or bad code generation are two possibilities).

Also, the program (as written) would NOT run properly in /CHECKMATE mode at all because the uninitialized data is still a problem (due to the addresses not being properly equivalenced.

However, by declaring the array sizes as a static size and accommodating the read of the character buffer with an implied DO-loop for idata, the program works fine. See the code posting of the changes after this next section.

 Code: Non-working version: !-----------------------------------------------------------------------     PROGRAM cTest     IMPLICIT NONE     CHARACTER*400 inString     INTEGER       iLength     inString = ' 32  202020060103092042676F46756C6C20'     READ (inString, '(BN,I5)') iLength         CALL Calculate (iLength, inString) !++ CALL Calculate (inString)     END PROGRAM cTest !-----------------------------------------------------------------------     SUBROUTINE Calculate (iLength, inString) !++ SUBROUTINE Calculate (inString)     IMPLICIT NONE     CHARACTER*400         inString     INTEGER               iLength !++ INTEGER, PARAMETER :: iLength = 32     INTEGER               iOK, LTX, I     CHARACTER*(iLength)   cBuffer     INTEGER*1           i1Data(iLength)     CHARACTER*(iLength) c1Data    EQUIVALENCE        (c1Data, i1Data)     INTEGER, EXTERNAL :: CallTest    print *,"Location of character data =",loc(c1data)     print *,"Location of integer data   =",loc(i1Data)         READ (inString, '(BN,I5,A)')  iLength, cBuffer !++ READ (inString, '(BN,5X,A)')  cBuffer     READ (cBuffer,  '(BN,160Z2)') i1Data   ! Read string to crypt !** DO I= 1, iLength !**    c1Data(I:I) = CHAR (i1Data(I)) !** ENDDO     LTX    = iLength / 2     WRITE  (*, *) ' '     WRITE  (*, '(''String lenghth  > '', I12)')    iLength     WRITE  (*, '(''Input  in HEX   > '',160Z2.2)') (i1Data(I), I=1,LTX)     WRITE  (*, '(''Input  in Int*1 > '', 16i4)')   (i1Data(I), I=1,LTX)     iOK  = CallTest (c1Data, iLength)     WRITE  (*, *) ' '     WRITE  (*, '(''Input  in HEX   > '',160Z2.2)') (i1Data(I), I=1,LTX)     WRITE  (*, '(''Input  in Int*1 > '', 16i4)')   (i1Data(I), I=1,LTX)     RETURN     END SUBROUTINE Calculate !-----------------------------------------------------------------------     INTEGER FUNCTION CallTest (c1Data, iLength)     IMPLICIT NONE     INTEGER        iLength     CHARACTER*32   c1Data     INTEGER*1      i1Data(32)     INTEGER        I, LTX    print *,"Location of input data=",loc(c1data)        DO I= 1, iLength        write(*,*)"At Index=",i," Char date=",ichar(c1data(i:i))        i1Data(I) = ICHAR (c1Data(I:I))     ENDDO     LTX    = iLength / 2     WRITE  (*, *) ' '     WRITE  (*, '(''Parameter HEX   > '',160Z2.2)') (i1Data(I), I=1,LTX)     WRITE  (*, '(''Parameter Int*1 > '', 16i4)')   (i1Data(I), I=1,LTX)     CallTest = 0     RETURN     END FUNCTION CallTest !-----------------------------------------------------------------------

This works:

[code:1:a53db70234] CHARACTER*(400) cBuffer

INTEGER*1
wahorger

Joined: 13 Oct 2014
Posts: 427
Location: Morrison, CO, USA

Posted: Thu Sep 29, 2016 7:48 pm    Post subject:

Oh bummer, exceeded the max message length. Here's the code section to change to make it work properly.

 Code: CHARACTER*(400)   cBuffer     INTEGER*1           i1Data(400)     CHARACTER*(400) c1Data    EQUIVALENCE        (c1Data, i1Data)     INTEGER, EXTERNAL :: CallTest    print *,"Location of character data =",loc(c1data)     print *,"Location of integer data   =",loc(i1Data)         READ (inString, '(BN,I5,A)')  iLength, cBuffer !++ READ (inString, '(BN,5X,A)')  cBuffer     READ (trim(cBuffer),  '(BN,160Z2)') (i1Data(i),i=1,ilength)   ! Read string to crypt
EKruck

Joined: 09 Jan 2010
Posts: 176
Location: Aalen, Germany

 Posted: Thu Sep 29, 2016 8:12 pm    Post subject: Paul, it looks really like a bug - probably a new one. With earlier FTN95 version I do not remember those problens. I have a lot of those parts in my software. The interesting point is, that comilation with /64 provides different results. Parts which are working in the 32-bit version fail with /64 and vice versa. I decided to remove the EQUIVALENCE statements and copy between INTEGER*1 and character variables using CHAR and ICHAR. Erwin
wahorger

Joined: 13 Oct 2014
Posts: 427
Location: Morrison, CO, USA

 Posted: Thu Sep 29, 2016 9:18 pm    Post subject: There's probably some reason why you cannot dynamically allocate an array and then equivalence it to another dynamic array. It really doesn't make sense because the compiler cannot determine intent when the allocation is at run-time. While it might work, I think it is odd to try. At least in "C" or "C++", you could allocate an array as character and then type cast the pointer to an integer. You then have the same effect as an "EQUIVALENCE" but with dynamic arrays. A problem/solution better left to Paul!
John-Silver

Joined: 30 Jul 2013
Posts: 708

Posted: Fri Sep 30, 2016 11:54 am    Post subject:

 Quote: EQUIVALENCE (c1Data, i1Data(1))

I'm having trouble following this !

How can a character variable (c1Data) of variable length 'istring' be EQUIValenced to an Integer variable (i1Data(1) ???
EKruck

Joined: 09 Jan 2010
Posts: 176
Location: Aalen, Germany

 Posted: Fri Sep 30, 2016 4:02 pm    Post subject: John, please note that it is integer*1, i.e. each character is one int*1. The length of both is identical, but this is not required. I'm using this since years with success. Erwin
 Display posts from previous: All Posts1 Day7 Days2 Weeks1 Month3 Months6 Months1 Year Oldest FirstNewest First
 All times are GMT + 1 Hour Page 1 of 1