You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							265 lines
						
					
					
						
							9.2 KiB
						
					
					
				
			
		
		
	
	
							265 lines
						
					
					
						
							9.2 KiB
						
					
					
				#!/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
 | 
						|
            cadd('\t{"%s",%s,{{%s}},%s, %s},' %
 | 
						|
                 (undo_rmbadname1(n), dm['rank'], dms, at,
 | 
						|
                  capi_maps.get_elsize(var)))
 | 
						|
            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,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]
 |