144 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			144 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| 
								 | 
							
								"""
							 | 
						||
| 
								 | 
							
								Build common block mechanism for f2py2e.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Copyright 1999 -- 2011 Pearu Peterson all rights reserved.
							 | 
						||
| 
								 | 
							
								Copyright 2011 -- present NumPy Developers.
							 | 
						||
| 
								 | 
							
								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.
							 | 
						||
| 
								 | 
							
								"""
							 | 
						||
| 
								 | 
							
								from . import __version__
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								f2py_version = __version__.version
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								from . import capi_maps, func2subr
							 | 
						||
| 
								 | 
							
								from .auxfuncs import getuseblocks, hasbody, hascommon, hasnote, isintent_hide, outmess
							 | 
						||
| 
								 | 
							
								from .crackfortran import rmbadname
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def findcommonblocks(block, top=1):
							 | 
						||
| 
								 | 
							
								    ret = []
							 | 
						||
| 
								 | 
							
								    if hascommon(block):
							 | 
						||
| 
								 | 
							
								        for key, value in block['common'].items():
							 | 
						||
| 
								 | 
							
								            vars_ = {v: block['vars'][v] for v in value}
							 | 
						||
| 
								 | 
							
								            ret.append((key, value, vars_))
							 | 
						||
| 
								 | 
							
								    elif hasbody(block):
							 | 
						||
| 
								 | 
							
								        for b in block['body']:
							 | 
						||
| 
								 | 
							
								            ret = ret + findcommonblocks(b, 0)
							 | 
						||
| 
								 | 
							
								    if top:
							 | 
						||
| 
								 | 
							
								        tret = []
							 | 
						||
| 
								 | 
							
								        names = []
							 | 
						||
| 
								 | 
							
								        for t in ret:
							 | 
						||
| 
								 | 
							
								            if t[0] not in names:
							 | 
						||
| 
								 | 
							
								                names.append(t[0])
							 | 
						||
| 
								 | 
							
								                tret.append(t)
							 | 
						||
| 
								 | 
							
								        return tret
							 | 
						||
| 
								 | 
							
								    return ret
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def buildhooks(m):
							 | 
						||
| 
								 | 
							
								    ret = {'commonhooks': [], 'initcommonhooks': [],
							 | 
						||
| 
								 | 
							
								           'docs': ['"COMMON blocks:\\n"']}
							 | 
						||
| 
								 | 
							
								    fwrap = ['']
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def fadd(line, s=fwrap):
							 | 
						||
| 
								 | 
							
								        s[0] = f'{s[0]}\n      {line}'
							 | 
						||
| 
								 | 
							
								    chooks = ['']
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def cadd(line, s=chooks):
							 | 
						||
| 
								 | 
							
								        s[0] = f'{s[0]}\n{line}'
							 | 
						||
| 
								 | 
							
								    ihooks = ['']
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def iadd(line, s=ihooks):
							 | 
						||
| 
								 | 
							
								        s[0] = f'{s[0]}\n{line}'
							 | 
						||
| 
								 | 
							
								    doc = ['']
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def dadd(line, s=doc):
							 | 
						||
| 
								 | 
							
								        s[0] = f'{s[0]}\n{line}'
							 | 
						||
| 
								 | 
							
								    for (name, vnames, vars) in findcommonblocks(m):
							 | 
						||
| 
								 | 
							
								        lower_name = name.lower()
							 | 
						||
| 
								 | 
							
								        hnames, inames = [], []
							 | 
						||
| 
								 | 
							
								        for n in vnames:
							 | 
						||
| 
								 | 
							
								            if isintent_hide(vars[n]):
							 | 
						||
| 
								 | 
							
								                hnames.append(n)
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                inames.append(n)
							 | 
						||
| 
								 | 
							
								        if hnames:
							 | 
						||
| 
								 | 
							
								            outmess('\t\tConstructing COMMON block support for "%s"...\n\t\t  %s\n\t\t  Hidden: %s\n' % (
							 | 
						||
| 
								 | 
							
								                name, ','.join(inames), ','.join(hnames)))
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            outmess('\t\tConstructing COMMON block support for "%s"...\n\t\t  %s\n' % (
							 | 
						||
| 
								 | 
							
								                name, ','.join(inames)))
							 | 
						||
| 
								 | 
							
								        fadd(f'subroutine f2pyinit{name}(setupfunc)')
							 | 
						||
| 
								 | 
							
								        for usename in getuseblocks(m):
							 | 
						||
| 
								 | 
							
								            fadd(f'use {usename}')
							 | 
						||
| 
								 | 
							
								        fadd('external setupfunc')
							 | 
						||
| 
								 | 
							
								        for n in vnames:
							 | 
						||
| 
								 | 
							
								            fadd(func2subr.var2fixfortran(vars, n))
							 | 
						||
| 
								 | 
							
								        if name == '_BLNK_':
							 | 
						||
| 
								 | 
							
								            fadd(f"common {','.join(vnames)}")
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            fadd(f"common /{name}/ {','.join(vnames)}")
							 | 
						||
| 
								 | 
							
								        fadd(f"call setupfunc({','.join(inames)})")
							 | 
						||
| 
								 | 
							
								        fadd('end\n')
							 | 
						||
| 
								 | 
							
								        cadd('static FortranDataDef f2py_%s_def[] = {' % (name))
							 | 
						||
