Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
capi_maps.py812 linesDownload Raw Back to f2py
1"""
2Copyright 1999 -- 2011 Pearu Peterson all rights reserved.
3Copyright 2011 -- present NumPy Developers.
4Permission to use, modify, and distribute this software is given under the
5terms of the NumPy License.
6
7NO WARRANTY IS EXPRESSED OR IMPLIED.  USE AT YOUR OWN RISK.
8"""
9from . import __version__
10
11f2py_version = __version__.version
12
13import copy
14import os
15import re
16
17from . import cb_rules
18from ._isocbind import iso_c2py_map, iso_c_binding_map, isoc_c2pycode_map
19
20# The environment provided by auxfuncs.py is needed for some calls to eval.
21# As the needed functions cannot be determined by static inspection of the
22# code, it is safest to use import * pending a major refactoring of f2py.
23from .auxfuncs import *
24from .crackfortran import markoutercomma
25
26__all__ = [
27    'getctype', 'getstrlength', 'getarrdims', 'getpydocsign',
28    'getarrdocsign', 'getinit', 'sign2map', 'routsign2map', 'modsign2map',
29    'cb_sign2map', 'cb_routsign2map', 'common_sign2map', 'process_f2cmap_dict'
30]
31
32
33depargs = []
34lcb_map = {}
35lcb2_map = {}
36# forced casting: mainly caused by the fact that Python or Numeric
37#                 C/APIs do not support the corresponding C types.
38c2py_map = {'double': 'float',
39            'float': 'float',                          # forced casting
40            'long_double': 'float',                    # forced casting
41            'char': 'int',                             # forced casting
42            'signed_char': 'int',                      # forced casting
43            'unsigned_char': 'int',                    # forced casting
44            'short': 'int',                            # forced casting
45            'unsigned_short': 'int',                   # forced casting
46            'int': 'int',                              # forced casting
47            'long': 'int',
48            'long_long': 'long',
49            'unsigned': 'int',                         # forced casting
50            'complex_float': 'complex',                # forced casting
51            'complex_double': 'complex',
52            'complex_long_double': 'complex',          # forced casting
53            'string': 'string',
54            'character': 'bytes',
55            }
56
57c2capi_map = {'double': 'NPY_DOUBLE',
58                'float': 'NPY_FLOAT',
59                'long_double': 'NPY_LONGDOUBLE',
60                'char': 'NPY_BYTE',
61                'unsigned_char': 'NPY_UBYTE',
62                'signed_char': 'NPY_BYTE',
63                'short': 'NPY_SHORT',
64                'unsigned_short': 'NPY_USHORT',
65                'int': 'NPY_INT',
66                'unsigned': 'NPY_UINT',
67                'long': 'NPY_LONG',
68                'unsigned_long': 'NPY_ULONG',
69                'long_long': 'NPY_LONGLONG',
70                'unsigned_long_long': 'NPY_ULONGLONG',
71                'complex_float': 'NPY_CFLOAT',
72                'complex_double': 'NPY_CDOUBLE',
73                'complex_long_double': 'NPY_CDOUBLE',
74                'string': 'NPY_STRING',
75                'character': 'NPY_STRING'}
76
77c2pycode_map = {'double': 'd',
78                'float': 'f',
79                'long_double': 'g',
80                'char': 'b',
81                'unsigned_char': 'B',
82                'signed_char': 'b',
83                'short': 'h',
84                'unsigned_short': 'H',
85                'int': 'i',
86                'unsigned': 'I',
87                'long': 'l',
88                'unsigned_long': 'L',
89                'long_long': 'q',
90                'unsigned_long_long': 'Q',
91                'complex_float': 'F',
92                'complex_double': 'D',
93                'complex_long_double': 'G',
94                'string': 'S',
95                'character': 'c'}
96
97# https://docs.python.org/3/c-api/arg.html#building-values
98c2buildvalue_map = {'double': 'd',
99                    'float': 'f',
100                    'char': 'b',
101                    'signed_char': 'b',
102                    'short': 'h',
103                    'int': 'i',
104                    'long': 'l',
105                    'long_long': 'L',
106                    'complex_float': 'N',
107                    'complex_double': 'N',
108                    'complex_long_double': 'N',
109                    'string': 'y',
110                    'character': 'c'}
111
112f2cmap_all = {'real': {'': 'float', '4': 'float', '8': 'double',
113                       '12': 'long_double', '16': 'long_double'},
114              'integer': {'': 'int', '1': 'signed_char', '2': 'short',
115                          '4': 'int', '8': 'long_long',
116                          '-1': 'unsigned_char', '-2': 'unsigned_short',
117                          '-4': 'unsigned', '-8': 'unsigned_long_long'},
118              'complex': {'': 'complex_float', '8': 'complex_float',
119                          '16': 'complex_double', '24': 'complex_long_double',
120                          '32': 'complex_long_double'},
121              'complexkind': {'': 'complex_float', '4': 'complex_float',
122                              '8': 'complex_double', '12': 'complex_long_double',
123                              '16': 'complex_long_double'},
124              'logical': {'': 'int', '1': 'char', '2': 'short', '4': 'int',
125                          '8': 'long_long'},
126              'double complex': {'': 'complex_double'},
127              'double precision': {'': 'double'},
128              'byte': {'': 'char'},
129              }
130
131# Add ISO_C handling
132c2pycode_map.update(isoc_c2pycode_map)
133c2py_map.update(iso_c2py_map)
134f2cmap_all, _ = process_f2cmap_dict(f2cmap_all, iso_c_binding_map, c2py_map)
135# End ISO_C handling
136f2cmap_default = copy.deepcopy(f2cmap_all)
137
138f2cmap_mapped = []
139
140def load_f2cmap_file(f2cmap_file):
141    global f2cmap_all, f2cmap_mapped
142
143    f2cmap_all = copy.deepcopy(f2cmap_default)
144
145    if f2cmap_file is None:
146        # Default value
147        f2cmap_file = '.f2py_f2cmap'
148        if not os.path.isfile(f2cmap_file):
149            return
150
151    # User defined additions to f2cmap_all.
152    # f2cmap_file must contain a dictionary of dictionaries, only. For
153    # example, {'real':{'low':'float'}} means that Fortran 'real(low)' is
154    # interpreted as C 'float'. This feature is useful for F90/95 users if
155    # they use PARAMETERS in type specifications.
156    try:
157        outmess(f'Reading f2cmap from {f2cmap_file!r} ...\n')
158        with open(f2cmap_file) as f:
159            d = eval(f.read().lower(), {}, {})
160        f2cmap_all, f2cmap_mapped = process_f2cmap_dict(f2cmap_all, d, c2py_map, True)
161        outmess('Successfully applied user defined f2cmap changes\n')
162    except Exception as msg:
163        errmess(f'Failed to apply user defined f2cmap changes: {msg}. Skipping.\n')
164
165
166cformat_map = {'double': '%g',
167               'float': '%g',
168               'long_double': '%Lg',
169               'char': '%d',
170               'signed_char': '%d',
171               'unsigned_char': '%hhu',
172               'short': '%hd',
173               'unsigned_short': '%hu',
174               'int': '%d',
175               'unsigned': '%u',
176               'long': '%ld',
177               'unsigned_long': '%lu',
178               'long_long': '%ld',
179               'complex_float': '(%g,%g)',
180               'complex_double': '(%g,%g)',
181               'complex_long_double': '(%Lg,%Lg)',
182               'string': '\\"%s\\"',
183               'character': "'%c'",
184               }
185
186# Auxiliary functions
187
188
189def getctype(var):
190    """
191    Determines C type
192    """
193    ctype = 'void'
194    if isfunction(var):
195        if 'result' in var:
196            a = var['result']
197        else:
198            a = var['name']
199        if a in var['vars']:
200            return getctype(var['vars'][a])
201        else:
202            errmess(f'getctype: function {a} has no return value?!\n')
203    elif issubroutine(var):
204        return ctype
205    elif ischaracter_or_characterarray(var):
206        return 'character'
207    elif isstring_or_stringarray(var):
208        return 'string'
209    elif 'typespec' in var and var['typespec'].lower() in f2cmap_all:
210        typespec = var['typespec'].lower()
211        f2cmap = f2cmap_all[typespec]
212        ctype = f2cmap['']  # default type
213        if 'kindselector' in var:
214            if '*' in var['kindselector']:
215                try:
216                    ctype = f2cmap[var['kindselector']['*']]
217                except KeyError:
218                    errmess('getctype: "%s %s %s" not supported.\n' %
219                            (var['typespec'], '*', var['kindselector']['*']))
220            elif 'kind' in var['kindselector']:
221                if typespec + 'kind' in f2cmap_all:
222                    f2cmap = f2cmap_all[typespec + 'kind']
223                try:
224                    ctype = f2cmap[var['kindselector']['kind']]
225                except KeyError:
226                    if typespec in f2cmap_all:
227                        f2cmap = f2cmap_all[typespec]
228                    try:
229                        ctype = f2cmap[str(var['kindselector']['kind'])]
230                    except KeyError:
231                        errmess('getctype: "%s(kind=%s)" is mapped to C "%s" (to override define dict(%s = dict(%s="<C typespec>")) in %s/.f2py_f2cmap file).\n'
232                                % (typespec, var['kindselector']['kind'], ctype,
233                                   typespec, var['kindselector']['kind'], os.getcwd()))
234    elif not isexternal(var):
235        errmess(f'getctype: No C-type found in "{var}", assuming void.\n')
236    return ctype
237
238
239def f2cexpr(expr):
240    """Rewrite Fortran expression as f2py supported C expression.
241
242    Due to the lack of a proper expression parser in f2py, this
243    function uses a heuristic approach that assumes that Fortran
244    arithmetic expressions are valid C arithmetic expressions when
245    mapping Fortran function calls to the corresponding C function/CPP
246    macros calls.
247
248    """
249    # TODO: support Fortran `len` function with optional kind parameter
250    expr = re.sub(r'\blen\b', 'f2py_slen', expr)
251    return expr
252
253
254def getstrlength(var):
255    if isstringfunction(var):
256        if 'result' in var:
257            a = var['result']
258        else:
259            a = var['name']
260        if a in var['vars']:
261            return getstrlength(var['vars'][a])
262        else:
263            errmess(f'getstrlength: function {a} has no return value?!\n')
264    if not isstring(var):
265        errmess(
266            f'getstrlength: expected a signature of a string but got: {repr(var)}\n')
267    len = '1'
268    if 'charselector' in var:
269        a = var['charselector']
270        if '*' in a:
271            len = a['*']
272        elif 'len' in a:
273            len = f2cexpr(a['len'])
274    if re.match(r'\(\s*(\*|:)\s*\)', len) or re.match(r'(\*|:)', len):
275        if isintent_hide(var):
276            errmess('getstrlength:intent(hide): expected a string with defined length but got: %s\n' % (
277                repr(var)))
278        len = '-1'
279    return len
280
281
282def getarrdims(a, var, verbose=0):
283    ret = {}
284    if isstring(var) and not isarray(var):
285        ret['size'] = getstrlength(var)
286        ret['rank'] = '0'
287        ret['dims'] = ''
288    elif isscalar(var):
289        ret['size'] = '1'
290        ret['rank'] = '0'
291        ret['dims'] = ''
292    elif isarray(var):
293        dim = copy.copy(var['dimension'])
294        ret['size'] = '*'.join(dim)
295        try:
296            ret['size'] = repr(eval(ret['size']))
297        except Exception:
298            pass
299        ret['dims'] = ','.join(dim)
300        ret['rank'] = repr(len(dim))
301        ret['rank*[-1]'] = repr(len(dim) * [-1])[1:-1]
302        for i in range(len(dim)):  # solve dim for dependencies
303            v = []
304            if dim[i] in depargs:
305                v = [dim[i]]
306            else:
307                for va in depargs:
308                    if re.match(r'.*?\b%s\b.*' % va, dim[i]):
309                        v.append(va)
310            for va in v:
311                if depargs.index(va) > depargs.index(a):
312                    dim[i] = '*'
313                    break
314        ret['setdims'], i = '', -1
315        for d in dim:
316            i = i + 1
317            if d not in ['*', ':', '(*)', '(:)']:
318                ret['setdims'] = '%s#varname#_Dims[%d]=%s,' % (
319                    ret['setdims'], i, d)
320        if ret['setdims']:
321            ret['setdims'] = ret['setdims'][:-1]
322        ret['cbsetdims'], i = '', -1
323        for d in var['dimension']:
324            i = i + 1
325            if d not in ['*', ':', '(*)', '(:)']:
326                ret['cbsetdims'] = '%s#varname#_Dims[%d]=%s,' % (
327                    ret['cbsetdims'], i, d)
328            elif isintent_in(var):
329                outmess('getarrdims:warning: assumed shape array, using 0 instead of %r\n'
330                        % (d))
331                ret['cbsetdims'] = '%s#varname#_Dims[%d]=%s,' % (
332                    ret['cbsetdims'], i, 0)
333            elif verbose:
334                errmess(
335                    f'getarrdims: If in call-back function: array argument {repr(a)} must have bounded dimensions: got {repr(d)}\n')
336        if ret['cbsetdims']:
337            ret['cbsetdims'] = ret['cbsetdims'][:-1]
338#         if not isintent_c(var):
339#             var['dimension'].reverse()
340    return ret
341
342
343def getpydocsign(a, var):
344    global lcb_map
345    if isfunction(var):
346        if 'result' in var:
347            af = var['result']
348        else:
349            af = var['name']
350        if af in var['vars']:
351            return getpydocsign(af, var['vars'][af])
352        else:
353            errmess(f'getctype: function {af} has no return value?!\n')
354        return '', ''
355    sig, sigout = a, a
356    opt = ''
357    if isintent_in(var):
358        opt = 'input'
359    elif isintent_inout(var):
360        opt = 'in/output'
361    out_a = a
362    if isintent_out(var):
363        for k in var['intent']:
364            if k[:4] == 'out=':
365                out_a = k[4:]
366                break
367    init = ''
368    ctype = getctype(var)
369
370    if hasinitvalue(var):
371        init, showinit = getinit(a, var)
372        init = f', optional\\n    Default: {showinit}'
373    if isscalar(var):
374        if isintent_inout(var):
375            sig = '%s : %s rank-0 array(%s,\'%s\')%s' % (a, opt, c2py_map[ctype],
376                                                         c2pycode_map[ctype], init)
377        else:
378            sig = f'{a} : {opt} {c2py_map[ctype]}{init}'
379        sigout = f'{out_a} : {c2py_map[ctype]}'
380    elif isstring(var):
381        if isintent_inout(var):
382            sig = '%s : %s rank-0 array(string(len=%s),\'c\')%s' % (
383                a, opt, getstrlength(var), init)
384        else:
385            sig = f'{a} : {opt} string(len={getstrlength(var)}){init}'
386        sigout = f'{out_a} : string(len={getstrlength(var)})'
387    elif isarray(var):
388        dim = var['dimension']
389        rank = repr(len(dim))
390        sig = '%s : %s rank-%s array(\'%s\') with bounds (%s)%s' % (a, opt, rank,
391                                                                    c2pycode_map[
392                                                                        ctype],
393                                                                    ','.join(dim), init)
394        if a == out_a:
395            sigout = '%s : rank-%s array(\'%s\') with bounds (%s)'\
396                % (a, rank, c2pycode_map[ctype], ','.join(dim))
397        else:
398            sigout = '%s : rank-%s array(\'%s\') with bounds (%s) and %s storage'\
399                % (out_a, rank, c2pycode_map[ctype], ','.join(dim), a)
400    elif isexternal(var):
401        ua = ''
402        if a in lcb_map and lcb_map[a] in lcb2_map and 'argname' in lcb2_map[lcb_map[a]]:
403            ua = lcb2_map[lcb_map[a]]['argname']
404            if not ua == a:
405                ua = f' => {ua}'
406            else:
407                ua = ''
408        sig = f'{a} : call-back function{ua}'
409        sigout = sig
410    else:
411        errmess(
412            f'getpydocsign: Could not resolve docsignature for "{a}".\n')
413    return sig, sigout
414
415
416def getarrdocsign(a, var):
417    ctype = getctype(var)
418    if isstring(var) and (not isarray(var)):
419        sig = f'{a} : rank-0 array(string(len={getstrlength(var)}),\'c\')'
420    elif isscalar(var):
421        sig = f'{a} : rank-0 array({c2py_map[ctype]},\'{c2pycode_map[ctype]}\')'
422    elif isarray(var):
423        dim = var['dimension']
424        rank = repr(len(dim))
425        sig = '%s : rank-%s array(\'%s\') with bounds (%s)' % (a, rank,
426                                                               c2pycode_map[
427                                                                   ctype],
428                                                               ','.join(dim))
429    return sig
430
431
432def getinit(a, var):
433    if isstring(var):
434        init, showinit = '""', "''"
435    else:
436        init, showinit = '', ''
437    if hasinitvalue(var):
438        init = var['=']
439        showinit = init
440        if iscomplex(var) or iscomplexarray(var):
441            ret = {}
442
443            try:
444                v = var["="]
445                if ',' in v:
446                    ret['init.r'], ret['init.i'] = markoutercomma(
447                        v[1:-1]).split('@,@')
448                else:
449                    v = eval(v, {}, {})
450                    ret['init.r'], ret['init.i'] = str(v.real), str(v.imag)
451            except Exception:
452                raise ValueError(
453                    f'getinit: expected complex number `(r,i)\' but got `{init}\' as initial value of {a!r}.')
454            if isarray(var):
455                init = f"(capi_c.r={ret['init.r']},capi_c.i={ret['init.i']},capi_c)"
456        elif isstring(var):
457            if not init:
458                init, showinit = '""', "''"
459            if init[0] == "'":
460                init = '"%s"' % (init[1:-1].replace('"', '\\"'))
461            if init[0] == '"':
462                showinit = f"'{init[1:-1]}'"
463    return init, showinit
464
465
466def get_elsize(var):
467    if isstring(var) or isstringarray(var):
468        elsize = getstrlength(var)
469        # override with user-specified length when available:
470        elsize = var['charselector'].get('f2py_len', elsize)
471        return elsize
472    if ischaracter(var) or ischaracterarray(var):
473        return '1'
474    # for numerical types, PyArray_New* functions ignore specified
475    # elsize, so we just return 1 and let elsize be determined at
476    # runtime, see fortranobject.c
477    return '1'
478
479
480def sign2map(a, var):
481    """
482    varname,ctype,atype
483    init,init.r,init.i,pytype
484    vardebuginfo,vardebugshowvalue,varshowvalue
485    varrformat
486
487    intent
488    """
489    out_a = a
490    if isintent_out(var):
491        for k in var['intent']:
492            if k[:4] == 'out=':
493                out_a = k[4:]
494                break
495    ret = {'varname': a, 'outvarname': out_a, 'ctype': getctype(var)}
496    intent_flags = []
497    for f, s in isintent_dict.items():
498        if f(var):
499            intent_flags.append(f'F2PY_{s}')
500    if intent_flags:
501        # TODO: Evaluate intent_flags here.
502        ret['intent'] = '|'.join(intent_flags)
503    else:
504        ret['intent'] = 'F2PY_INTENT_IN'
505    if isarray(var):
506        ret['varrformat'] = 'N'
507    elif ret['ctype'] in c2buildvalue_map:
508        ret['varrformat'] = c2buildvalue_map[ret['ctype']]
509    else:
510        ret['varrformat'] = 'O'
511    ret['init'], ret['showinit'] = getinit(a, var)
512    if hasinitvalue(var) and iscomplex(var) and not isarray(var):
513        ret['init.r'], ret['init.i'] = markoutercomma(
514            ret['init'][1:-1]).split('@,@')
515    if isexternal(var):
516        ret['cbnamekey'] = a
517        if a in lcb_map:
518            ret['cbname'] = lcb_map[a]
519            ret['maxnofargs'] = lcb2_map[lcb_map[a]]['maxnofargs']
520            ret['nofoptargs'] = lcb2_map[lcb_map[a]]['nofoptargs']
521            ret['cbdocstr'] = lcb2_map[lcb_map[a]]['docstr']
522            ret['cblatexdocstr'] = lcb2_map[lcb_map[a]]['latexdocstr']
523        else:
524            ret['cbname'] = a
525            errmess('sign2map: Confused: external %s is not in lcb_map%s.\n' % (
526                a, list(lcb_map.keys())))
527    if isstring(var):
528        ret['length'] = getstrlength(var)
529    if isarray(var):
530        ret = dictappend(ret, getarrdims(a, var))
531        dim = copy.copy(var['dimension'])
532    if ret['ctype'] in c2capi_map:
533        ret['atype'] = c2capi_map[ret['ctype']]
534        ret['elsize'] = get_elsize(var)
535    # Debug info
536    if debugcapi(var):
537        il = [isintent_in, 'input', isintent_out, 'output',
538              isintent_inout, 'inoutput', isrequired, 'required',
539              isoptional, 'optional', isintent_hide, 'hidden',
540              iscomplex, 'complex scalar',
541              l_and(isscalar, l_not(iscomplex)), 'scalar',
542              isstring, 'string', isarray, 'array',
543              iscomplexarray, 'complex array', isstringarray, 'string array',
544              iscomplexfunction, 'complex function',
545              l_and(isfunction, l_not(iscomplexfunction)), 'function',
546              isexternal, 'callback',
547              isintent_callback, 'callback',
548              isintent_aux, 'auxiliary',
549              ]
550        rl = []
551        for i in range(0, len(il), 2):
552            if il[i](var):
553                rl.append(il[i + 1])
554        if isstring(var):
555            rl.append(f"slen({a})={ret['length']}")
556        if isarray(var):
557            ddim = ','.join(
558                map(lambda x, y: f'{x}|{y}', var['dimension'], dim))
559            rl.append(f'dims({ddim})')
560        if isexternal(var):
561            ret['vardebuginfo'] = f"debug-capi:{a}=>{ret['cbname']}:{','.join(rl)}"
562        else:
563            ret['vardebuginfo'] = 'debug-capi:%s %s=%s:%s' % (
564                ret['ctype'], a, ret['showinit'], ','.join(rl))
565        if isscalar(var):
566            if ret['ctype'] in cformat_map:
567                ret['vardebugshowvalue'] = f"debug-capi:{a}={cformat_map[ret['ctype']]}"
568        if isstring(var):
569            ret['vardebugshowvalue'] = 'debug-capi:slen(%s)=%%d %s=\\"%%s\\"' % (
570                a, a)
571        if isexternal(var):
572            ret['vardebugshowvalue'] = f'debug-capi:{a}=%p'
573    if ret['ctype'] in cformat_map:
574        ret['varshowvalue'] = f"#name#:{a}={cformat_map[ret['ctype']]}"
575        ret['showvalueformat'] = f"{cformat_map[ret['ctype']]}"
576    if isstring(var):
577        ret['varshowvalue'] = '#name#:slen(%s)=%%d %s=\\"%%s\\"' % (a, a)
578    ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, var)
579    if hasnote(var):
580        ret['note'] = var['note']
581    return ret
582
583
584def routsign2map(rout):
585    """
586    name,NAME,begintitle,endtitle
587    rname,ctype,rformat
588    routdebugshowvalue
589    """
590    global lcb_map
591    name = rout['name']
592    fname = getfortranname(rout)
593    ret = {'name': name,
594           'texname': name.replace('_', '\\_'),
595           'name_lower': name.lower(),
596           'NAME': name.upper(),
597           'begintitle': gentitle(name),
598           'endtitle': gentitle(f'end of {name}'),
599           'fortranname': fname,
600           'FORTRANNAME': fname.upper(),
601           'callstatement': getcallstatement(rout) or '',
602           'usercode': getusercode(rout) or '',
603           'usercode1': getusercode1(rout) or '',
604           }
605    if '_' in fname:
606        ret['F_FUNC'] = 'F_FUNC_US'
607    else:
608        ret['F_FUNC'] = 'F_FUNC'
609    if '_' in name:
610        ret['F_WRAPPEDFUNC'] = 'F_WRAPPEDFUNC_US'
611    else:
612        ret['F_WRAPPEDFUNC'] = 'F_WRAPPEDFUNC'
613    lcb_map = {}
614    if 'use' in rout:
615        for u in rout['use'].keys():
616            if u in cb_rules.cb_map:
617                for un in cb_rules.cb_map[u]:
618                    ln = un[0]
619                    if 'map' in rout['use'][u]:
620                        for k in rout['use'][u]['map'].keys():
621                            if rout['use'][u]['map'][k] == un[0]:
622                                ln = k
623                                break
624                    lcb_map[ln] = un[1]
625    elif rout.get('externals'):
626        errmess('routsign2map: Confused: function %s has externals %s but no "use" statement.\n' % (
627            ret['name'], repr(rout['externals'])))
628    ret['callprotoargument'] = getcallprotoargument(rout, lcb_map) or ''
629    if isfunction(rout):
630        if 'result' in rout:
631            a = rout['result']
632        else:
633            a = rout['name']
634        ret['rname'] = a
635        ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, rout)
636        ret['ctype'] = getctype(rout['vars'][a])
637        if hasresultnote(rout):
638            ret['resultnote'] = rout['vars'][a]['note']
639            rout['vars'][a]['note'] = ['See elsewhere.']
640        if ret['ctype'] in c2buildvalue_map:
641            ret['rformat'] = c2buildvalue_map[ret['ctype']]
642        else:
643            ret['rformat'] = 'O'
644            errmess('routsign2map: no c2buildvalue key for type %s\n' %
645                    (repr(ret['ctype'])))
646        if debugcapi(rout):
647            if ret['ctype'] in cformat_map:
648                ret['routdebugshowvalue'] = 'debug-capi:%s=%s' % (
649                    a, cformat_map[ret['ctype']])
650            if isstringfunction(rout):
651                ret['routdebugshowvalue'] = 'debug-capi:slen(%s)=%%d %s=\\"%%s\\"' % (
652                    a, a)
653        if isstringfunction(rout):
654            ret['rlength'] = getstrlength(rout['vars'][a])
655            if ret['rlength'] == '-1':
656                errmess('routsign2map: expected explicit specification of the length of the string returned by the fortran function %s; taking 10.\n' % (
657                    repr(rout['name'])))
658                ret['rlength'] = '10'
659    if hasnote(rout):
660        ret['note'] = rout['note']
661        rout['note'] = ['See elsewhere.']
662    return ret
663
664
665def modsign2map(m):
666    """
667    modulename
668    """
669    if ismodule(m):
670        ret = {'f90modulename': m['name'],
671               'F90MODULENAME': m['name'].upper(),
672               'texf90modulename': m['name'].replace('_', '\\_')}
673    else:
674        ret = {'modulename': m['name'],
675               'MODULENAME': m['name'].upper(),
676               'texmodulename': m['name'].replace('_', '\\_')}
677    ret['restdoc'] = getrestdoc(m) or []
678    if hasnote(m):
679        ret['note'] = m['note']
680    ret['usercode'] = getusercode(m) or ''
681    ret['usercode1'] = getusercode1(m) or ''
682    if m['body']:
683        ret['interface_usercode'] = getusercode(m['body'][0]) or ''
684    else:
685        ret['interface_usercode'] = ''
686    ret['pymethoddef'] = getpymethoddef(m) or ''
687    if 'gil_used' in m:
688        ret['gil_used'] = m['gil_used']
689    if 'coutput' in m:
690        ret['coutput'] = m['coutput']
691    if 'f2py_wrapper_output' in m:
692        ret['f2py_wrapper_output'] = m['f2py_wrapper_output']
693    return ret
694
695
696def cb_sign2map(a, var, index=None):
697    ret = {'varname': a}
698    ret['varname_i'] = ret['varname']
699    ret['ctype'] = getctype(var)
700    if ret['ctype'] in c2capi_map:
701        ret['atype'] = c2capi_map[ret['ctype']]
702        ret['elsize'] = get_elsize(var)
703    if ret['ctype'] in cformat_map:
704        ret['showvalueformat'] = f"{cformat_map[ret['ctype']]}"
705    if isarray(var):
706        ret = dictappend(ret, getarrdims(a, var))
707    ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, var)
708    if hasnote(var):
709        ret['note'] = var['note']
710        var['note'] = ['See elsewhere.']
711    return ret
712
713
714def cb_routsign2map(rout, um):
715    """
716    name,begintitle,endtitle,argname
717    ctype,rctype,maxnofargs,nofoptargs,returncptr
718    """
719    ret = {'name': f"cb_{rout['name']}_in_{um}",
720           'returncptr': ''}
721    if isintent_callback(rout):
722        if '_' in rout['name']:
723            F_FUNC = 'F_FUNC_US'
724        else:
725            F_FUNC = 'F_FUNC'
726        ret['callbackname'] = f"{F_FUNC}({rout['name'].lower()},{rout['name'].upper()})"
727        ret['static'] = 'extern'
728    else:
729        ret['callbackname'] = ret['name']
730        ret['static'] = 'static'
731    ret['argname'] = rout['name']
732    ret['begintitle'] = gentitle(ret['name'])
733    ret['endtitle'] = gentitle(f"end of {ret['name']}")
734    ret['ctype'] = getctype(rout)
735    ret['rctype'] = 'void'
736    if ret['ctype'] == 'string':
737        ret['rctype'] = 'void'
738    else:
739        ret['rctype'] = ret['ctype']
740    if ret['rctype'] != 'void':
741        if iscomplexfunction(rout):
742            ret['returncptr'] = """
743#ifdef F2PY_CB_RETURNCOMPLEX
744return_value=
745#endif
746"""
747        else:
748            ret['returncptr'] = 'return_value='
749    if ret['ctype'] in cformat_map:
750        ret['showvalueformat'] = f"{cformat_map[ret['ctype']]}"
751    if isstringfunction(rout):
752        ret['strlength'] = getstrlength(rout)
753    if isfunction(rout):
754        if 'result' in rout:
755            a = rout['result']
756        else:
757            a = rout['name']
758        if hasnote(rout['vars'][a]):
759            ret['note'] = rout['vars'][a]['note']
760            rout['vars'][a]['note'] = ['See elsewhere.']
761        ret['rname'] = a
762        ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, rout)
763        if iscomplexfunction(rout):
764            ret['rctype'] = """
765#ifdef F2PY_CB_RETURNCOMPLEX
766#ctype#
767#else
768void
769#endif
770"""
771    elif hasnote(rout):
772        ret['note'] = rout['note']
773        rout['note'] = ['See elsewhere.']
774    nofargs = 0
775    nofoptargs = 0
776    if 'args' in rout and 'vars' in rout:
777        for a in rout['args']:
778            var = rout['vars'][a]
779            if l_or(isintent_in, isintent_inout)(var):
780                nofargs = nofargs + 1
781                if isoptional(var):
782                    nofoptargs = nofoptargs + 1
783    ret['maxnofargs'] = repr(nofargs)
784    ret['nofoptargs'] = repr(nofoptargs)
785    if hasnote(rout) and isfunction(rout) and 'result' in rout:
786        ret['routnote'] = rout['note']
787        rout['note'] = ['See elsewhere.']
788    return ret
789
790
791def common_sign2map(a, var):  # obsolete
792    ret = {'varname': a, 'ctype': getctype(var)}
793    if isstringarray(var):
794        ret['ctype'] = 'char'
795    if ret['ctype'] in c2capi_map:
796        ret['atype'] = c2capi_map[ret['ctype']]
797        ret['elsize'] = get_elsize(var)
798    if ret['ctype'] in cformat_map:
799        ret['showvalueformat'] = f"{cformat_map[ret['ctype']]}"
800    if isarray(var):
801        ret = dictappend(ret, getarrdims(a, var))
802    elif isstring(var):
803        ret['size'] = getstrlength(var)
804        ret['rank'] = '1'
805    ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, var)
806    if hasnote(var):
807        ret['note'] = var['note']
808        var['note'] = ['See elsewhere.']
809    # for strings this returns 0-rank but actually is 1-rank
810    ret['arrdocstr'] = getarrdocsign(a, var)
811    return ret
812 
codekingpro/portable-devtools · Team Ai