편의상 다음은 Ian의 VariableDefinitionContext 패키지를 컴파일하기위한 스크립트입니다. 그것은 (... gfortran-6.1 ifort-14이 부족 구문 지원으로 컴파일 할 수 없었다) -standard-semantics
와 ifort - 16.0 성공적으로
#!/usr/bin/env python
from __future__ import print_function
import os
with open("compile-order.txt", "r") as f:
tmp = f.read()
allsrc = tmp.split()
#cmd = "ifort -standard-semantics -warn -check all"
cmd = "ifort -standard-semantics"
obj = ""
for src in allsrc:
print("compiling", src)
os.system((cmd + " -c %s") % (src))
obj += src[ :-4 ]+ ".o "
os.system((cmd + " %s") % (obj))
# Usage: ./a.out test.f90
를 컴파일 ...하지만 다음과 같은 명령이 밝혀졌다 같은 일을 할 수 있어요 !! (@IanH 덕분에)
$ ifort -standard-semantics @compile-order.txt
FWIW, 여기에 인쇄 (잠재적으로) 수정 변수에 대한 또 다른 파이썬 스크립트입니다. 이 스크립트는 gfortran 덤프 파일에서 다양한 기호를 검색합니다. Ian의 패키지와는 달리 Fortran 구문의 최소 집합 만 고려됩니다 (직접 할당과 기본 읽기/쓰기 문 등).
이러한 종류의 스크립트를 사용하는 잠재적 인 방법은 잠재적으로 수정 된 COMMON 변수를 찾는 것입니다. 이전에, 나는 일반적인 블록의 톤과 기존 포트란 프로그램을 수정하는 힘든 경험을했다, 그래서
#!/usr/bin/env python
from __future__ import print_function
import os, sys
def pushuniq(coll, item):
if not (item in coll): coll.append(item)
def getvarname(s, proc):
try:
return s.split(proc + ":")[ 1 ].split("(")[ 0 ].split("%")[ 0 ]
except: # ad-hoc!
return s.split("(")[ 0 ].split("%")[ 0 ]
#------------------------------------------------------------------------
def varcheck(filename, Qwritedump=False):
"""
checks and prints potentially modified variables.
Usage: varcheck.py <filenames>
Set Qwritedump=True to write dump files.
"""
#.........................................................
# Generate gfortran dump file
cmd = "gfortran -fdump-parse-tree -c %s" # gfort >=4.7
# cmd = "gfortran -fdump-fortran-original -c %s" # gfort >=5
with os.popen(cmd % (filename)) as p:
lines = p.readlines()
base = '.'.join(filename.split('.')[:-1])
os.system("rm -f %s.{o,mod}" % (base)) # remove .o and .mod
if Qwritedump:
with open("%s.dump" % (filename), "w") as f:
f.write(''.join(lines))
#/
#.........................................................
# List of variables
varlist = {} # (potentially) modified variables
arglist = {} # dummy arguments
comlist = {} # common variables
modlist = {} # module variables
reslist = {} # result variables
sublist = {} # child subroutines
namlist = {} # namelists
#.........................................................
# Scan the dump file
Qread = False
Qgetarg = False
for line in lines:
word = line.split()
if len(word) == 0 : continue # skip blank lines
if word[ 0 ].isdigit() : word = word[ 1: ] # remove line numbers
key = word[ 0 ]
if key == "Namespace:" : continue
if key == "procedure":
proc = word[ -1 ]
varlist[ proc ] = []
arglist[ proc ] = []
comlist[ proc ] = []
modlist[ proc ] = []
reslist[ proc ] = []
namlist[ proc ] = []
sublist[ proc ] = []
continue
if key == "common:": continue
if key == "symtree:": sym = word[ 1 ].strip("'").lower()
# result variable
if (sym == proc) and (key == "result:"):
reslist[ proc ].append(word[ 1 ])
# dummy arguments
if "DUMMY" in line:
arglist[ proc ].append(sym)
# common variables
if "IN-COMMON" in line:
comlist[ proc ].append(sym)
# module variables
if ("VARIABLE" in line) and ("USE-ASSOC" in line):
modlist[ proc ].append(sym)
# child subroutines
if key == "CALL":
pushuniq(sublist[ proc ], word[ 1 ])
# namelists
if (key == "READ") and ("NML=" in line):
namlist[ proc ].append(word[ -1 ].split("NML=")[ -1 ])
# iostat
if "IOSTAT=" in line:
tmp = line.split("IOSTAT=")[ 1 ].split()[ 0 ]
sym = getvarname(tmp, proc)
pushuniq(varlist[ proc ], (sym, "iostat"))
#/
def addmemvar(op):
for v in word[ 1: ]:
if proc in v:
sym = getvarname(v, proc)
pushuniq(varlist[ proc ], (sym, op))
# allocation
if key == "ALLOCATE" : addmemvar("alloc")
if key == "DEALLOCATE" : addmemvar("dealloc")
if "move_alloc" in line : addmemvar("move_alloc")
# search for modified variables
if key == "READ" : Qread = True
if key == "DT_END" : Qread = False
if (key == "ASSIGN") or \
(Qread and (key == "TRANSFER")) or \
(key == "WRITE" and (proc in word[ 1 ])):
if key == "ASSIGN" : code = "assign"
if key == "WRITE" : code = "write"
if key == "TRANSFER" : code = "read"
sym = getvarname(word[ 1 ], proc)
pushuniq(varlist[ proc ], (sym, code))
#/
#/
all_lists = { "var": varlist, "arg": arglist, "com": comlist,
"mod": modlist, "res": reslist, "sub": sublist,
"nam": namlist }
#.........................................................
# Print results
for proc in varlist.keys():
print("-" * 60)
print(proc + ":")
for tag in [ "arg", "com", "mod", "res" ]:
if tag == "arg":
print(" " + tag + ":", arglist[ proc ])
else:
print(" " + tag + ":")
for (sym, code) in varlist[ proc ]:
if sym in all_lists[ tag ][ proc ]:
print(" %-10s (%s)" % (sym, code))
#/
#/
print(" misc:")
for (sym, code) in varlist[ proc ]:
if ":" in sym:
print(" %-10s (%s)" % (sym, code))
#/
print(" call:", sublist[ proc ])
if len(namlist[ proc ]) > 0:
print(" namelist:", namlist[ proc ])
#/
return all_lists
#/
#------------------------------------------------------------------------
if __name__ == "__main__":
if len(sys.argv) == 1:
sys.exit("Usage: varcheck.py <filenames>")
else:
filenames = sys.argv[ 1: ]
for filename in filenames:
varcheck(filename)
#/
예 1 ... 이러한 상황에 유용 할 수 있습니다 LAPACK이 zheev
$ ./varcheck.py zheev.f
------------------------------------------------------------
zheev:
arg: ['jobz', 'uplo', 'n', 'a', 'lda', 'w', 'work', 'lwork', 'rwork', 'info']
info (assign)
work (assign)
w (assign)
a (assign)
com:
mod:
res:
call: ['xerbla', 'zlascl', 'zhetrd', 'dsterf', 'zungtr', 'zsteqr', 'dscal']
예 2 : 간단한 테스트 프로그램
!--------------------------------------------------------
module myvar
character(50) :: str
type mytype
integer :: n
endtype
type(mytype) :: obj
integer :: foo
end
!--------------------------------------------------------
subroutine mysub(a, b, c, ios, n, p, q, r)
use myvar
dimension b(10)
common /com1/ dat(50), x, y, z, wtf(1000)
common /com2/ dat2(50)
integer inp, out
namelist /list/ str
namelist /list2/ p, q
inp = 10 ; out = 20
open(inp, file="test.dat", status="old", iostat=ios10)
read(inp, *, iostat=ios) a, (b(i), i=3,5)
write(out, *) "hello"
read(inp, *) c
read(inp, list)
close(inp, iostat=ios30)
write(str, "(f8.3)") a + c
do i = 1, n
dat(i) = b(i)
enddo
x = p + q
y = x * 2
100 c = dat(1) + x + y
end
!--------------------------------------------------------
subroutine mysub2(&
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, &
b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, &
c1, c2, c3, c4, c5, c6, c7, c8, c9, c10)
a3 = 3.0
b5 = 5.0
end
!--------------------------------------------------------
function myfunc(x, m)
common /com2/ dat2(50)
common /com3/ dat3(50)
100 myfunc = x + dat2(m)
200 m = 5
where(dat2 < 1.0) dat2 = 500.0
end
!--------------------------------------------------------
function myfunc2() result(res)
use myvar
implicit none
integer :: res
obj % n = 500
res = obj % n
call sub2(res)
end
!--------------------------------------------------------
subroutine myalloc(a, ier)
implicit none
integer, allocatable :: a(:), b(:)
integer ier
allocate(a(10), b(20), source=0, stat=ier)
end
!--------------------------------------------------------
subroutine mydealloc(a, b, ier)
implicit none
integer, allocatable :: a(:), b(:)
integer ier
deallocate(a, b, stat=ier)
end
!--------------------------------------------------------
subroutine mymovealloc(a, b)
implicit none
integer, allocatable :: a(:), b(:)
call move_alloc(a, b)
end
!--------------------------------------------------------
program main
use myvar
implicit none
integer a, dat
common /com/ dat
call mymain_int
print *, a, dat, foo
contains
subroutine mymain_int
integer b
a = 1
b = 2
dat = 100
foo = 200
end subroutine
end program
!--------------------------------------------------------
module mymod
use myvar
implicit none
integer bar
contains
subroutine mymod_sub
use myvar
integer a, dat
common /com/ dat
call mymod_sub_int
bar = 300
print *, a, dat, foo, bar
contains
subroutine mymod_sub_int
integer b
a = 1
b = 2
dat = 100
foo = 200
end subroutine
end subroutine
end module
결과 :
------------------------------------------------------------
mysub:
arg: ['a', 'b', 'c', 'ios', 'n', 'p', 'q', 'r']
ios (iostat)
a (read)
b (read)
c (read)
c (assign)
com:
dat (assign)
x (assign)
y (assign)
mod:
str (write)
res:
call: []
namelist: ['list']
------------------------------------------------------------
mysub2:
arg: ['a1', 'a10', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9', 'b1', 'b10', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8', 'b9', 'c1', 'c10', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9']
a3 (assign)
b5 (assign)
com:
mod:
res:
call: []
------------------------------------------------------------
myfunc:
arg: ['m', 'x']
m (assign)
com:
dat2 (assign)
mod:
res:
myfunc (assign)
call: []
------------------------------------------------------------
myfunc2:
arg: []
com:
mod:
obj (assign)
res:
res (assign)
call: ['sub2']
------------------------------------------------------------
myalloc:
arg: ['a', 'ier']
ier (alloc)
a (alloc)
com:
mod:
res:
call: []
------------------------------------------------------------
mydealloc:
arg: ['a', 'b', 'ier']
ier (dealloc)
a (dealloc)
b (dealloc)
com:
mod:
res:
call: []
------------------------------------------------------------
mymovealloc:
arg: ['a', 'b']
a (move_alloc)
b (move_alloc)
com:
mod:
res:
call: ['_gfortran_move_alloc']
------------------------------------------------------------
main:
arg: []
com:
mod:
res:
misc:
call: ['mymain_int']
------------------------------------------------------------
mymain_int:
arg: []
com:
mod:
res:
misc:
main:a (assign)
main:dat (assign)
main:foo (assign)
call: []
------------------------------------------------------------
mymod_sub:
arg: []
com:
mod:
res:
misc:
mymod:bar (assign)
call: ['mymod_sub_int']
------------------------------------------------------------
mymod_sub_int:
arg: []
com:
mod:
res:
misc:
mymod_sub:a (assign)
mymod_sub:dat (assign)
mymod_sub:foo (assign)
call: []
필자는 그러한 도구에 대해서는 잘 알지 못하지만 각각에 대해 의도 (intent (in))를 내려 놓고 컴파일러가 불평하는 곳을 볼 수 있습니까? 그렇습니다, 절대적으로 해킹 할 필요는 없지만 빠른 해킹이 필요한 경우에는 ... – francescalus
다른 소스 파일에있는 경우 많은 컴파일러가 catch하지 않을 수도 있습니다. –
F77의 변수 정의 컨텍스트 수는 최신 코드와 비교할 때 작습니다. 그렇다면 모든 코드에서 모든 정의 가능성에 관심이 있습니까, 아니면 단지 LHS 할당인지 F77인지 만 신경 쓰시겠습니까? – francescalus