10
0
mirror of https://gitlab.com/scemama/irpf90.git synced 2024-11-09 07:33:43 +01:00

Merge branch 'master' of ssh://git.code.sf.net/p/irpf90/code

* 'master' of ssh://git.code.sf.net/p/irpf90/code: (23 commits)
  IRPF90_MAKE variable
  Gitignore file added
  Error messages cleaned
  Compile external sources first
  Compile first external sources
  support for recursive subroutines in indent
  Added support of documentation of subroutines and functions
  Added irpf90_indent
  Add tags for vi navigation
  Forgot to remove debug print
  Fixed man error in make
  Corrected bug with unexisting directories
  Added auto codelet generation
  Forgot file
  Added autocompletion in irpman
  Fixed bug with Cython
  Added -I option
  Work to do
  Added man pages
  Bug with +=
  ...
This commit is contained in:
vijaygopalchilkuri 2014-04-02 22:55:59 +02:00
commit 7a4b8cb8dc
29 changed files with 709 additions and 113 deletions

View File

@ -1,10 +1,10 @@
.PHONY: all src man
all: src man
src:
$(MAKE) -C $@
man:
$(MAKE) -C $@
- $(MAKE) -C $@
all: src man

6
README
View File

@ -7,7 +7,7 @@ Dependencies
- GNU make (>= 3.81 recommended)
- Python > 2.3
- Any Fortran 90 compiler (Intel recommended, for example)
- Any Fortran 90 compiler (Intel recommended)
Installing IRPF90
-----------------
@ -19,7 +19,9 @@ ${IRPF90_HOME} is the location of your irpf90 directory::
cat << EOF >> ${HOME}/.bash_profile
export PYTHONPATH=${IRPF90_HOME}/src:${PYTHONPATH}
export PATH=${IRPF90_HOME}/bin:${PATH}
export MANPATH=${IRPF90_HOME}/man:${MANPATH}
EOF
. ${HOME}/.bash_profile
Using IRPF90
@ -42,6 +44,6 @@ Author
------
| Anthony Scemama, LCPQ-IRSAMC, CNRS-Universite Paul Sabatier
| scemama@irsamc.ups-tlse.fr
| <scemama@irsamc.ups-tlse.fr>
| http://scemama.mooo.com

View File

@ -1 +1 @@
../src/irpf90.exe
../src/irpf90_python.exe

40
bin/irpf90_indent Executable file
View File

@ -0,0 +1,40 @@
#!/usr/bin/python
# IRPF90 is a Fortran90 preprocessor written in Python for programming using
# the Implicit Reference to Parameters (IRP) method.
# Copyright (C) 2009 Anthony SCEMAMA
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Anthony Scemama
# LCPQ - IRSAMC - CNRS
# Universite Paul Sabatier
# 118, route de Narbonne
# 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr
import os
import sys
wd = os.path.abspath(os.path.dirname(__file__))
sys.path.insert(0,(wd+"/../src/"))
sys.path.insert(0,(wd+"/../share/irpf90/src/"))
def main():
import irpf90_indent
irpf90_indent.main()
main()

View File

@ -1,4 +1,4 @@
#!/usr/bin/python
#!/bin/bash
# IRPF90 is a Fortran90 preprocessor written in Python for programming using
# the Implicit Reference to Parameters (IRP) method.
# Copyright (C) 2009 Anthony SCEMAMA
@ -24,19 +24,25 @@
# 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr
# Define auto-completion for bash
import os
import sys
wd = os.path.abspath(os.path.dirname(__file__))
sys.path.insert(0,(wd+"/../src/"))
sys.path.insert(0,(wd+"/../share/irpf90/src/"))
if len(sys.argv) != 2:
print "Usage:"
print sys.argv[0]+" <irp_variable>"
sys.exit(1)
from irpf90_t import mandir
os.system("man ./"+mandir+sys.argv[1].lower()+".l")
case "$0" in
*bash*)
_irpman_complete()
{
local cur
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=( $(compgen -W "`cat tags | cut -d' ' -f 1`" -- "$cur" ) )
} && complete -F _irpman_complete irpman
;;
*)
if [[ -z $1 ]] ; then
echo "To activate auto-completion in bash:"
echo "source " $0
else
python $(dirname $0)/../src/irpman.py $1
fi
;;
esac

View File

@ -1,4 +1,4 @@
IRPF90 = ~/irpf90/bin/irpf90 -a -d
IRPF90 = python ../src/irpf90.py -I input -a -d
FC = gfortran
FCFLAGS= -O2

View File

@ -20,6 +20,7 @@ BEGIN_PROVIDER [ integer, u2 ]
integer :: fu
! u2 = fu(d3,d4)
u2 = d3+d4+1
ASSERT (u2 > d3)
END_PROVIDER
integer function fu(x,y)

Binary file not shown.

View File

@ -1,5 +1,5 @@
include version
default:
default: version
set -x
NAME=irpf90-$(VERSION)-noarch-src.tar.gz ;\
cd ..;\

View File

