codekingpro/portable-devtools
115k
1"""
2Build common block mechanism for f2py2e.
3
4Copyright 1999 -- 2011 Pearu Peterson all rights reserved.
5Copyright 2011 -- present NumPy Developers.
6Permission to use, modify, and distribute this software is given under the
7terms of the NumPy License
8
9NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
10"""
11from . import __version__
12
13f2py_version = __version__.version
14
15from . import capi_maps, func2subr
16from .auxfuncs import getuseblocks, hasbody, hascommon, hasnote, isintent_hide, outmess
17from .crackfortran import rmbadname
18
19
20def findcommonblocks(block, top=1):
21 ret = []
22 if hascommon(block):
23 for key, value in block['common'].items():
24 vars_ = {v: block['vars'][v] for v in value}
25 ret.append((key, value, vars_))
26 elif hasbody(block):
27 for b in block['body']:
28 ret = ret + findcommonblocks(b, 0)
29 if top:
30 tret = []
31 names = []
32 for t in ret:
33 if t[0] not in names:
34 names.append(t[0])
35 tret.append(t)
36 return tret
37 return ret
38
39
40def buildhooks(m):
41 ret = {'commonhooks': [], 'initcommonhooks': [],
42 'docs': ['"COMMON blocks:\\n"']}
43 fwrap = ['']
44
45 def fadd(line, s=fwrap):
46 s[0] = f'{s[0]}\n {line}'
47 chooks = ['']
48
49 def cadd(line, s=chooks):
50 s[0] = f'{s[0]}\n{line}'
51 ihooks = ['']
52
53 def iadd(line, s=ihooks):
54 s[0] = f'{s[0]}\n{line}'
55 doc = ['']
56
57 def dadd(line, s=doc):
58 s[0] = f'{s[0]}\n{line}'
59 for (name, vnames, vars) in findcommonblocks(m):
60 lower_name = name.lower()
61 hnames, inames = [], []
62 for n in vnames:
63 if isintent_hide(vars[n]):
64 hnames.append(n)
65 else:
66 inames.append(n)
67 if hnames:
68 outmess('\t\tConstructing COMMON block support for "%s"...\n\t\t %s\n\t\t Hidden: %s\n' % (
69 name, ','.join(inames), ','.join(hnames)))
70 else:
71 outmess('\t\tConstructing COMMON block support for "%s"...\n\t\t %s\n' % (
72 name, ','.join(inames)))
73 fadd(f'subroutine f2pyinit{name}(setupfunc)')
74 for usename in getuseblocks(m):
75 fadd(f'use {usename}')
76 fadd('external setupfunc')
77 for n in vnames:
78 fadd(func2subr.var2fixfortran(vars, n))
79 if name == '_BLNK_':
80 fadd(f"common {','.join(vnames)}")
81 else:
82 fadd(f"common /{name}/ {','.join(vnames)}")
83 fadd(f"call setupfunc({','.join(inames)})")
84 fadd('end\n')
85 cadd('static FortranDataDef f2py_%s_def[] = {' % (name))
86 idims = []
87 for n in inames:
88 ct = capi_maps.getctype(vars[n])
89 elsize = capi_maps.get_elsize(vars[n])
90 at = capi_maps.c2capi_map[ct]
91 dm = capi_maps.getarrdims(n, vars[n])
92 if dm['dims']:
93 idims.append(f"({dm['dims']})")
94 else:
95 idims.append('')
96 dms = dm['dims'].strip()
97 if not dms:
98 dms = '-1'
99 cadd('\t{\"%s\",%s,{{%s}},%s, %s},'
100 % (n, dm['rank'], dms, at, elsize))
101 cadd('\t{NULL}\n};')
102 inames1 = rmbadname(inames)
103 inames1_tps = ','.join(['char *' + s for s in inames1])
104 cadd('static void f2py_setup_%s(%s) {' % (name, inames1_tps))
105 cadd('\tint i_f2py=0;')
106 for n in inames1:
107 cadd(f'\tf2py_{name}_def[i_f2py++].data = {n};')
108 cadd('}')
109 if '_' in lower_name:
110 F_FUNC = 'F_FUNC_US'
111 else:
112 F_FUNC = 'F_FUNC'
113 cadd('extern void %s(f2pyinit%s,F2PYINIT%s)(void(*)(%s));'
114 % (F_FUNC, lower_name, name.upper(),
115 ','.join(['char*'] * len(inames1))))
116 cadd('static void f2py_init_%s(void) {' % name)
117 cadd('\t%s(f2pyinit%s,F2PYINIT%s)(f2py_setup_%s);'
118 % (F_FUNC, lower_name, name.upper(), name))
119 cadd('}\n')
120 iadd(f'\ttmp = PyFortranObject_New(f2py_{name}_def,f2py_init_{name});')
121 iadd('\tif (tmp == NULL) return NULL;')
122 iadd(f'\tif (F2PyDict_SetItemString(d, "{name}", tmp) == -1) return NULL;')
123 iadd('\tPy_DECREF(tmp);')
124 tname = name.replace('_', '\\_')
125 dadd('\\subsection{Common block \\texttt{%s}}\n' % (tname))
126 dadd('\\begin{description}')
127 for n in inames:
128 dadd('\\item[]{{}\\verb@%s@{}}' %
129 (capi_maps.getarrdocsign(n, vars[n])))
130 if hasnote(vars[n]):
131 note = vars[n]['note']
132 if isinstance(note, list):
133 note = '\n'.join(note)
134 dadd(f'--- {note}')
135 dadd('\\end{description}')
136 ret['docs'].append(
137 f"\"\t/{name}/ {','.join(map(lambda v, d: v + d, inames, idims))}\\n\"")
138 ret['commonhooks'] = chooks
139 ret['initcommonhooks'] = ihooks
140 ret['latexdoc'] = doc[0]
141 if len(ret['docs']) <= 1:
142 ret['docs'] = ''
143 return ret, fwrap[0]
144 