| 
								 | 
							
								        idims = []
							 | 
						||
| 
								 | 
							
								        for n in inames:
							 | 
						||
| 
								 | 
							
								            ct = capi_maps.getctype(vars[n])
							 | 
						||
| 
								 | 
							
								            elsize = capi_maps.get_elsize(vars[n])
							 | 
						||
| 
								 | 
							
								            at = capi_maps.c2capi_map[ct]
							 | 
						||
| 
								 | 
							
								            dm = capi_maps.getarrdims(n, vars[n])
							 | 
						||
| 
								 | 
							
								            if dm['dims']:
							 | 
						||
| 
								 | 
							
								                idims.append(f"({dm['dims']})")
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                idims.append('')
							 | 
						||
| 
								 | 
							
								            dms = dm['dims'].strip()
							 | 
						||
| 
								 | 
							
								            if not dms:
							 | 
						||
| 
								 | 
							
								                dms = '-1'
							 | 
						||
| 
								 | 
							
								            cadd('\t{\"%s\",%s,{{%s}},%s, %s},'
							 | 
						||
| 
								 | 
							
								                 % (n, dm['rank'], dms, at, elsize))
							 | 
						||
| 
								 | 
							
								        cadd('\t{NULL}\n};')
							 | 
						||
| 
								 | 
							
								        inames1 = rmbadname(inames)
							 | 
						||
| 
								 | 
							
								        inames1_tps = ','.join(['char *' + s for s in inames1])
							 | 
						||
| 
								 | 
							
								        cadd('static void f2py_setup_%s(%s) {' % (name, inames1_tps))
							 | 
						||
| 
								 | 
							
								        cadd('\tint i_f2py=0;')
							 | 
						||
| 
								 | 
							
								        for n in inames1:
							 | 
						||
| 
								 | 
							
								            cadd(f'\tf2py_{name}_def[i_f2py++].data = {n};')
							 | 
						||
| 
								 | 
							
								        cadd('}')
							 | 
						||
| 
								 | 
							
								        if '_' in lower_name:
							 | 
						||
| 
								 | 
							
								            F_FUNC = 'F_FUNC_US'
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            F_FUNC = 'F_FUNC'
							 | 
						||
| 
								 | 
							
								        cadd('extern void %s(f2pyinit%s,F2PYINIT%s)(void(*)(%s));'
							 | 
						||
| 
								 | 
							
								             % (F_FUNC, lower_name, name.upper(),
							 | 
						||
| 
								 | 
							
								                ','.join(['char*'] * len(inames1))))
							 | 
						||
| 
								 | 
							
								        cadd('static void f2py_init_%s(void) {' % name)
							 | 
						||
| 
								 | 
							
								        cadd('\t%s(f2pyinit%s,F2PYINIT%s)(f2py_setup_%s);'
							 | 
						||
| 
								 | 
							
								             % (F_FUNC, lower_name, name.upper(), name))
							 | 
						||
| 
								 | 
							
								        cadd('}\n')
							 | 
						||
| 
								 | 
							
								        iadd(f'\ttmp = PyFortranObject_New(f2py_{name}_def,f2py_init_{name});')
							 | 
						||
| 
								 | 
							
								        iadd('\tif (tmp == NULL) return NULL;')
							 | 
						||
| 
								 | 
							
								        iadd(f'\tif (F2PyDict_SetItemString(d, "{name}", tmp) == -1) return NULL;')
							 | 
						||
| 
								 | 
							
								        iadd('\tPy_DECREF(tmp);')
							 | 
						||
| 
								 | 
							
								        tname = name.replace('_', '\\_')
							 | 
						||
| 
								 | 
							
								        dadd('\\subsection{Common block \\texttt{%s}}\n' % (tname))
							 | 
						||
| 
								 | 
							
								        dadd('\\begin{description}')
							 | 
						||
| 
								 | 
							
								        for n in inames:
							 | 
						||
| 
								 | 
							
								            dadd('\\item[]{{}\\verb@%s@{}}' %
							 | 
						||
| 
								 | 
							
								                 (capi_maps.getarrdocsign(n, vars[n])))
							 | 
						||
| 
								 | 
							
								            if hasnote(vars[n]):
							 | 
						||
| 
								 | 
							
								                note = vars[n]['note']
							 | 
						||
| 
								 | 
							
								                if isinstance(note, list):
							 | 
						||
| 
								 | 
							
								                    note = '\n'.join(note)
							 | 
						||
| 
								 | 
							
								                dadd(f'--- {note}')
							 | 
						||
| 
								 | 
							
								        dadd('\\end{description}')
							 | 
						||
| 
								 | 
							
								        ret['docs'].append(
							 | 
						||
| 
								 | 
							
								            f"\"\t/{name}/ {','.join(map(lambda v, d: v + d, inames, idims))}\\n\"")
							 | 
						||
| 
								 | 
							
								    ret['commonhooks'] = chooks
							 | 
						||
| 
								 | 
							
								    ret['initcommonhooks'] = ihooks
							 | 
						||
| 
								 | 
							
								    ret['latexdoc'] = doc[0]
							 | 
						||
| 
								 | 
							
								    if len(ret['docs']) <= 1:
							 | 
						||
| 
								 | 
							
								        ret['docs'] = ''
							 | 
						||
| 
								 | 
							
								    return ret, fwrap[0]
							 |