@ -1,13 +1,10 @@
PYTHON=python
PYVERSION=$(shell $(PYTHON) -c "import sys; print(sys.version[:3])")
HAS_CYTHON=$(shell which cython &> /dev/null && echo 1 || echo 0)
HAS_CYTHON=$(shell bash -c "which cython &> /dev/null && echo 1 || echo 0")
ifneq ($(HAS_CYTHON),0)
../bin/irpf90: irpf90.exe
rm ../bin/irpf90 ; cd ../bin ; ln -s ../src/irpf90.exe irpf90
irpf90.exe: irpf90.so
gcc build/*/irpf90.o -L/usr/lib64 -lpython$(PYVERSION) -o irpf90.exe
../bin/irpf90: irpf90.so
rm ../bin/irpf90 ; cd ../bin ; ln -s ../src/irpf90_python.exe irpf90
irpf90.so : $(wildcard *.py) irpf90.c
./cython_setup.py build_ext --inplace

45
src/codelet.py Normal file
View File

@ -0,0 +1,45 @@
#!/usr/bin/python
from command_line import command_line
import irpf90_t
def run():
template = """
program codelet_%(name)s
implicit none
integer :: i
double precision :: ticks_0, ticks_1, cpu_0, cpu_1
integer, parameter :: irp_imax = %(NMAX)d
%(precondition)s
call provide_%(name)s
double precision :: irp_rdtsc
call cpu_time(cpu_0)
ticks_0 = irp_rdtsc()
do i=1,irp_imax
call bld_%(name)s
enddo
ticks_1 = irp_rdtsc()
call cpu_time(cpu_1)
print *, '%(name)s'
print *, '-----------'
print *, 'Cycles:'
print *, (ticks_1-ticks_0)/dble(irp_imax)
print *, 'Seconds:'
print *, (cpu_1-cpu_0)/dble(irp_imax)
end
"""
name, NMAX, precondition, filename = command_line.codelet
if precondition is None:
precondition = ""
else:
precondition = "PROVIDE "+precondition
file = open(filename,'w')
file.write(template%locals())
file.close()

View File

@ -48,9 +48,12 @@ options['s'] = [ 'substitute' , 'Substitute values in do loops for generating
options['r'] = [ 'no_directives', 'Ignore all compiler directives !DEC$ and !DIR$', 0 ]
options['n'] = [ 'inline' , 'all|providers|builders : Force inlining of providers or builders', 1 ]
options['u'] = [ 'unused' , 'Print unused providers', 0 ]
options['I'] = [ 'include' , 'Include directory', 1 ]
options['c'] = [ 'codelet' , 'entity:NMAX or entity:precondition:NMAX : Generate a codelet to profile a provider running NMAX times', 1 ]
class CommandLine(object):
do_openmp = False
def __init__(self):
global options
self._opts = None
@ -66,6 +69,19 @@ class CommandLine(object):
return self._defined
defined = property(fget=defined)
def include_dir(self):
if '_include_dir' not in self.__dict__:
self._include_dir = []
for o,a in self.opts:
if o in [ "-I", '--'+options['I'][0] ]:
if len(a) < 1:
print "Error: -I option needs a directory"
if a[-1] != '/':
a = a+'/'
self._include_dir.append(a)
return self._include_dir
include_dir = property(fget=include_dir)
def inline(self):
if '_inline' not in self.__dict__:
self._inline = ""
@ -87,6 +103,28 @@ class CommandLine(object):
return self._substituted
substituted = property(fget=substituted)
def codelet(self):
if '_codelet' not in self.__dict__:
self._codelet = []
for o,a in self.opts:
if o in [ "-c", '--'+options['c'][0] ]:
buffer = a.split(':')
filename = 'codelet_'+buffer[0]+'.irp.f'
if len(buffer) == 2:
self._codelet = [buffer[0], int(buffer[1]), None, filename]
elif len(buffer) == 3:
self._codelet = [buffer[0], int(buffer[2]), buffer[1], filename]
else:
print """
Error in codelet definition. Use:
--codelet=provider:NMAX
or
--codelet=provider:precondition:NMAX
"""
sys.exit(1)
return self._codelet
codelet = property(fget=codelet)
def preprocessed(self):
if '_preprocessed' not in self.__dict__:
self._preprocessed = []

View File

@ -27,6 +27,8 @@
from variable import Variable
from variables import variables
from subroutine import Sub
from subroutines import subroutines
from irpf90_t import *
from util import *
@ -93,6 +95,46 @@ def do_print(var):
process_deps(file,var.needed_by)
file.close()
######################################################################
def process_declaration_subroutine(file, sub):
print >>file, sub.line.text.split('!')[0].strip()
# for line in sub.text:
######################################################################
def do_print_subroutines(sub):
assert type(sub) == Sub
filename = sub.line.filename
name = sub.name
file = open("%s%s.l"%(mandir,sub.name), "w")
print >>file, '.TH "IRPF90 entities" l %s "IRPF90 entities" %s'%(name,name)
print >>file, ".SH Declaration"
print >>file, ".nf"
process_declaration_subroutine(file,sub)
print >>file, ".ni"
if sub.doc != []:
print >>file, ".SH Description"
for l in sub.doc:
process_doc(file,l)
print >>file, ".SH File\n.P"
print >>file, filename
if sub.needs != []:
sub.needs.sort()
print >>file, ".SH Needs"
process_deps(file,sub.needs)
if sub.called_by != []:
sub.called_by.sort()
print >>file, ".SH Called by"
process_deps(file,sub.called_by)
if sub.calls != []:
sub.calls.sort()
print >>file, ".SH Calls"
process_deps(file,sub.calls)
if sub.touches != []:
sub.touches.sort()
print >>file, ".SH Touches"
process_deps(file,sub.touches)
file.close()
######################################################################
def run():
import parsed_text
@ -100,14 +142,28 @@ def run():
if os.fork() == 0:
for v in variables.values():
do_print(v)
for s in subroutines.values():
do_print_subroutines(s)
sys.exit(0)
if os.fork() == 0:
tags = []
l = variables.keys()
file = open("irpf90_entities","w")
l.sort()
for v in l:
do_print_short(file,variables[v])
line = variables[v].line
tags.append( '%s\t%s\t/%s/;"\n'%(v,line.filename[0],line.text.split('!')[0].strip()) )
file.close()
l = subroutines.keys()
for v in l:
line = subroutines[v].line
tags.append('%s\t%s\t/%s/;"\n'%(v,line.filename,line.text.split('!')[0].strip()))
tags.sort()
file = open("tags","w")
for line in tags:
file.write(line)
file.close()
sys.exit(0)

View File

@ -30,6 +30,7 @@ import os
import util
import makefile
import irpf90_t
from command_line import command_line
initialized = False
@ -49,23 +50,36 @@ def init():
except OSError:
os.mkdir(dir)
for dir in command_line.include_dir:
dir = irpf90_t.irpdir+dir
try:
wd = os.getcwd()
os.chdir(dir)
os.chdir(wd)
except OSError:
os.mkdir(dir)
# Create makefile
makefile.create()
# Copy current files in the irpdir
for filename in os.listdir(os.getcwd()):
if not filename[0].startswith(".") and not os.path.isdir(filename):
for dir in ['./']+command_line.include_dir:
try:
os.stat(dir)
except:
print dir,'not in dir'
continue
for filename in os.listdir(dir):
filename = dir+filename
if not filename.startswith(".") and not os.path.isdir(filename):
try:
file = open(filename,"r")
except IOError:
print "Warning : Unable to read file %s."%(filename)
else:
buffer = file.readlines()
file.close()
if not util.same_file(irpf90_t.irpdir+filename,buffer):
file = open(filename,"r")
buffer = file.read()
file.close()
if not util.same_file(irpf90_t.irpdir+filename,buffer):
file = open(irpf90_t.irpdir+filename,"w")
file.write(buffer)
file.close()

View File

@ -35,9 +35,10 @@ except:
pass
sys.setcheckinterval(1000)
def main():
from command_line import command_line
def main():
vim.install()
if command_line.do_help:
@ -72,10 +73,15 @@ def main():
for x in parents:
print "- %s"%(x,)
if command_line.do_codelet:
import profile
profile.build_rdtsc()
import codelet
codelet.run()
if not command_line.do_run:
return
init()
import irp_stack
@ -102,3 +108,4 @@ def main():
if __name__ == '__main__':
main()

247
src/irpf90_indent.py Executable file
View File

@ -0,0 +1,247 @@
#!/usr/bin/python
import sys
import re
LENMAX = 70
tabn = 2
tab = " "*tabn
class Grep(object):
re_begin_program = re.compile(r"^\s*program\s",flags=re.I)
def begin_program(self,string):
return re.match(self.re_begin_program,string) is not None
re_end_program = re.compile(r"\s*(end\s*!?$|end\s*program)",flags=re.I)
def end_program(self,string):
return re.match(self.re_end_program,string) is not None
re_begin_subroutine = re.compile(r"^\s*(recursive)?\s*subroutine\s",flags=re.I)
def begin_subroutine(self,string):
return re.match(self.re_begin_subroutine,string) is not None
re_end_subroutine = re.compile(r"\s*(end\s*!?$|end\s*subroutine)",flags=re.I)
def end_subroutine(self,string):
return re.match(self.re_end_subroutine,string) is not None
re_begin_function = re.compile(r"^.*function\s+.*\(",flags=re.I)
def begin_function(self,string):
return re.match(self.re_begin_function,string) is not None
re_end_function = re.compile(r"\s*(end\s*!?$|end\s*function)",flags=re.I)
def end_function(self,string):
return re.match(self.re_end_function,string) is not None
re_begin_provider = re.compile(r"^\s*&?begin_provider\s",flags=re.I)
def begin_provider(self,string):
return re.match(self.re_begin_provider,string) is not None
re_end_provider = re.compile(r"^\s*end_provider\s*(!.*)?$", flags=re.I)
def end_provider(self,string):
return re.match(self.re_end_provider,string) is not None
re_begin_do = re.compile(r"^\s*do\s+",flags=re.I)
def begin_do(self,string):
return re.match(self.re_begin_do,string) is not None
re_end_do = re.compile(r"^\s*end\s*do\s*(!.*)?$",flags=re.I)
def end_do(self,string):
return re.match(self.re_end_do,string) is not None
re_begin_if = re.compile(r"^\s*if(\(|\s+).*(&|then)\s*(!.*)?$",flags=re.I)
def begin_if(self,string):
return re.match(self.re_begin_if,string) is not None
re_else = re.compile(r"^\s*else",flags=re.I)
def xelse(self,string):
return re.match(self.re_else,string) is not None
re_end_if = re.compile(r"^\s*end\s*if\s*(!.*)?$",flags=re.I)
def end_if(self,string):
return re.match(self.re_end_if,string) is not None
re_begin_select = re.compile(r"^\s*select\s*case",flags=re.I)
def begin_select(self,string):
return re.match(self.re_begin_select,string) is not None
re_case = re.compile(r"^\s*case\s*\(",flags=re.I)
def case(self,string):
return re.match(self.re_case,string) is not None
re_end_select = re.compile(r"^\s*end\s*select\s*(!.*)?$",flags=re.I)
def end_select(self,string):
return re.match(self.re_end_select,string) is not None
re_continuation = re.compile(r"^\s*\S+.*&")
def continuation(self,string):
return re.match(self.re_continuation,string) is not None
re_declaration = re.compile(r"^.*::.*$")
def declaration(self,string):
return re.match(self.re_declaration,string) is not None
grep = Grep()
class indent(object):
def __init__(self):
"""Run the program"""
self.run()
def format_declaration(self,string,n):
l,r = string.split('::')
return l.strip().ljust(n) + ' :: '+ r.strip()
def format_continuation(self,string,n):
buffer = string.split('&')
if len(buffer) == 1:
l = buffer[0]
return l
else:
l, r = buffer
return l.strip().ljust(69-len(n)) + '&'+ r.strip()
def get_filename(self):
"""The file name is the first argument"""
if '_filename' not in self.__dict__:
try:
self._filename = sys.argv[1]
except:
self._filename = None
return self._filename
filename=property(fget=get_filename)
def get_text(self):
"""The text of the file is a list of lines"""
if '_text' not in self.__dict__:
if self.filename is not None:
f = open(self.filename,'r')
self._text = f.read().splitlines()
f.close()
else:
self._text = sys.stdin.read().splitlines()
return self._text
text=property(fget=get_text)
def indentlevel(self,line):
line = line.rstrip()
k=0
if len(line) > 0:
while line[k] == ' ':
k+=1
return k
def run(self):
lines = self.text
indent0 = " "*self.indentlevel(self.text[0])
k = indent0
line = ""
for i in range(len(self.text)):
prevline = line
line = self.text[i].strip()
if grep.continuation(line):
line = self.format_continuation(line,k)
if grep.continuation(prevline):
print k+2*tab+self.format_continuation(line,k+2*tab)
continue
if grep.begin_subroutine(line):
print line
k = indent0+tab
continue
if grep.begin_function(line):
print line
k = indent0+tab
continue
if grep.begin_program(line):
print line
k = indent0+tab
continue
if grep.begin_provider(line):
if line[0] != '&':
k = indent0+tab
if grep.begin_provider(self.text[i+1].strip()):
print " "+line
else:
print line
else:
print line
continue
if grep.declaration(line):
print k+self.format_declaration(line,30)
continue
if grep.begin_do(line):
print k+line
k += tab
continue
if grep.begin_if(line):
print k+line
k += tab
continue
if grep.xelse(line):
print k[:-tabn]+line
continue
if grep.begin_select(line):
print k+line
k += 2*tab
continue
if grep.case(line):
print k[:-tabn]+line
continue
if grep.end_do(line):
k = k[:-tabn]
print k+line
continue
if grep.end_if(line):
k = k[:-tabn]
print k+line
continue
if grep.end_select(line):
k = k[:-2*tabn]
print k+line
continue
if grep.end_subroutine(line):
print line
k = indent0
continue
if grep.end_function(line):
print line
k = indent0
continue
if grep.end_provider(line):
print line
k = indent0
continue
if grep.end_program(line):
print line
k = indent0
continue
print k+line
def main():
indent()
if __name__ == '__main__':
main()

View File

@ -54,211 +54,245 @@ class Line(object):
lower = property(fget=get_lower)
class Empty_line(Line):
str="Empty_line"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Empty_line",self.i,self.text)
class Simple_line(Line):
str="Simple_line"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Simple_line",self.i,self.text)
class Declaration(Line):
str="Declaration"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Declaration",self.i,self.text)
class Continue(Line):
str="Continue"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Continue",self.i,self.text)
class Begin_provider(Line):
str = "Provider"
str="Begin_provider"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Begin_provider",self.i,self.text)
class Cont_provider(Line):
str="Cont_provider"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Cont_provider",self.i,self.text)
class End_provider(Line):
str="End_provider"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("End_provider",self.i,self.text)
class Begin_doc(Line):
str="Begin_doc"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Begin_doc",self.i,self.text)
class Doc(Line):
str="Doc"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Doc",self.i,self.text)
class End_doc(Line):
str="End_doc"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("End_doc",self.i,self.text)
class Begin_shell(Line):
str="Begin_shell"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Begin_shell",self.i,self.text)
class End_shell(Line):
str="End_shell"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("End_shell",self.i,self.text)
class Begin_template(Line):
str="Begin_template"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Begin_template",self.i,self.text)
class End_template(Line):
str="End_template"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("End_template",self.i,self.text)
class Subst(Line):
str="Subst"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Subst",self.i,self.text)
class Assert(Line):
str="Assert"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Assert",self.i,self.text)
class Touch(Line):
str="Touch"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Touch",self.i,self.text)
class SoftTouch(Touch):
str="SoftTouch"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("SoftTouch",self.i,self.text)
class Irp_read(Line):
str="Irp_read"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Irp_read",self.i,self.text)
class Irp_write(Line):
str="Irp_write"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Irp_write",self.i,self.text)
class Irp_If(Line):
str="Irp_If"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Irp_If",self.i,self.text)
class Irp_Else(Line):
str="Irp_Else"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Irp_Else",self.i,self.text)
class Irp_Endif(Line):
str="Irp_Endif"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Irp_Endif",self.i,self.text)
class Openmp(Line):
str="Openmp"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Openmp",self.i,self.text)
class Directive(Line):
str="Directive"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Directive",self.i,self.text)
class Use(Line):
str="Use"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Use",self.i,self.text)
class Do(Line):
str="Do"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Do",self.i,self.text)
class Enddo (Line):
str="Enddo"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Enddo",self.i,self.text)
class If(Line):
str="If"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("If",self.i,self.text)
class Elseif(Line):
str="Elseif"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Elseif",self.i,self.text)
class Else(Line):
str="Else"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Else",self.i,self.text)
class Endif(Line):
str="Endif"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Endif",self.i,self.text)
class Select(Line):
str="Select"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Select",self.i,self.text)
class Case(Line):
str="Case"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Case",self.i,self.text)
class End_select(Line):
str="End_select"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
@ -286,54 +320,63 @@ class Function(Line):
return "%20s:%5d : %s"%("Function",self.i,self.text)
class Call(Line):
str="Call"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Call",self.i,self.text)
class Provide(Line):
str="Provide"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Provide",self.i,self.text)
class NoDep(Line):
str="NoDep"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("NoDep",self.i,self.text)
class Return (Line):
str="Return"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Return",self.i,self.text)
class Include(Line):
str="Include"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Include",self.i,self.text)
class Implicit (Line):
str="Implicit"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Implicit",self.i,self.text)
class Free(Line):
str="Free"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("Free",self.i,self.text)
class End(Line):
str="End"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
return "%20s:%5d : %s"%("End",self.i,self.text)
class Provide_all (Line):
str="Provide_all"
def __init__(self,i,text,filename):
Line.__init__(self,i,text,filename)
def __repr__(self):
@ -349,6 +392,14 @@ def create_irpf90_files():
def is_irpf90_file(filename):
return filename.endswith(".irp.f") and not filename.startswith('.')
result = filter ( is_irpf90_file, os.listdir(os.getcwd()) )
for dir in command_line.include_dir:
try:
os.stat(dir)
result += map(lambda x: dir+x, filter ( is_irpf90_file, os.listdir(dir) ) )
except:
continue
if command_line.do_codelet:
result += [command_line.codelet[3]]
return result
irpf90_files = create_irpf90_files()

39
src/irpman.py Executable file
View File

@ -0,0 +1,39 @@
#!/usr/bin/python
# IRPF90 is a Fortran90 preprocessor written in Python for programming using
# the Implicit Reference to Parameters (IRP) method.
# Copyright (C) 2009 Anthony SCEMAMA
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Anthony Scemama
# LCPQ - IRSAMC - CNRS
# Universite Paul Sabatier
# 118, route de Narbonne
# 31062 Toulouse Cedex 4
# scemama@irsamc.ups-tlse.fr
import os
import sys
wd = os.path.abspath(os.path.dirname(__file__))
from irpf90_t import mandir
filename = sys.argv[1].lower()+".l"
if filename not in os.listdir(mandir):
print "%s does not exist"%(sys.argv[1])
sys.exit(-1)
os.system("man ./"+mandir+sys.argv[1].lower()+".l")

View File

@ -32,6 +32,8 @@ irpdir = irpf90_t.irpdir
mandir = irpf90_t.mandir
FILENAME = "Makefile"
FILENAME_GITIGNORE = ".gitignore"
IRPF90_MAKE = "irpf90.make"
######################################################################
def create():
@ -51,45 +53,65 @@ SRC=
OBJ=
LIB=
include irpf90.make
include %s
irpf90.make: $(wildcard *.irp.f)
%s: $(filter-out %s%%, $(wildcard */*.irp.f)) $(wildcard *.irp.f) $(wildcard *.inc.f) Makefile
\t$(IRPF90)
"""
"""%(IRPF90_MAKE,IRPF90_MAKE,irpdir)
file.write(t)
file.close()
create_gitignore()
######################################################################
def create_gitignore():
has_makefile = True
try:
file = open(FILENAME_GITIGNORE,"r")
except IOError:
has_makefile = False
if has_makefile:
return
file = open(FILENAME_GITIGNORE,"w")
t = "\n".join([ irpdir, mandir, IRPF90_MAKE, 'irpf90_entities', 'tags' ])
file.write(t)
file.close()
######################################################################
def run():
from modules import modules
if os.fork() == 0:
mod = []
for m in modules.values():
mod.append(m)
file = open('irpf90.make','w')
result = "SRC += %sirp_stack.irp.F90"%(irpdir)
file = open(IRPF90_MAKE,'w')
result = ""
result += "FC+=-I %s "%(irpdir)
for i in command_line.include_dir:
result += "-I %s%s "%(irpdir,i)
result += "\n"
result += "SRC += %sirp_stack.irp.F90"%(irpdir)
result += " %sirp_touches.irp.F90"%(irpdir)
if command_line.do_openmp:
result += " %sirp_locks.irp.F90"%(irpdir)
if command_line.do_profile:
result += " %sirp_profile.irp.F90"%(irpdir)
for m in mod:
result += " %s%s.irp.F90"%(irpdir,m.name[:-4])
result += " %s%s.irp.module.F90"%(irpdir,m.name[:-4])
result += " %s%s.irp.F90"%(irpdir,m.filename)
result += " %s%s.irp.module.F90"%(irpdir,m.filename)
print >>file, result
result = "OBJ += %sirp_stack.irp.o"%(irpdir)
result = "OBJ_IRP = "
for m in mod:
if not m.is_main:
result += " %s%s.irp.o"%(irpdir,m.name[:-4])
result += " %s%s.irp.module.o"%(irpdir,m.name[:-4])
result += " %s%s.irp.o"%(irpdir,m.filename)
result += " %s%s.irp.module.o"%(irpdir,m.filename)
print >>file, result
print >>file, "OBJ1 = $(patsubst %%, %s%%,$(notdir $(OBJ))) %sirp_touches.irp.o"%(irpdir,irpdir),
print >>file, "OBJ1 = $(OBJ_IRP) $(OBJ) %sirp_touches.irp.o"%(irpdir),
if command_line.do_profile:
print >>file, " %sirp_profile.irp.o"%(irpdir), " irp_rdtsc.o",
if command_line.do_codelet:
print >>file, " irp_rdtsc.o",
if command_line.do_openmp:
print >>file, " %sirp_locks.irp.o"%(irpdir),
else:
@ -106,14 +128,14 @@ def run():
print >>file, "ifdef USE_IRPF90_A"
for m in mod:
if m.is_main:
exe = m.name[:-4]
exe = m.filename
print >>file, "%s: %s%s.irp.o %s%s.irp.module.o irpf90.a"%(exe,irpdir,exe,irpdir,exe)
print >>file, "\t$(FC) -o $@ %s$@.irp.o %s$@.irp.module.o irpf90.a $(LIB)"%(irpdir,irpdir)
print >>file, "\t@$(MAKE) -s move"
print >>file, "else"
for m in mod:
if m.is_main:
exe = m.name[:-4]
exe = m.filename
print >>file, "%s: %s%s.irp.o %s%s.irp.module.o $(OBJ1)"%(exe,irpdir,exe,irpdir,exe)
print >>file, "\t$(FC) -o $@ %s$@.irp.o %s$@.irp.module.o $(OBJ1) $(LIB)"%(irpdir,irpdir)
print >>file, "\t@$(MAKE) -s move"
@ -121,14 +143,16 @@ def run():
buffer = ""
for m in mod:
filename = "%s%s.irp.o: %s%s.irp.module.o"%(irpdir,m.name[:-4],irpdir,m.name[:-4])
mds = map (lambda x: " %s%s.irp.module.o"%(irpdir,x[:-4]),m.needed_modules)
filename = "%s%s.irp.o: $(OBJ) %s%s.irp.module.o"%(irpdir,m.filename,irpdir,m.filename)
needed_modules = filter( lambda x: modules[x].name in m.needed_modules, modules )
needed_files = map(lambda x: modules[x].filename, needed_modules)
mds = map (lambda x: " %s%s.irp.module.o"%(irpdir,x),needed_files)
print >>file, filename," ".join(mds)," ".join(m.includes)
if not m.is_main:
buffer += "\t - @echo '"+filename+" ".join(mds)+"' >> %sdist_Makefile\n"%(irpdir)
print >>file, "%sirp_touches.irp.o:"%(irpdir),
print >>file, "%sirp_touches.irp.o: $(OBJ) "%(irpdir),
mds = filter(lambda x: not x.is_main,mod)
mds = map(lambda x: " %s%s.irp.o %s%s.irp.o"%(irpdir,x.name[:-4],irpdir,x.name[:-4]),mds)
mds = map(lambda x: " %s%s.irp.o %s%s.irp.o"%(irpdir,x.filename,irpdir,x.filename),mds)
print >>file," ".join(mds)
if command_line.do_profile:
print >>file, "%sirp_profile.irp.o:"%(irpdir),
@ -143,14 +167,14 @@ def run():
# print >>file, "\t- @echo FCFLAGS=$(FCFLAGS) >> %sdist_Makefile"%(irpdir)
# print >>file, "\t- @echo LIB=$(LIB) >> %sdist_Makefile"%(irpdir)
# print >>file, "\t- @echo .DEFAULT_GOAL: exe >> %sdist_Makefile"%(irpdir)
# print >>file, "\t- @echo 'exe: $$(EXE).irp.F90 $(OBJ) irp_touches.irp.o' >> %sdist_Makefile"%(irpdir)
# print >>file, "\t- @echo '\t$$(FC) -o $$(EXE) $$(EXE).irp.F90 $(OBJ) irp_touches.irp.o $$(LIB)' >> %sdist_Makefile"%(irpdir)
# print >>file, "\t- @echo 'exe: $$(EXE).irp.F90 $(OBJ_IRP) $(OBJ) irp_touches.irp.o' >> %sdist_Makefile"%(irpdir)
# print >>file, "\t- @echo '\t$$(FC) -o $$(EXE) $$(EXE).irp.F90 $(OBJ_IRP) $(OBJ) irp_touches.irp.o $$(LIB)' >> %sdist_Makefile"%(irpdir)
# print >>file, "\t- @echo '%%.o: %%.F90' >> %sdist_Makefile"%(irpdir)
# print >>file, "\t- @echo '\t$$(FC) $$(FCFLAGS) -c $$*.F90 -o $$*.o' >> %sdist_Makefile"%(irpdir)
# print >>file, "\t- @echo 'clean:' >> %sdist_Makefile"%(irpdir)
# print >>file, "\t- @echo '\trm *.o *.mod $$(EXE) 2>/dev/null' >> %sdist_Makefile"%(irpdir)
# print >>file, buffer
# print >>file, "\t- @echo '\tirp_touches.irp.o: irp_touches.irp.F90 $(OBJ) >> %sdist_Makefile"%(irpdir)
# print >>file, "\t- @echo '\tirp_touches.irp.o: irp_touches.irp.F90 $(OBJ_IRP) $(OBJ) >> %sdist_Makefile"%(irpdir)
# print >>file, "%%.dist: %sdist_Makefile"%(irpdir)
# print >>file, "\t- @mkdir -p dist/$*| DO_NOTHING="
@ -165,23 +189,23 @@ def run():
# print >>file, "\t- @cp %s$*.irp.F90 dist/$*/| DO_NOTHING="%(irpdir)
# print >>file, "\t- cd dist ; tar -zcvf ../$*.tar.gz $*\n"
print >>file, irpdir+"%.irp.module.o: "+irpdir+"%.irp.module.F90"
print >>file, "\t$(FC) $(FCFLAGS) -c "+irpdir+"$*.irp.module.F90 -o "+irpdir+"$*.irp.module.o"
print >>file, irpdir+"%.irp.o: "+irpdir+"%.irp.module.o "+irpdir+"%.irp.F90"
print >>file, "\t$(FC) $(FCFLAGS) -c "+irpdir+"$*.irp.F90 -o "+irpdir+"$*.irp.o"
print >>file, irpdir+"%.irp.o: "+irpdir+"%.irp.F90"
print >>file, "\t$(FC) $(FCFLAGS) -c "+irpdir+"$*.irp.F90 -o "+irpdir+"$*.irp.o"
print >>file, irpdir+"%.o: %.F90"
print >>file, "\t$(FC) $(FCFLAGS) -c $*.F90 -o "+irpdir+"$*.o"
print >>file, irpdir+"%.o: %.f90\n\t$(FC) $(FCFLAGS) -c $*.f90 -o "+irpdir+"$*.o"
print >>file, irpdir+"%.o: %.f\n\t$(FC) $(FCFLAGS) -c $*.f -o "+irpdir+"$*.o"
print >>file, irpdir+"%.o: %.F\n\t$(FC) $(FCFLAGS) -c $*.F -o "+irpdir+"$*.o"
print >>file, irpdir+"%.irp.F90: irpf90.make\n"
for dir in [ irpdir ] + map(lambda x: irpdir+x, command_line.include_dir):
print >>file, dir+"%.irp.module.o: $(OBJ) "+dir+"%.irp.module.F90"
print >>file, "\t$(FC) $(FCFLAGS) -c "+dir+"$*.irp.module.F90 -o "+dir+"$*.irp.module.o"
print >>file, dir+"%.irp.o: $(OBJ) "+dir+"%.irp.module.o "+dir+"%.irp.F90"
print >>file, "\t$(FC) $(FCFLAGS) -c "+dir+"$*.irp.F90 -o "+dir+"$*.irp.o"
print >>file, dir+"%.irp.o: $(OBJ) "+dir+"%.irp.F90"
print >>file, "\t$(FC) $(FCFLAGS) -c "+dir+"$*.irp.F90 -o "+dir+"$*.irp.o"
print >>file, dir+"%.o: %.F90"
print >>file, "\t$(FC) $(FCFLAGS) -c $*.F90 -o "+dir+"$*.o"
print >>file, dir+"%.o: %.f90\n\t$(FC) $(FCFLAGS) -c $*.f90 -o "+dir+"$*.o"
print >>file, dir+"%.o: %.f\n\t$(FC) $(FCFLAGS) -c $*.f -o "+dir+"$*.o"
print >>file, dir+"%.o: %.F\n\t$(FC) $(FCFLAGS) -c $*.F -o "+dir+"$*.o"
print >>file, dir+"%.irp.F90: "+IRPF90_MAKE+"\n"
print >>file, "move:\n\t@mv -f *.mod IRPF90_temp/ 2> /dev/null | DO_NOTHING=\n"
print >>file, "irpf90.a: $(OBJ1)\n\t$(AR) crf irpf90.a $(OBJ1)\n"
print >>file, "irpf90.a: $(OBJ) $(OBJ1)\n\t$(AR) crf irpf90.a $(OBJ1)\n"
print >>file, "clean:\n\trm -rf $(EXE) $(OBJ1) irpf90.a $(ALL_OBJ1) $(ALL)\n"
print >>file, "veryclean:\n\t- $(MAKE) clean\n"
print >>file, "\t- rm -rf "+irpdir+" "+mandir+" irpf90.make irpf90_variables dist\n"
print >>file, "\t- rm -rf "+irpdir+" "+mandir+" "+IRPF90_MAKE+" irpf90_entities dist\n"
file.close()
sys.exit(0)

