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