Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Exception error

JohnNichols
Valued Contributor III
743 Views

There is an exception error in the code and I cannot understand fully why it is occurring.  

I have a set of routines from the late 1980s.  The routine is called  DRAWN, line 30 in the printout is throwing an exception on Y2.  

 

It is all in the file acad.f90.   This is the calling line.  

CALL DRAWN (A2+d9,ds + d12,0.0,0.0,2,COLOUR2,1)

This draws to DXF files and I never want numbers less than 0, so I trap them and usually draw them to zero.  

 

I was playing with the plotter on a funny line and I deliberately drew it to zero zero,  just using 0.0, 0.0 in the calling line.  There was a mistake in the routine, and it checked for less than Y2 < 0.1.  

It them threw a breakpoint when it tried to set Y2 to 0.0


    CALL DRAWN (A2+d9,ds + d12,d100,d100,2,COLOUR2,1)

if I create a variable d100 and set to 0.0 it all works and I get the error message.  

But I do not understand if Y2 is a local variable in Drawn why it cannot be changed -  I can see a reason, just checking this was intended. 

 



    !      ************************************************************
    !
    SUBROUTINE DRAWN (X1,Y1,X2,Y2,NC,N_COLOUR,I)
    !
    !      ************************************************************

    implicit none
    real X1,Y1,X2,Y2
    integer NC,N_COLOUR,I

    If(X1 .lt. 0.0) then
        X1 = 0.0
        Write(*,100)X1,Y1,X2,Y2
100     Format("     You have a number less then zero in plotting - this is not permitted :: ",4(E10.2,3x))
        !        pause
    endif
    If(Y1 .lt. 0.0) then
        Y1 = 0.0
        Write(*,100)X1,Y1,X2,Y2
        !        pause
    endif
    If(X2 .lt. 0.0) then
        X2 = 0.0
        Write(*,100)X1,Y1,X2,Y2
        !        pause
    endif
    If(Y2 .lt. 0.0) then
        Y2 = 0.0
        Write(*,100)X1,Y1,X2,Y2
        !       pause
    endif

    WRITE(3,10)I
10  FORMAT(1X,' 0',/&
        ,'LINE',/&
        ,'999',/&
        ,'UNIT !ALL => ',I3,/&
        ,'  8')

    IF (NC .EQ. 1) THEN
        WRITE(3,11)
11      FORMAT( 'PIPE')
    ELSEIF (NC .EQ. 2) THEN
        WRITE(3,12)
12      FORMAT( 'CABLES')
    ELSEIF (NC .EQ. 3) THEN
        WRITE(3,13)
13      FORMAT( 'MAN_HOLE')
    ELSEIF (NC .EQ. 4) THEN
        WRITE(3,14)
14      FORMAT( 'NAT_SURF')
    ELSEIF (NC .EQ. 5) THEN
        WRITE(3,15)
15      FORMAT( 'BOX_25')
    ELSEIF (NC .EQ. 6) THEN
        WRITE(3,16)
16      FORMAT( 'ARROW_25')
    ELSEIF (NC .EQ. 7) THEN
        WRITE(3,50)
