fortran goto scope - fortran

I have a legacy fortran code with many statements like 'goto 50'. I was wondering whether the target of goto is global or local. I mean, if multiple functions have a target '50', where does the goto leads to.
Thanks for answering.

The statement labels (eg, "50") have to be defined within the current "scoping unit", which basically translates in this context to the subroutine/function that the goto call is in (or the main program, if the call is in the main program).
So for instance, in the following program, the main program and both contained subroutines have their own label 50, and the gotos go to "their" line 50.
program testgotos
implicit none
goto 50
call second
50 call first
call second
contains
subroutine first
integer :: a = 10
goto 50
a = 20
50 print *,'First: a = ', a
end subroutine first
subroutine second
integer :: a = 20
goto 50
a = 40
50 print *,'Second: a = ', a
end subroutine second
end program testgotos

Local.
Technically from the f77 standard ( http://www.fortran.com/fortran/F77_std/f77_std.html )
"Statement labels have a scope of a program unit."

Related

How to watch global variables( from module which was used in main program) using debugger?

I am very new in using Code::Blocks 17.12 for a creating and debugging projects.
At some stage of coding i need to watch values of local and global variables because i want to avoid any wrong logic in my fortran code.
All global variables are declared in module which was included in main program by use, non_intrinsic.
When I try to watch values of mentioned global variables in the watch windows got only empty space for functions and local variables.
This is my example code:
MODULE EES_DM_PRO
IMLICIT NONE
INTEGER :: VAR_01, VAR_02
CONTAINS
SUBROUTINE DM_LOAD_VALUES()
INTEGER, PARAMETER :: UN = 15
OPEN( UN, FILE = 'DATA.TXT')
READ( UN, * ) VAR_01
READ( UN, * ) VAR_02
CLOSE( UN )
END SUBROUTINE DM_LOAD_VALUES
END MODULE
PROGRAM EES_DM_TS
USE, NON_INTRINSIC :: EES_DM_PRO
IMPLICIT NONE
CALL DM_LOAD_VALUES()
END PROGRAM
If I put a breakpoints afther line where was called subroutine and if I start debugging process in the watch window I got a empty space for locals.
Is it possible o track values of VAR_01 and VAR_02 in main program?

The use of backspace character ( char(8) ) in Fortran [duplicate]

This question already has answers here:
How do I format a PRINT or WRITE statement to overwrite the current line on the console screen?
(4 answers)
Closed 5 years ago.
For "flavorful" output during iteration procedure, I'd like to use following approach (I saw it for some program written in C++) in Fortran.
Every new iteration gives me the line in the console with corresponding information:
Iteration XX Accuracy X.XXXXE-XX Time spent XX seconds
I want every new line to replace the previous one (i.e. labels "Iteration" "Accuracy" ... etc. remain unchanged, while values change).
I tried different variants including
backspace(6)
backspace(0)
write (*,*) char(8)//'Accuracy ...'
Of course, first two lines give a runtime error and the last gives nothing.
How can I implement such an approach?
It's perhaps a bit rather complicated solution, but one option would be to use the ncurses library - http://genepi.qimr.edu.au/staff/davidD/
Below is a modification of the program testcurs.f90available for download from the linked page. It just displays a progress message which is being progressively updated. In order to test it, you will need also the ncurses.f90 module and then link with -lncurses, i.e.,
gfortran -c ncurses.f95
gfortran -o test testcurs.f95 -lncurses
The example (showing just the program itself, testcurs.f90 contains also the definition of initTest etc.):
program testcurses
use curses
use commands
type (C_PTR) :: iwin = C_NULL_PTR
integer (C_INT) :: key
integer :: istat, new_option=1, old_option=0
CHARACTER(LEN=1024) :: msg
call initTest(iwin, istat)
if (istat /= 0) then
write(*,'(a)') 'ERROR: initscr failed!'
stop
end if
ierr = wbkgd(iwin, curses_a_reverse)
ierr = erase()
ierr = attrset(curses_a_bold)
DO i = 10, 100, 10
WRITE(msg, '(''Progress '', I0, ''%'')') i
ierr = mvaddstr(20, 20, TRIM(msg) // C_NULL_CHAR)
ierr = refresh()
CALL SLEEP(1)
END DO
key = getch()
ierr = delwin(iwin)
ierr = endwin()
end program testcurses

How Declare Global variables [duplicate]

This question already has an answer here:
How to avoid declaring and setting the value of a variable in each subroutine?
(1 answer)
Closed 5 years ago.
I have a program that calls functions within the same program but I want to declare and initialize the variables on the top and access them at the end of the program.
!Declaration
INTEGER TOPCHORD,BOTCHORD, SUPPS, PURLINS;
!Initialization
! Define Layers for connecting lines
TOPCHORD = 32
BOTCHORD = 32
SUPPS = 36
PURLINS = 30
INTEGER FUNCTION IFLANGE1(IEND1,IEND2,ISUP)
IFLANGE1=TOPCHORD
SELECT CASE(IEND1)
CASE(2,4,6,8,9,10)
IFLANGE1=BOTCHORD
IF(ISUP.EQ.1)IFLANGE1=SUPPS
END SELECT
SELECT CASE(IEND2)
CASE(2,4,6,8,9,10)
IFLANGE1=BOTCHORD
IF(ISUP.EQ.1)IFLANGE1=SUPPS
END SELECT
RETURN
END
I get error that variable 'SUPPS' referenced but not set
You might want to have a look at the documentation - you're missing a couple of important statements. (Also try to always include implicit none -- this is very helpful for catching certain issues).
A slightly modified code that should compile is
!Declaration
INTEGER TOPCHORD,BOTCHORD, SUPPS, PURLINS;
!Initialization
! Define Layers for connecting lines
TOPCHORD = 32
BOTCHORD = 32
SUPPS = 36
PURLINS = 30
contains !Indicate that the program unit contains other procedures
INTEGER FUNCTION IFLANGE1(IEND1,IEND2,ISUP)
IFLANGE1=TOPCHORD
SELECT CASE(IEND1)
CASE(2,4,6,8,9,10)
IFLANGE1=BOTCHORD
IF(ISUP.EQ.1)IFLANGE1=SUPPS
END SELECT
SELECT CASE(IEND2)
CASE(2,4,6,8,9,10)
IFLANGE1=BOTCHORD
IF(ISUP.EQ.1)IFLANGE1=SUPPS
END SELECT
RETURN
END FUNCTION !End the function definition
END !This is a required end statement to say we've reached the end of the program
This isn't the nicest style etc. but has the minimum number of changes to compile.
For any slightly more complex program I would strongly recommend using modules for storing variables (and also procedures) that you want to access from different parts of the code.

Error in fortran, undefined reference to subroutine

I am writing a subroutine and main function to call it, but getting error as undefined reference to ___. I found one reason: When I save the main and subroutine in the same file, compile and run that file, everything runs perfectly. However, when I save them into different .f90 files and try to run the main file, I get error. Is there any way I can make subroutine into a separate file and call into main calling program?
I got confused with another place - in the main program at !------ERROR------ place. I referred to Automatic width integer descriptor in fortran 90 I can use I0 as automatic width display indicator. But when I used the same, there is run time error expected integer but got character. Any idea about this?
! saved as sub_program.f90 file
SUBROUTINE sub_program (v1,v2,ctr)
IMPLICIT NONE
INTEGER, INTENT(IN) :: ctr
INTEGER, INTENT (OUT) :: v1,v2
SELECT CASE (ctr)
CASE (1)
v1=1
v2=0
CASE (2)
v1=0
v2=1
END SELECT
RETURN
END SUBROUTINE
! main calling program, saved as caller.f90
PROGRAM caller
IMPLICIT NONE
INTEGER :: v1,v2,ctr
DO ctr = 1,2,1
CALL sub_program (v1,v2,ctr)
WRITE (*,100) 'STEP = ',ctr,'V1 = ',v1,'V2 = ',v2 !------ERROR------
100 FORMAT (I0)
END DO
END PROGRAM
Thanks!
What is your compile command? For me, this compiles and runs normally
gfortran caller.f90 foo.f90 && ./a.out
I0 is an integer indicator, but some items following your WRITE statement are character strings. You can try, for example,
100 FORMAT (3(A, I0, 1X))
where 1X refers to a space.
As a note, if formatting is not terribly important and you're only interested in seeing some quick results, you can use the free format output (WRITE(*,*) ...).
EDIT: I had incorrectly referred to FORMAT as obsolete.

How to execute a command on the first and only first time entering fortran subroutine?

I wrote a subroutine for a Fortran program and I want to execute a command (delete file in the program directory and open a new one) the first, and only first time, the subroutine is called. I know that I can achieve this by creating some flag outside of the subroutine, in the main program, that I set to false at program startup and then set to true upon entering the subroutine. Then I could use this flag in an if statement to figure if the commands I want to execute on the initial call should be executed or not. But this requires me modifying the existing program and I didn't want to do that if I could avoid it. Is there some other way to do what I want to do?
An example might be:
subroutine test(a)
implicit none
integer, intent(inout) :: a
logical, save :: first_time=.true.
if(first_time) then
first_time=.false.
a = a + 12345
else
a = a - 67890
end if
end subroutine test
How about using some characteristic of the output file to determine whether or not to delete it? Time stamp, file lock, a particular file extension, etc.