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

Exit from a subroutine to a program

h_amini
Beginner
3,779 Views

Hi there

Could someone let me know if it is possible to go to a specific line of a program from a subroutine.

For example, the following program is to print only positive inputted numbers, but error #6323 occurs in compiling.

PROGRAM test01

1 READ*, x

CALL a(x)

GO TO 1

END PROGRAM test01

subroutine a(x)

if (x.lt.0) go to 1

print*, x

return

end

TEST01.F(7): error #6323: This label is not defined in this scoping unit. [1]

if (x.lt.0) go to 1

---------------------^

Many thanks

Hamid

0 Kudos
1 Solution
Les_Neilson
Valued Contributor II
3,779 Views
Quoting - h.amini

Hi there

Could someone let me know if it is possible to go to a specific line of a program from a subroutine.

There is something called "ALTERNATE RETURN" Look it up in the help.
Opinion varies as to it being a good or bad feature. Personally I consider it very bad.
Modifying your code slighlty :-

PROGRAM test01

1 READ*, x

CALL a(x,*1, *999) ! The *1, *2are the alternate returns

GO TO 1

999 continue

END PROGRAM test01

subroutine a(x, *, *) ! Ugly * in argument list

if (x.lt.0)return 1 ! return to the label identified by the

! first alternate return

if (x.eq.0)return2 ! return to the label identified by the

! second alternate return

print*, x

return

end

Les

View solution in original post

0 Kudos
9 Replies
jimdempseyatthecove
Honored Contributor III
3,779 Views
Quoting - h.amini

Hi there

Could someone let me know if it is possible to go to a specific line of a program from a subroutine.

For example, the following program is to print only positive inputted numbers, but error #6323 occurs in compiling.

PROGRAM test01

1 READ*, x

CALL a(x)

GO TO 1

END PROGRAM test01

subroutine a(x)

if (x.lt.0) go to 1

print*, x

return

end

TEST01.F(7): error #6323: This label is not defined in this scoping unit. [1]

if (x.lt.0) go to 1

---------------------^

Many thanks

Hamid

The label 1 of program test01 is outside the scope of subroutine a.

Consider changing subroutine a into a function a that returns an error code or logical (.true. or .false.) then testing the return value after evocation.

Jim Dempsey

0 Kudos
Les_Neilson
Valued Contributor II
3,780 Views
Quoting - h.amini

Hi there

Could someone let me know if it is possible to go to a specific line of a program from a subroutine.

There is something called "ALTERNATE RETURN" Look it up in the help.
Opinion varies as to it being a good or bad feature. Personally I consider it very bad.
Modifying your code slighlty :-

PROGRAM test01

1 READ*, x

CALL a(x,*1, *999) ! The *1, *2are the alternate returns

GO TO 1

999 continue

END PROGRAM test01

subroutine a(x, *, *) ! Ugly * in argument list

if (x.lt.0)return 1 ! return to the label identified by the

! first alternate return

if (x.eq.0)return2 ! return to the label identified by the

! second alternate return

print*, x

return

end

Les

0 Kudos
Jugoslav_Dujic
Valued Contributor II
3,779 Views
Quoting - Les Neilson

Opinion varies as to it being a good or bad feature. Personally I consider it very bad.

I don't think that the "opinion varies" -- the opinion that it's bad is fairly equivocal :-).

0 Kudos
Les_Neilson
Valued Contributor II
3,779 Views
Quoting - Jugoslav Dujic
I don't think that the "opinion varies" -- the opinion that it's bad is fairly equivocal :-).

Alas if the person who wrotethe code that I have modified since I started work here,is still out there and coding then at least one person likes alternate return. :-(

(BTW I see we are still without "smileys")

Les

0 Kudos
h_amini
Beginner
3,779 Views

The label 1 of program test01 is outside the scope of subroutine a.

Consider changing subroutine a into a function a that returns an error code or logical (.true. or .false.) then testing the return value after evocation.

Jim Dempsey

Many thanks Jim, but I have to use a subroutine

Hamid

0 Kudos
h_amini
Beginner
3,779 Views
Quoting - Les Neilson

There is something called "ALTERNATE RETURN" Look it up in the help.
Opinion varies as to it being a good or bad feature. Personally I consider it very bad.
Modifying your code slighlty :-

PROGRAM test01

1 READ*, x

CALL a(x,*1, *999) ! The *1, *2are the alternate returns

GO TO 1

999 continue

END PROGRAM test01

subroutine a(x, *, *) ! Ugly * in argument list

if (x.lt.0)return 1 ! return to the label identified by the

! first alternate return

if (x.eq.0)return2 ! return to the label identified by the

! second alternate return

print*, x

return

end

Les

Many thanks Les

Could you explain why you consider it a very bad idea. I do need it in the code I am writing.

Hamid

0 Kudos
Les_Neilson
Valued Contributor II
3,779 Views
Quoting - h.amini

Many thanks Les

Could you explain why you consider it a very bad idea. I do need it in the code I am writing.

Hamid

Ugly, Readability, Maintainability, ...
One way to avoid alternate return is to use a status return value :

subroutine foo(x,istat)
istat = 0
if (x .lt. 0) istat = 1
if (x .eq. 0) istat = 2
etc.
if (istat .ne. 0) return
... do something ...
end subroutine foo

For more complex variations on the values of istatin your main you would use a SELECT CASE on istat after calling foo. Or you could just use simple if statements

call foo(x,istat)
if (istat .eq. 1) go to 1
if (istat .eq. 2) go to 999
etc...

In your simplified example you could write it as

program main
integer :: istat
real :: x
istat = 0
DO WHILE (istat==0)
read *,x
call foo(x,istat)
ENDDO

subroutine foo(x, istat)
real :: x
integer :: istat
istat = 0
if (x.eq.0) istat=1 ! Setthefinish flag
if (x.gt.0) then
print *,x
endif
return
end subroutine foo

Les

0 Kudos
h_amini
Beginner
3,779 Views
Quoting - Les Neilson

Ugly, Readability, Maintainability, ...
One way to avoid alternate return is to use a status return value :

subroutine foo(x,istat)
istat = 0
if (x .lt. 0) istat = 1
if (x .eq. 0) istat = 2
etc.
if (istat .ne. 0) return
... do something ...
end subroutine foo

For more complex variations on the values of istatin your main you would use a SELECT CASE on istat after calling foo. Or you could just use simple if statements

call foo(x,istat)
if (istat .eq. 1) go to 1
if (istat .eq. 2) go to 999
etc...

In your simplified example you could write it as

program main
integer :: istat
real :: x
istat = 0
DO WHILE (istat==0)
read *,x
call foo(x,istat)
ENDDO

subroutine foo(x, istat)
real :: x
integer :: istat
istat = 0
if (x.eq.0) istat=1 ! Setthefinish flag
if (x.gt.0) then
print *,x
endif
return
end subroutine foo

Les

Much appreciated your kind response.

Hamid

0 Kudos
Steven_L_Intel1
Employee
3,779 Views

I'll also note that alternate returns have been removed from the Fortran language standard.

0 Kudos
Reply