50      FORMAT( 'HYDRAULIC_L')
    ELSEIF (NC .EQ.  THEN
        WRITE(3,51)
51      FORMAT( 'UP_HYDRAULIC')
    ENDIF

    WRITE(3,17)
17  FORMAT( '  62')
    WRITE(3,18)N_COLOUR
18  FORMAT( I2)
!    write(3,170)
!170 Format('  6'   )
!write(3,171)
!171 Format('ACAD_ISO02W100')
!write(3,172)
!172 Format('370')

!write(3,173)
!173 Format('   100')
    WRITE(3,19)
19  FORMAT(  ' 10')


    CALL LINE1(X1)

    WRITE(3,20)
20  FORMAT(1X,'20'  )

    CALL LINE1(Y1)

    WRITE(3,30)
30  FORMAT(1X,'11'  )

    CALL LINE1(X2)

    WRITE(3,40)
40  FORMAT(1X,'21'  )

    CALL LINE1(Y2)

    RETURN
    END

 

Screenshot 2022-07-16 100334.png

Screenshot 2022-07-16 100447.png

Screenshot 2022-07-16 100400.png

0 Kudos
4 Replies
Mentzer__Stuart
731 Views

Fortran passes by reference so assigning to literals and expressions is illegal so this usage is undefined behavior. Pass with %VAL wrappers on those arguments then they are pass-by-value and you can modify them safely.

 

Early Fortran compilers would let you modify a literal with such a bug so you could literally (sorry) make 1 == 2.

JohnNichols
Valued Contributor III
726 Views

never met an engineer who could not make 1 == 2 under normal circumstances.  

0 Kudos
cryptogram
New Contributor I
667 Views

I managed to do something like this back on the 360 mainframe.  I'd passed the constant 0.0 to a routine, where was used as an angle.  I wanted this angle to be in the range 0-360, and did some math on the argument make sure that it was.  I was a bad boy and assigned the result back into the argument.    The bit pattern of 0.0 coming in was  00 00 00 00, which is the normalized representation of real 0 on the IBM 360 architecture.   After the range checking, the bit pattern was changed.  It should have still been zero, but now it was different.  Something with the bit pattern  04 xx xx xx.  Perhaps an unnormalized version of 0, or maybe some small number.

 

In any case, the major effect of the error was immediate and showed up elsewhere.  In the same program, I often needed passed the constant 0 to routines.  This was integer 0.   What happened is that the compiler created one constant in memory 00 00 00 00, and used this same memory location for both real 0.0  and integer 0 constants.  When the bit pattern for real 0.0 was changed, this changed all the integer constants to a very large integer.

 

 

 

 

0 Kudos
JohnNichols
Valued Contributor III
649 Views

Thanks for the story, it gave me a good chuckle.  

I should have immediately realized what had happened, but I was thinking the local copy of the variable should have been changed whilst the global one was left as 0.00.  Too many languages, not enough thinking.  

When AutoCAD came to Australia, it included AUTOLISP, which was a boon in helping with fixing drawings.  A client walked in one day and asked, can you draw us longitudinal sections of pipelines for rising mains if we give you the data at each chainage.   It was faster to write a Fortran program to draw using a DXF file than anything else, + Fortran is way faster than LISP.  

I enclose the 1991 program, I looked at it again in 2014 just for fun.  It needs implicit  none and removal of the commons, but it is still useful for quick and nasty drawing.  I called the program Helga after Hagar's wife in the comic.  

 


(vmon)

(defun firststage ()

    (copy_write_information)
    (plot_information)
    (set_flags)
    (second_stage) ;the main body of the programme

)


(defun second_stage ()

    (while (< repeat_flag 1)
     (cond ((> count2 1)(zoom_p))
     )
     (reset_flags)
     (selection_set)
     (next_entry)
     (while (< flag_while 1)	       ;loop to last entry
      (cond ((= flag_test 1)(setq flag_while 1))  ;do last entry before EOL
	    ( T (third_stage))
      )
     )
     (end_test)
    )

)

(defun third_stage ()

    (setq type_1 (cdr (assoc 0 (entget e))))
    (cond ((equal type_1 "TEXT")  (fourth_stage))
	  ( T			  (other_list))
    )
    (next_entry)
)


(defun fourth_stage ()

    (setq num4 (+ num4 1))
    (setq a (entget e))
    (setq original-ht  (assoc int-num a))
    (setq b int-num)
    (setq new (cons b txtht))
    (setq a (subst new original-ht a))
    (entmod a)
    (write-line " A text entity has been changed!")

)



(defun copy_write_information ()
 
    (setvar "CMDECHO" 0)
    (write-line "")
    (write-line " This programme was developed by John Nichols ")
    (write-line " (C) JOHN NICHOLS, October 1987. ")

)

(defun plot_information ()

;    (initget (+ 1 2 4))
 ;   (setq txtht (getreal " Text height for the new text:"))
     (setq answ (getstring "Style, Layer, Height, or Angle : "))
     (cond ((or (equal answ "S")(equal answ "s"))(set_style)) 
           ((or (equal answ "L")(equal answ "l"))(set_layer))
           ((or (equal answ "h")(equal answ "H"))(set_height))
           ((or (equal answ "A")(equal answ "a"))(set_angle))
           ((or (equal answ "C")(equal answ "c"))(plot_information))
           (T (plot_information))
     )

)

(defun set_style      ()

     (setq int-num 7)
     (setq txtht (getstring " Style type <you check validity> :"))
     
)

(defun set_height ()

     (setq int-num 40)
     (initget (+ 1 2 4))
     (setq txtht (getreal " Text height for the new text:"))
     
)

(defun set_layer ()

     (setq int-num 8)
     (setq txtht (getstring " New Layer <make it first> :"))
     
)
(defun set_color  ()

     (setq int-num 62)
     (initget (+ 1 2 4))
     (setq txtht (getint " Text color for the text:"))
     
)

(defun set_angle  ()

     (setq int-num 50)
     (initget (+ 1 4))
     (setq txtht (getreal " Text angle for the text < 2pi>:"))
     
)


(defun set_flags ()

    (setq repeat_flag 0)
    (setq num 0)
    (setq num1 0)
    (setq num2 0)
    (setq num3 0)
    (setq num4 0)
    (setq count2 1)

)

(defun reset_flags ()

;   (setq flag_start 0)
    (setq flag_type 0)
    (setq flag_while 0)
    (setq flag_test 0)
    (setq count 0)
    (setq count1 1)

)

(defun end_test ()

    (setq q1 (getstring " Was that the last text change <Y/N> ? "))
    (cond ((or (equal q1 "Y")(equal q1 "y"))(next_group_1))
	  ( T (next_group))
    )
    (setq count2 (1+ count2))
    (princ)

)

(defun next_group_1 ()

    (setq repeat_flag 1)

)

(defun next_group ()
  
    (write-line " The next text group ")
    (plot_information)

)

(defun selection_set ()

    (write-line (strcat " This is text change group "(rtos count2 2 0)" ."))
    (zoom_drawing)
    (setq set-items (ssget))
    (setq num-ent (sslength set-items))

)

(defun zoom_p ()

    (command"zoom" "p")
    (command)

)

(defun zoom_drawing ()

    (setq pta (getpoint " The lower  left corner for the view area ? "))
    (setq ptb (getpoint " The upper right corner for the view area ? "))
    (command "zoom" "w" pta ptb)
    (command)

)

(defun next_entry ()

    (setq e (ssname set-items count))
    (cond ((=  count num-ent)(setq flag_test 1))
    )
    (setq count (1+ count))
    (setq count1 (1+ count1))

)

(defun other_list ()

    (setq num3 (+ num3 1))
    ( write-line " Another entity has been counted that was not changed !")

)

(defun C:MULL ()

   (firststage)

)

 

 But if you needed quick changes on the drawing, then LISP is good.  + Lisp is easy to read.   This program let the draughting person make global changes to a DWG file.    But LISP was hard to learn with only the manual and that is really small and skimpy and no internet.  I finally got the Winston and Horne book and knew I was in Heaven.  

Horses for courses. 

0 Kudos
Reply