123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- #!/usr/bin/env python3
- """
- Build F90 module support for f2py2e.
- Copyright 2000 Pearu Peterson all rights reserved,
- Pearu Peterson <pearu@ioc.ee>
- Permission to use, modify, and distribute this software is given under the
- terms of the NumPy License.
- NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
- $Date: 2005/02/03 19:30:23 $
- Pearu Peterson
- """
- __version__ = "$Revision: 1.27 $"[10:-1]
- f2py_version = 'See `f2py -v`'
- import numpy as np
- from . import capi_maps
- from . import func2subr
- from .crackfortran import undo_rmbadname, undo_rmbadname1
- # The environment provided by auxfuncs.py is needed for some calls to eval.
- # As the needed functions cannot be determined by static inspection of the
- # code, it is safest to use import * pending a major refactoring of f2py.
- from .auxfuncs import *
- options = {}
- def findf90modules(m):
- if ismodule(m):
- return [m]
- if not hasbody(m):
- return []
- ret = []
- for b in m['body']:
- if ismodule(b):
- ret.append(b)
- else:
- ret = ret + findf90modules(b)
- return ret
- fgetdims1 = """\
- external f2pysetdata
- logical ns
- integer r,i
- integer(%d) s(*)
- ns = .FALSE.
- if (allocated(d)) then
- do i=1,r
- if ((size(d,i).ne.s(i)).and.(s(i).ge.0)) then
- ns = .TRUE.
- end if
- end do
- if (ns) then
- deallocate(d)
- end if
- end if
- if ((.not.allocated(d)).and.(s(1).ge.1)) then""" % np.intp().itemsize
- fgetdims2 = """\
- end if
- if (allocated(d)) then
- do i=1,r
- s(i) = size(d,i)
- end do
- end if
- flag = 1
- call f2pysetdata(d,allocated(d))"""
- fgetdims2_sa = """\
- end if
- if (allocated(d)) then
- do i=1,r
- s(i) = size(d,i)
- end do
- !s(r) must be equal to len(d(1))
- end if
- flag = 2
- call f2pysetdata(d,allocated(d))"""
- def buildhooks(pymod):
- from . import rules
- ret = {'f90modhooks': [], 'initf90modhooks': [], 'body': [],
- 'need': ['F_FUNC', 'arrayobject.h'],
- 'separatorsfor': {'includes0': '\n', 'includes': '\n'},
- 'docs': ['"Fortran 90/95 modules:\\n"'],
- 'latexdoc': []}
- fhooks = ['']
- def fadd(line, s=fhooks):
- s[0] = '%s\n %s' % (s[0], line)
- doc = ['']
- def dadd(line, s=doc):
- s[0] = '%s\n%s' % (s[0], line)
- for m in findf90modules(pymod):
- sargs, fargs, efargs, modobjs, notvars, onlyvars = [], [], [], [], [
- m['name']], []
- sargsp = []
- ifargs = []
- mfargs = []
- if hasbody(m):
- for b in m['body']:
- notvars.append(b['name'])
- for n in m['vars'].keys():
- var = m['vars'][n]
- if (n not in notvars) and (not l_or(isintent_hide, isprivate)(var)):
- onlyvars.append(n)
- mfargs.append(n)
- outmess('\t\tConstructing F90 module support for "%s"...\n' %
- (m['name']))
- if onlyvars:
- outmess('\t\t Variables: %s\n' % (' '.join(onlyvars)))
- chooks = ['']
- def cadd(line, s=chooks):
- s[0] = '%s\n%s' % (s[0], line)
- ihooks = ['']
- def iadd(line, s=ihooks):
- s[0] = '%s\n%s' % (s[0], line)
- vrd = capi_maps.modsign2map(m)
- cadd('static FortranDataDef f2py_%s_def[] = {' % (m['name']))
- dadd('\\subsection{Fortran 90/95 module \\texttt{%s}}\n' % (m['name']))
- if hasnote(m):
- note = m['note']
- if isinstance(note, list):
- note = '\n'.join(note)
- dadd(note)
- if onlyvars:
- dadd('\\begin{description}')
- for n in onlyvars:
- var = m['vars'][n]
- modobjs.append(n)
- ct = capi_maps.getctype(var)
- at = capi_maps.c2capi_map[ct]
- dm = capi_maps.getarrdims(n, var)
- dms = dm['dims'].replace('*', '-1').strip()
- dms = dms.replace(':', '-1').strip()
- if not dms:
- dms = '-1'
- use_fgetdims2 = fgetdims2
- if isstringarray(var):
- if 'charselector' in var and 'len' in var['charselector']:
- cadd('\t{"%s",%s,{{%s,%s}},%s},'
- % (undo_rmbadname1(n), dm['rank'], dms, var['charselector']['len'], at))
- use_fgetdims2 = fgetdims2_sa
- else:
- cadd('\t{"%s",%s,{{%s}},%s},' %
- (undo_rmbadname1(n), dm['rank'], dms, at))
- else:
- cadd('\t{"%s",%s,{{%s}},%s},' %
- (undo_rmbadname1(n), dm['rank'], dms, at))
- dadd('\\item[]{{}\\verb@%s@{}}' %
- (capi_maps.getarrdocsign(n, var)))
- if hasnote(var):
- note = var['note']
- if isinstance(note, list):
- note = '\n'.join(note)
- dadd('--- %s' % (note))
- if isallocatable(var):
- fargs.append('f2py_%s_getdims_%s' % (m['name'], n))
- efargs.append(fargs[-1])
- sargs.append(
- 'void (*%s)(int*,int*,void(*)(char*,int*),int*)' % (n))
- sargsp.append('void (*)(int*,int*,void(*)(char*,int*),int*)')
- iadd('\tf2py_%s_def[i_f2py++].func = %s;' % (m['name'], n))
- fadd('subroutine %s(r,s,f2pysetdata,flag)' % (fargs[-1]))
- fadd('use %s, only: d => %s\n' %
- (m['name'], undo_rmbadname1(n)))
- fadd('integer flag\n')
- fhooks[0] = fhooks[0] + fgetdims1
- dms = range(1, int(dm['rank']) + 1)
- fadd(' allocate(d(%s))\n' %
- (','.join(['s(%s)' % i for i in dms])))
- fhooks[0] = fhooks[0] + use_fgetdims2
- fadd('end subroutine %s' % (fargs[-1]))
- else:
- fargs.append(n)
- sargs.append('char *%s' % (n))
- sargsp.append('char*')
- iadd('\tf2py_%s_def[i_f2py++].data = %s;' % (m['name'], n))
- if onlyvars:
- dadd('\\end{description}')
- if hasbody(m):
- for b in m['body']:
- if not isroutine(b):
- outmess("f90mod_rules.buildhooks:"
- f" skipping {b['block']} {b['name']}\n")
- continue
- modobjs.append('%s()' % (b['name']))
- b['modulename'] = m['name']
- api, wrap = rules.buildapi(b)
- if isfunction(b):
- fhooks[0] = fhooks[0] + wrap
- fargs.append('f2pywrap_%s_%s' % (m['name'], b['name']))
- ifargs.append(func2subr.createfuncwrapper(b, signature=1))
- else:
- if wrap:
- fhooks[0] = fhooks[0] + wrap
- fargs.append('f2pywrap_%s_%s' % (m['name'], b['name']))
- ifargs.append(
- func2subr.createsubrwrapper(b, signature=1))
- else:
- fargs.append(b['name'])
- mfargs.append(fargs[-1])
- api['externroutines'] = []
- ar = applyrules(api, vrd)
- ar['docs'] = []
- ar['docshort'] = []
- ret = dictappend(ret, ar)
- cadd('\t{"%s",-1,{{-1}},0,NULL,(void *)f2py_rout_#modulename#_%s_%s,doc_f2py_rout_#modulename#_%s_%s},' %
- (b['name'], m['name'], b['name'], m['name'], b['name']))
- sargs.append('char *%s' % (b['name']))
- sargsp.append('char *')
- iadd('\tf2py_%s_def[i_f2py++].data = %s;' %
- (m['name'], b['name']))
- cadd('\t{NULL}\n};\n')
- iadd('}')
- ihooks[0] = 'static void f2py_setup_%s(%s) {\n\tint i_f2py=0;%s' % (
- m['name'], ','.join(sargs), ihooks[0])
- if '_' in m['name']:
- F_FUNC = 'F_FUNC_US'
- else:
- F_FUNC = 'F_FUNC'
- iadd('extern void %s(f2pyinit%s,F2PYINIT%s)(void (*)(%s));'
- % (F_FUNC, m['name'], m['name'].upper(), ','.join(sargsp)))
- iadd('static void f2py_init_%s(void) {' % (m['name']))
- iadd('\t%s(f2pyinit%s,F2PYINIT%s)(f2py_setup_%s);'
- % (F_FUNC, m['name'], m['name'].upper(), m['name']))
- iadd('}\n')
- ret['f90modhooks'] = ret['f90modhooks'] + chooks + ihooks
- ret['initf90modhooks'] = ['\tPyDict_SetItemString(d, "%s", PyFortranObject_New(f2py_%s_def,f2py_init_%s));' % (
- m['name'], m['name'], m['name'])] + ret['initf90modhooks']
- fadd('')
- fadd('subroutine f2pyinit%s(f2pysetupfunc)' % (m['name']))
- if mfargs:
- for a in undo_rmbadname(mfargs):
- fadd('use %s, only : %s' % (m['name'], a))
- if ifargs:
- fadd(' '.join(['interface'] + ifargs))
- fadd('end interface')
- fadd('external f2pysetupfunc')
- if efargs:
- for a in undo_rmbadname(efargs):
- fadd('external %s' % (a))
- fadd('call f2pysetupfunc(%s)' % (','.join(undo_rmbadname(fargs))))
- fadd('end subroutine f2pyinit%s\n' % (m['name']))
- dadd('\n'.join(ret['latexdoc']).replace(
- r'\subsection{', r'\subsubsection{'))
- ret['latexdoc'] = []
- ret['docs'].append('"\t%s --- %s"' % (m['name'],
- ','.join(undo_rmbadname(modobjs))))
- ret['routine_defs'] = ''
- ret['doc'] = []
- ret['docshort'] = []
- ret['latexdoc'] = doc[0]
- if len(ret['docs']) <= 1:
- ret['docs'] = ''
- return ret, fhooks[0]
|