View File

@ -46,7 +46,8 @@ class Fmodule(object):
def __init__(self,text,filename):
self.text = put_info(text,filename)
self.name = "%s_mod"%(filename[:-6])
self.filename = filename[:-6]
self.name = "%s_mod"%(self.filename).replace('/','__').replace('.','Dot')
def is_main(self):
if '_is_main' not in self.__dict__:

View File

@ -42,7 +42,7 @@ modules = create_modules()
######################################################################
def write_module(m):
# Module data
filename = irpdir+m.name[0:-4]+".irp.module.F90"
filename = irpdir+m.filename+".irp.module.F90"
text = m.header + m.head
text = map(lambda x: "%s\n"%(x),text)
if not same_file(filename,text):
@ -52,7 +52,7 @@ def write_module(m):
file.close()
# Subroutines
filename = irpdir+m.name[0:-4]+".irp.F90"
filename = irpdir+m.filename+".irp.F90"
text = m.header + m.generated_text + m.residual_text
text = map(lambda x: "%s\n"%(x),text)
if not same_file(filename,text):

View File

@ -355,23 +355,14 @@ def add_operators(text):
for line in text:
buffer = line.text
if "+=" in buffer:
if "if" in buffer:
if buffer.lstrip().startswith("if "):
re_incr = re.compile(r"(.*)(\))(\s*)(.*)(\+=)(.*$)",re.S)
line.text = re.sub(re_incr,r'\1\2\4=\4+(\6)', buffer)
else:
line.text = re.sub(re_incr,r'\1\2=\2+(\4)', buffer)
elif "-=" in buffer:
if "if" in buffer:
re_decr = re.compile(r"(.*)(\))(\s*)(.*)(\-=)(.*$)",re.S)
line.text = re.sub(re_decr,r'\1\2\4=\4-(\6)', buffer)
else:
line.text = re.sub(re_decr,r'\1\2=\2-(\4)', buffer)
# line.text = re.sub(re_decr,r'\1\2=\2-(\4)', buffer)
elif "*=" in buffer:
if "if" in buffer:
re_mult = re.compile(r"(.*)(\))(\s*)(.*)(\*=)(.*$)",re.S)
line.text = re.sub(re_mult,r'\1\2\4=\4*(\6)', buffer)
else:
line.text = re.sub(re_mult,r'\1\2=\2*(\4)', buffer)
result.append(line)
return result
@ -673,7 +664,11 @@ def change_includes(text):
if len(txt) != 3:
print txt
error.fail(line,"Error in include statement")
directory = (("./"+line.filename).rsplit('/',1)[0]+'/')[2:]
if directory == "":
filename = txt[1].strip()
else:
filename = directory+txt[1].strip()
try:
file = open(filename,'r')
file.close()
@ -793,6 +788,7 @@ def check_begin_end(text):
error.fail(text[begin],"Missing 'end%s'"%(x,))
def find_matching_end_subfunpro(begin,x):
line = text[begin]
for i in range(begin+1,len(text)):
line = text[i]
if type(line) == x:

