|
""" |
|
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] |
|
|