View File

@ -20,7 +20,6 @@ import subprocess
import tempfile
import os
import threading
from variables import variables
def build_rdtsc():
file,filename = tempfile.mkstemp()
@ -36,6 +35,7 @@ def build_rdtsc():
threading.Thread(target=t).start()
def build_module():
from variables import variables
data = """
module irp_timer
double precision :: irp_profile(3,%(n)d)

View File

@ -37,6 +37,7 @@ class Sub(object):
assert len(text) > 0
assert type(text[0]) in [Subroutine, Function]
self.text = text
self.called_by = []
############################################################
def name(self):
@ -58,7 +59,7 @@ class Sub(object):
if '_doc' not in self.__dict__:
def f(l): return
buffer = filter(lambda l:type(l) == Doc, self.text)
self._doc = map(lambda l: l.text[1:], buffer)
self._doc = map(lambda l: l.text.lstrip()[1:], buffer)
if buffer == []:
error.warn(None,"Subroutine %s is not documented"%(self.name))
return self._doc
@ -114,7 +115,7 @@ class Sub(object):
buffer = filter(lambda x: type(x) == Call,self.text)
self._calls = []
for line in buffer:
sub = line.text.split('(',1)[0].split()[1]
sub = line.text.split('(',1)[0].split()[1].lower()
self._calls.append(sub)
self._calls = make_single(self._calls)
return self._calls

View File

@ -25,7 +25,10 @@
# scemama@irsamc.ups-tlse.fr
from util import *
from subroutine import *
from variables import variables
from variable import Variable
from irpf90_t import *
def create_subroutines():
@ -47,7 +50,22 @@ def create_subroutines():
inside = False
return result
def create_called_by(subs,vars):
for s in subs.values() + vars.values():
if type(s) == Variable and s.same_as != s.name:
continue
for x in s.calls:
try:
subs[x].called_by.append(s.name)
except KeyError:
pass
for s in subs.values():
s.called_by = make_single(s.called_by)
s.called_by.sort()
subroutines = create_subroutines()
create_called_by(subroutines,variables)
if __name__ == '__main__':
for v in subroutines.keys():

View File

@ -35,7 +35,10 @@ def lower(x):
def same_file(filename,txt):
assert isinstance(filename,str)
assert type(txt) == list
if (type(txt) == list):
buffer = ''.join(txt)
else:
buffer = txt
try:
file = open(filename,"r")
@ -44,8 +47,6 @@ def same_file(filename,txt):
stream = file.read()
file.close()
buffer = ''.join(txt)
if len(stream) != len(buffer):
return False
if stream != buffer:

View File

@ -106,7 +106,7 @@ class Variable(object):
if '_doc' not in self.__dict__:
text = self.text
buffer = filter(lambda l:type(l) == Doc, text)
self._doc = map(lambda l: l.text[1:], buffer)
self._doc = map(lambda l: l.text.lstrip()[1:], buffer)
if buffer == []:
error.warn(None,"Variable %s is not documented"%(self.name))
return self._doc
@ -130,6 +130,18 @@ class Variable(object):
return self._includes
includes = property(includes)
############################################################
def calls(self):
if '_calls' not in self.__dict__:
self._calls = []
text = self.text
for line in filter(lambda x: type(x) == Call,text):
sub = line.text.split('(',1)[0].split()[1].lower()
self._calls.append(sub)
make_single(self._calls)
return self._calls
calls=property(fget=calls)
############################################################
def others(self):
if '_others' not in self.__dict__:
@ -200,7 +212,7 @@ class Variable(object):
############################################################
def fmodule(self):
if '_fmodule' not in self.__dict__:
self._fmodule = self.line.filename[0].split('.irp.f')[0]+'_mod'
self._fmodule = self.line.filename[0].replace('/','__').split('.irp.f')[0]+'_mod'
return self._fmodule
fmodule = property(fmodule)

View File

@ -1 +1 @@
version = "1.2.20"
version = "1.3.6"