Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
cb_rules.py666 linesDownload Raw Back to f2py
1"""
2Build call-back 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__, cfuncs
12from .auxfuncs import (
13    applyrules,
14    debugcapi,
15    dictappend,
16    errmess,
17    getargs,
18    hasnote,
19    isarray,
20    iscomplex,
21    iscomplexarray,
22    iscomplexfunction,
23    isfunction,
24    isintent_c,
25    isintent_hide,
26    isintent_in,
27    isintent_inout,
28    isintent_nothide,
29    isintent_out,
30    isoptional,
31    isrequired,
32    isscalar,
33    isstring,
34    isstringfunction,
35    issubroutine,
36    l_and,
37    l_not,
38    l_or,
39    outmess,
40    replace,
41    stripcomma,
42    throw_error,
43)
44
45f2py_version = __version__.version
46
47
48################## Rules for callback function ##############
49
50cb_routine_rules = {
51    'cbtypedefs': 'typedef #rctype#(*#name#_typedef)(#optargs_td##args_td##strarglens_td##noargs#);',
52    'body': """
53#begintitle#
54typedef struct {
55    PyObject *capi;
56    PyTupleObject *args_capi;
57    int nofargs;
58    jmp_buf jmpbuf;
59} #name#_t;
60
61#if defined(F2PY_THREAD_LOCAL_DECL) && !defined(F2PY_USE_PYTHON_TLS)
62
63static F2PY_THREAD_LOCAL_DECL #name#_t *_active_#name# = NULL;
64
65static #name#_t *swap_active_#name#(#name#_t *ptr) {
66    #name#_t *prev = _active_#name#;
67    _active_#name# = ptr;
68    return prev;
69}
70
71static #name#_t *get_active_#name#(void) {
72    return _active_#name#;
73}
74
75#else
76
77static #name#_t *swap_active_#name#(#name#_t *ptr) {
78    char *key = "__f2py_cb_#name#";
79    return (#name#_t *)F2PySwapThreadLocalCallbackPtr(key, ptr);
80}
81
82static #name#_t *get_active_#name#(void) {
83    char *key = "__f2py_cb_#name#";
84    return (#name#_t *)F2PyGetThreadLocalCallbackPtr(key);
85}
86
87#endif
88
89/*typedef #rctype#(*#name#_typedef)(#optargs_td##args_td##strarglens_td##noargs#);*/
90#static# #rctype# #callbackname# (#optargs##args##strarglens##noargs#) {
91    #name#_t cb_local = { NULL, NULL, 0 };
92    #name#_t *cb = NULL;
93    PyTupleObject *capi_arglist = NULL;
94    PyObject *capi_return = NULL;
95    PyObject *capi_tmp = NULL;
96    PyObject *capi_arglist_list = NULL;
97    int capi_j,capi_i = 0;
98    int capi_longjmp_ok = 1;
99#decl#
100#ifdef F2PY_REPORT_ATEXIT
101f2py_cb_start_clock();
102#endif
103    cb = get_active_#name#();
104    if (cb == NULL) {
105        capi_longjmp_ok = 0;
106        cb = &cb_local;
107    }
108    capi_arglist = cb->args_capi;
109    CFUNCSMESS(\"cb:Call-back function #name# (maxnofargs=#maxnofargs#(-#nofoptargs#))\\n\");
110    CFUNCSMESSPY(\"cb:#name#_capi=\",cb->capi);
111    if (cb->capi==NULL) {
112        capi_longjmp_ok = 0;
113        cb->capi = PyObject_GetAttrString(#modulename#_module,\"#argname#\");
114        CFUNCSMESSPY(\"cb:#name#_capi=\",cb->capi);
115    }
116    if (cb->capi==NULL) {
117        PyErr_SetString(#modulename#_error,\"cb: Callback #argname# not defined (as an argument or module #modulename# attribute).\\n\");
118        goto capi_fail;
119    }
120    if (F2PyCapsule_Check(cb->capi)) {
121    #name#_typedef #name#_cptr;
122    #name#_cptr = F2PyCapsule_AsVoidPtr(cb->capi);
123    #returncptr#(*#name#_cptr)(#optargs_nm##args_nm##strarglens_nm#);
124    #return#
125    }
126    if (capi_arglist==NULL) {
127        capi_longjmp_ok = 0;
128        capi_tmp = PyObject_GetAttrString(#modulename#_module,\"#argname#_extra_args\");
129        if (capi_tmp) {
130            capi_arglist = (PyTupleObject *)PySequence_Tuple(capi_tmp);
131            Py_DECREF(capi_tmp);
132            if (capi_arglist==NULL) {
133                PyErr_SetString(#modulename#_error,\"Failed to convert #modulename#.#argname#_extra_args to tuple.\\n\");
134                goto capi_fail;
135            }
136        } else {
137            PyErr_Clear();
138            capi_arglist = (PyTupleObject *)Py_BuildValue(\"()\");
139        }
140    }
141    if (capi_arglist == NULL) {
142        PyErr_SetString(#modulename#_error,\"Callback #argname# argument list is not set.\\n\");
143        goto capi_fail;
144    }
145#setdims#
146#ifdef PYPY_VERSION
147#define CAPI_ARGLIST_SETITEM(idx, value) PyList_SetItem((PyObject *)capi_arglist_list, idx, value)
148    capi_arglist_list = PySequence_List((PyObject *)capi_arglist);
149    if (capi_arglist_list == NULL) goto capi_fail;
150#else
151#define CAPI_ARGLIST_SETITEM(idx, value) PyTuple_SetItem((PyObject *)capi_arglist, idx, value)
152#endif
153#pyobjfrom#
154#undef CAPI_ARGLIST_SETITEM
155#ifdef PYPY_VERSION
156    CFUNCSMESSPY(\"cb:capi_arglist=\",capi_arglist_list);
157#else
158    CFUNCSMESSPY(\"cb:capi_arglist=\",capi_arglist);
159#endif
160    CFUNCSMESS(\"cb:Call-back calling Python function #argname#.\\n\");
161#ifdef F2PY_REPORT_ATEXIT
162f2py_cb_start_call_clock();
163#endif
164#ifdef PYPY_VERSION
165    capi_return = PyObject_CallObject(cb->capi,(PyObject *)capi_arglist_list);
166    Py_DECREF(capi_arglist_list);
167    capi_arglist_list = NULL;
168#else
169    capi_return = PyObject_CallObject(cb->capi,(PyObject *)capi_arglist);
170#endif
171#ifdef F2PY_REPORT_ATEXIT
172f2py_cb_stop_call_clock();
173#endif
174    CFUNCSMESSPY(\"cb:capi_return=\",capi_return);
175    if (capi_return == NULL) {
176        fprintf(stderr,\"capi_return is NULL\\n\");
177        goto capi_fail;
178    }
179    if (capi_return == Py_None) {
180        Py_DECREF(capi_return);
181        capi_return = Py_BuildValue(\"()\");
182    }
183    else if (!PyTuple_Check(capi_return)) {
184        capi_return = Py_BuildValue(\"(N)\",capi_return);
185    }
186    capi_j = PyTuple_Size(capi_return);
187    capi_i = 0;
188#frompyobj#
189    CFUNCSMESS(\"cb:#name#:successful\\n\");
190    Py_DECREF(capi_return);
191#ifdef F2PY_REPORT_ATEXIT
192f2py_cb_stop_clock();
193#endif
194    goto capi_return_pt;
195capi_fail:
196    fprintf(stderr,\"Call-back #name# failed.\\n\");
197    Py_XDECREF(capi_return);
198    Py_XDECREF(capi_arglist_list);
199    if (capi_longjmp_ok) {
200        longjmp(cb->jmpbuf,-1);
201    }
202capi_return_pt:
203    ;
204#return#
205}
206#endtitle#
207""",
208    'need': ['setjmp.h', 'CFUNCSMESS', 'F2PY_THREAD_LOCAL_DECL'],
209    'maxnofargs': '#maxnofargs#',
210    'nofoptargs': '#nofoptargs#',
211    'docstr': """\
212    def #argname#(#docsignature#): return #docreturn#\\n\\
213#docstrsigns#""",
214    'latexdocstr': """
215{{}\\verb@def #argname#(#latexdocsignature#): return #docreturn#@{}}
216#routnote#
217
218#latexdocstrsigns#""",
219    'docstrshort': 'def #argname#(#docsignature#): return #docreturn#'
220}
221cb_rout_rules = [
222    {  # Init
223        'separatorsfor': {'decl': '\n',
224                          'args': ',', 'optargs': '', 'pyobjfrom': '\n', 'freemem': '\n',
225                          'args_td': ',', 'optargs_td': '',
226                          'args_nm': ',', 'optargs_nm': '',
227                          'frompyobj': '\n', 'setdims': '\n',
228                          'docstrsigns': '\\n"\n"',
229                          'latexdocstrsigns': '\n',
230                          'latexdocstrreq': '\n', 'latexdocstropt': '\n',
231                          'latexdocstrout': '\n', 'latexdocstrcbs': '\n',
232                          },
233        'decl': '/*decl*/', 'pyobjfrom': '/*pyobjfrom*/', 'frompyobj': '/*frompyobj*/',
234        'args': [], 'optargs': '', 'return': '', 'strarglens': '', 'freemem': '/*freemem*/',
235        'args_td': [], 'optargs_td': '', 'strarglens_td': '',
236        'args_nm': [], 'optargs_nm': '', 'strarglens_nm': '',
237        'noargs': '',
238        'setdims': '/*setdims*/',
239        'docstrsigns': '', 'latexdocstrsigns': '',
240        'docstrreq': '    Required arguments:',
241        'docstropt': '    Optional arguments:',
242        'docstrout': '    Return objects:',
243        'docstrcbs': '    Call-back functions:',
244        'docreturn': '', 'docsign': '', 'docsignopt': '',
245        'latexdocstrreq': '\\noindent Required arguments:',
246        'latexdocstropt': '\\noindent Optional arguments:',
247        'latexdocstrout': '\\noindent Return objects:',
248        'latexdocstrcbs': '\\noindent Call-back functions:',
249        'routnote': {hasnote: '--- #note#', l_not(hasnote): ''},
250    }, {  # Function
251        'decl': '    #ctype# return_value = 0;',
252        'frompyobj': [
253            {debugcapi: '    CFUNCSMESS("cb:Getting return_value->");'},
254            '''\
255    if (capi_j>capi_i) {
256        GETSCALARFROMPYTUPLE(capi_return,capi_i++,&return_value,#ctype#,
257          "#ctype#_from_pyobj failed in converting return_value of"
258          " call-back function #name# to C #ctype#\\n");
259    } else {
260        fprintf(stderr,"Warning: call-back function #name# did not provide"
261                       " return value (index=%d, type=#ctype#)\\n",capi_i);
262    }''',
263            {debugcapi:
264             '    fprintf(stderr,"#showvalueformat#.\\n",return_value);'}
265        ],
266        'need': ['#ctype#_from_pyobj', {debugcapi: 'CFUNCSMESS'}, 'GETSCALARFROMPYTUPLE'],
267        'return': '    return return_value;',
268        '_check': l_and(isfunction, l_not(isstringfunction), l_not(iscomplexfunction))
269    },
270    {  # String function
271        'pyobjfrom': {debugcapi: '    fprintf(stderr,"debug-capi:cb:#name#:%d:\\n",return_value_len);'},
272        'args': '#ctype# return_value,int return_value_len',
273        'args_nm': 'return_value,&return_value_len',
274        'args_td': '#ctype# ,int',
275        'frompyobj': [
276            {debugcapi: '    CFUNCSMESS("cb:Getting return_value->\\"");'},
277            """\
278    if (capi_j>capi_i) {
279        GETSTRFROMPYTUPLE(capi_return,capi_i++,return_value,return_value_len);
280    } else {
281        fprintf(stderr,"Warning: call-back function #name# did not provide"
282                       " return value (index=%d, type=#ctype#)\\n",capi_i);
283    }""",
284            {debugcapi:
285             '    fprintf(stderr,"#showvalueformat#\\".\\n",return_value);'}
286        ],
287        'need': ['#ctype#_from_pyobj', {debugcapi: 'CFUNCSMESS'},
288                 'string.h', 'GETSTRFROMPYTUPLE'],
289        'return': 'return;',
290        '_check': isstringfunction
291    },
292    {  # Complex function
293        'optargs': """
294#ifndef F2PY_CB_RETURNCOMPLEX
295#ctype# *return_value
296#endif
297""",
298        'optargs_nm': """
299#ifndef F2PY_CB_RETURNCOMPLEX
300return_value
301#endif
302""",
303        'optargs_td': """
304#ifndef F2PY_CB_RETURNCOMPLEX
305#ctype# *
306#endif
307""",
308        'decl': """
309#ifdef F2PY_CB_RETURNCOMPLEX
310    #ctype# return_value = {0, 0};
311#endif
312""",
313        'frompyobj': [
314            {debugcapi: '    CFUNCSMESS("cb:Getting return_value->");'},
315            """\
316    if (capi_j>capi_i) {
317#ifdef F2PY_CB_RETURNCOMPLEX
318        GETSCALARFROMPYTUPLE(capi_return,capi_i++,&return_value,#ctype#,
319          \"#ctype#_from_pyobj failed in converting return_value of call-back\"
320          \" function #name# to C #ctype#\\n\");
321#else
322        GETSCALARFROMPYTUPLE(capi_return,capi_i++,return_value,#ctype#,
323          \"#ctype#_from_pyobj failed in converting return_value of call-back\"
324          \" function #name# to C #ctype#\\n\");
325#endif
326    } else {
327        fprintf(stderr,
328                \"Warning: call-back function #name# did not provide\"
329                \" return value (index=%d, type=#ctype#)\\n\",capi_i);
330    }""",
331            {debugcapi: """\
332#ifdef F2PY_CB_RETURNCOMPLEX
333    fprintf(stderr,\"#showvalueformat#.\\n\",(return_value).r,(return_value).i);
334#else
335    fprintf(stderr,\"#showvalueformat#.\\n\",(*return_value).r,(*return_value).i);
336#endif
337"""}
338        ],
339        'return': """
340#ifdef F2PY_CB_RETURNCOMPLEX
341    return return_value;
342#else
343    return;
344#endif
345""",
346        'need': ['#ctype#_from_pyobj', {debugcapi: 'CFUNCSMESS'},
347                 'string.h', 'GETSCALARFROMPYTUPLE', '#ctype#'],
348        '_check': iscomplexfunction
349    },
350    {'docstrout': '        #pydocsignout#',
351     'latexdocstrout': ['\\item[]{{}\\verb@#pydocsignout#@{}}',
352                        {hasnote: '--- #note#'}],
353     'docreturn': '#rname#,',
354     '_check': isfunction},
355    {'_check': issubroutine, 'return': 'return;'}
356]
357
358cb_arg_rules = [
359    {  # Doc
360        'docstropt': {l_and(isoptional, isintent_nothide): '        #pydocsign#'},
361        'docstrreq': {l_and(isrequired, isintent_nothide): '        #pydocsign#'},
362        'docstrout': {isintent_out: '        #pydocsignout#'},
363        'latexdocstropt': {l_and(isoptional, isintent_nothide): ['\\item[]{{}\\verb@#pydocsign#@{}}',
364                                                                 {hasnote: '--- #note#'}]},
365        'latexdocstrreq': {l_and(isrequired, isintent_nothide): ['\\item[]{{}\\verb@#pydocsign#@{}}',
366                                                                 {hasnote: '--- #note#'}]},
367        'latexdocstrout': {isintent_out: ['\\item[]{{}\\verb@#pydocsignout#@{}}',
368                                          {l_and(hasnote, isintent_hide): '--- #note#',
369                                           l_and(hasnote, isintent_nothide): '--- See above.'}]},
370        'docsign': {l_and(isrequired, isintent_nothide): '#varname#,'},
371        'docsignopt': {l_and(isoptional, isintent_nothide): '#varname#,'},
372        'depend': ''
373    },
374    {
375        'args': {
376            l_and(isscalar, isintent_c): '#ctype# #varname_i#',
377            l_and(isscalar, l_not(isintent_c)): '#ctype# *#varname_i#_cb_capi',
378            isarray: '#ctype# *#varname_i#',
379            isstring: '#ctype# #varname_i#'
380        },
381        'args_nm': {
382            l_and(isscalar, isintent_c): '#varname_i#',
383            l_and(isscalar, l_not(isintent_c)): '#varname_i#_cb_capi',
384            isarray: '#varname_i#',
385            isstring: '#varname_i#'
386        },
387        'args_td': {
388            l_and(isscalar, isintent_c): '#ctype#',
389            l_and(isscalar, l_not(isintent_c)): '#ctype# *',
390            isarray: '#ctype# *',
391            isstring: '#ctype#'
392        },
393        'need': {l_or(isscalar, isarray, isstring): '#ctype#'},
394        # untested with multiple args
395        'strarglens': {isstring: ',int #varname_i#_cb_len'},
396        'strarglens_td': {isstring: ',int'},  # untested with multiple args
397        # untested with multiple args
398        'strarglens_nm': {isstring: ',#varname_i#_cb_len'},
399    },
400    {  # Scalars
401        'decl': {l_not(isintent_c): '    #ctype# #varname_i#=(*#varname_i#_cb_capi);'},
402        'error': {l_and(isintent_c, isintent_out,
403                        throw_error('intent(c,out) is forbidden for callback scalar arguments')):
404                  ''},
405        'frompyobj': [{debugcapi: '    CFUNCSMESS("cb:Getting #varname#->");'},
406                      {isintent_out:
407                       '    if (capi_j>capi_i)\n        GETSCALARFROMPYTUPLE(capi_return,capi_i++,#varname_i#_cb_capi,#ctype#,"#ctype#_from_pyobj failed in converting argument #varname# of call-back function #name# to C #ctype#\\n");'},
408                      {l_and(debugcapi, l_and(l_not(iscomplex), isintent_c)):
409                          '    fprintf(stderr,"#showvalueformat#.\\n",#varname_i#);'},
410                      {l_and(debugcapi, l_and(l_not(iscomplex), l_not(isintent_c))):
411                          '    fprintf(stderr,"#showvalueformat#.\\n",*#varname_i#_cb_capi);'},
412                      {l_and(debugcapi, l_and(iscomplex, isintent_c)):
413                          '    fprintf(stderr,"#showvalueformat#.\\n",(#varname_i#).r,(#varname_i#).i);'},
414                      {l_and(debugcapi, l_and(iscomplex, l_not(isintent_c))):
415                          '    fprintf(stderr,"#showvalueformat#.\\n",(*#varname_i#_cb_capi).r,(*#varname_i#_cb_capi).i);'},
416                      ],
417        'need': [{isintent_out: ['#ctype#_from_pyobj', 'GETSCALARFROMPYTUPLE']},
418                 {debugcapi: 'CFUNCSMESS'}],
419        '_check': isscalar
420    }, {
421        'pyobjfrom': [{isintent_in: """\
422    if (cb->nofargs>capi_i)
423        if (CAPI_ARGLIST_SETITEM(capi_i++,pyobj_from_#ctype#1(#varname_i#)))
424            goto capi_fail;"""},
425                      {isintent_inout: """\
426    if (cb->nofargs>capi_i)
427        if (CAPI_ARGLIST_SETITEM(capi_i++,pyarr_from_p_#ctype#1(#varname_i#_cb_capi)))
428            goto capi_fail;"""}],
429        'need': [{isintent_in: 'pyobj_from_#ctype#1'},
430                 {isintent_inout: 'pyarr_from_p_#ctype#1'},
431                 {iscomplex: '#ctype#'}],
432        '_check': l_and(isscalar, isintent_nothide),
433        '_optional': ''
434    }, {  # String
435        'frompyobj': [{debugcapi: '    CFUNCSMESS("cb:Getting #varname#->\\"");'},
436                      """    if (capi_j>capi_i)
437        GETSTRFROMPYTUPLE(capi_return,capi_i++,#varname_i#,#varname_i#_cb_len);""",
438                      {debugcapi:
439                       '    fprintf(stderr,"#showvalueformat#\\":%d:.\\n",#varname_i#,#varname_i#_cb_len);'},
440                      ],
441        'need': ['#ctype#', 'GETSTRFROMPYTUPLE',
442                 {debugcapi: 'CFUNCSMESS'}, 'string.h'],
443        '_check': l_and(isstring, isintent_out)
444    }, {
445        'pyobjfrom': [
446            {debugcapi:
447             ('    fprintf(stderr,"debug-capi:cb:#varname#=#showvalueformat#:'
448              '%d:\\n",#varname_i#,#varname_i#_cb_len);')},
449            {isintent_in: """\
450    if (cb->nofargs>capi_i)
451        if (CAPI_ARGLIST_SETITEM(capi_i++,pyobj_from_#ctype#1size(#varname_i#,#varname_i#_cb_len)))
452            goto capi_fail;"""},
453                      {isintent_inout: """\
454    if (cb->nofargs>capi_i) {
455        int #varname_i#_cb_dims[] = {#varname_i#_cb_len};
456        if (CAPI_ARGLIST_SETITEM(capi_i++,pyarr_from_p_#ctype#1(#varname_i#,#varname_i#_cb_dims)))
457            goto capi_fail;
458    }"""}],
459        'need': [{isintent_in: 'pyobj_from_#ctype#1size'},
460                 {isintent_inout: 'pyarr_from_p_#ctype#1'}],
461        '_check': l_and(isstring, isintent_nothide),
462        '_optional': ''
463    },
464    # Array ...
465    {
466        'decl': '    npy_intp #varname_i#_Dims[#rank#] = {#rank*[-1]#};',
467        'setdims': '    #cbsetdims#;',
468        '_check': isarray,
469        '_depend': ''
470    },
471    {
472        'pyobjfrom': [{debugcapi: '    fprintf(stderr,"debug-capi:cb:#varname#\\n");'},
473                      {isintent_c: """\
474    if (cb->nofargs>capi_i) {
475        /* tmp_arr will be inserted to capi_arglist_list that will be
476           destroyed when leaving callback function wrapper together
477           with tmp_arr. */
478        PyArrayObject *tmp_arr = (PyArrayObject *)PyArray_New(&PyArray_Type,
479          #rank#,#varname_i#_Dims,#atype#,NULL,(char*)#varname_i#,#elsize#,
480          NPY_ARRAY_CARRAY,NULL);
481""",
482                       l_not(isintent_c): """\
483    if (cb->nofargs>capi_i) {
484        /* tmp_arr will be inserted to capi_arglist_list that will be
485           destroyed when leaving callback function wrapper together
486           with tmp_arr. */
487        PyArrayObject *tmp_arr = (PyArrayObject *)PyArray_New(&PyArray_Type,
488          #rank#,#varname_i#_Dims,#atype#,NULL,(char*)#varname_i#,#elsize#,
489          NPY_ARRAY_FARRAY,NULL);
490""",
491                       },
492                      """
493        if (tmp_arr==NULL)
494            goto capi_fail;
495        if (CAPI_ARGLIST_SETITEM(capi_i++,(PyObject *)tmp_arr))
496            goto capi_fail;
497}"""],
498        '_check': l_and(isarray, isintent_nothide, l_or(isintent_in, isintent_inout)),
499        '_optional': '',
500    }, {
501        'frompyobj': [{debugcapi: '    CFUNCSMESS("cb:Getting #varname#->");'},
502                      """    if (capi_j>capi_i) {
503        PyArrayObject *rv_cb_arr = NULL;
504        if ((capi_tmp = PyTuple_GetItem(capi_return,capi_i++))==NULL) goto capi_fail;
505        rv_cb_arr =  array_from_pyobj(#atype#,#varname_i#_Dims,#rank#,F2PY_INTENT_IN""",
506                      {isintent_c: '|F2PY_INTENT_C'},
507                      """,capi_tmp);
508        if (rv_cb_arr == NULL) {
509            fprintf(stderr,\"rv_cb_arr is NULL\\n\");
510            goto capi_fail;
511        }
512        MEMCOPY(#varname_i#,PyArray_DATA(rv_cb_arr),PyArray_NBYTES(rv_cb_arr));
513        if (capi_tmp != (PyObject *)rv_cb_arr) {
514            Py_DECREF(rv_cb_arr);
515        }
516    }""",
517                      {debugcapi: '    fprintf(stderr,"<-.\\n");'},
518                      ],
519        'need': ['MEMCOPY', {iscomplexarray: '#ctype#'}],
520        '_check': l_and(isarray, isintent_out)
521    }, {
522        'docreturn': '#varname#,',
523        '_check': isintent_out
524    }
525]
526
527################## Build call-back module #############
528cb_map = {}
529
530
531def buildcallbacks(m):
532    cb_map[m['name']] = []
533    for bi in m['body']:
534        if bi['block'] == 'interface':
535            for b in bi['body']:
536                if b:
537                    buildcallback(b, m['name'])
538                else:
539                    errmess(f"warning: empty body for {m['name']}\n")
540
541
542def buildcallback(rout, um):
543    from . import capi_maps
544
545    outmess(f"    Constructing call-back function \"cb_{rout['name']}_in_{um}\"\n")
546    args, depargs = getargs(rout)
547    capi_maps.depargs = depargs
548    var = rout['vars']
549    vrd = capi_maps.cb_routsign2map(rout, um)
550    rd = dictappend({}, vrd)
551    cb_map[um].append([rout['name'], rd['name']])
552    for r in cb_rout_rules:
553        if ('_check' in r and r['_check'](rout)) or ('_check' not in r):
554            ar = applyrules(r, vrd, rout)
555            rd = dictappend(rd, ar)
556    savevrd = {}
557    for i, a in enumerate(args):
558        vrd = capi_maps.cb_sign2map(a, var[a], index=i)
559        savevrd[a] = vrd
560        for r in cb_arg_rules:
561            if '_depend' in r:
562                continue
563            if '_optional' in r and isoptional(var[a]):
564                continue
565            if ('_check' in r and r['_check'](var[a])) or ('_check' not in r):
566                ar = applyrules(r, vrd, var[a])
567                rd = dictappend(rd, ar)
568                if '_break' in r:
569                    break
570    for a in args:
571        vrd = savevrd[a]
572        for r in cb_arg_rules:
573            if '_depend' in r:
574                continue
575            if ('_optional' not in r) or ('_optional' in r and isrequired(var[a])):
576                continue
577            if ('_check' in r and r['_check'](var[a])) or ('_check' not in r):
578                ar = applyrules(r, vrd, var[a])
579                rd = dictappend(rd, ar)
580                if '_break' in r:
581                    break
582    for a in depargs:
583        vrd = savevrd[a]
584        for r in cb_arg_rules:
585            if '_depend' not in r:
586                continue
587            if '_optional' in r:
588                continue
589            if ('_check' in r and r['_check'](var[a])) or ('_check' not in r):
590                ar = applyrules(r, vrd, var[a])
591                rd = dictappend(rd, ar)
592                if '_break' in r:
593                    break
594    if 'args' in rd and 'optargs' in rd:
595        if isinstance(rd['optargs'], list):
596            rd['optargs'] = rd['optargs'] + ["""
597#ifndef F2PY_CB_RETURNCOMPLEX
598,
599#endif
600"""]
601            rd['optargs_nm'] = rd['optargs_nm'] + ["""
602#ifndef F2PY_CB_RETURNCOMPLEX
603,
604#endif
605"""]
606            rd['optargs_td'] = rd['optargs_td'] + ["""
607#ifndef F2PY_CB_RETURNCOMPLEX
608,
609#endif
610"""]
611    if isinstance(rd['docreturn'], list):
612        rd['docreturn'] = stripcomma(
613            replace('#docreturn#', {'docreturn': rd['docreturn']}))
614    optargs = stripcomma(replace('#docsignopt#',
615                                 {'docsignopt': rd['docsignopt']}
616                                 ))
617    if optargs == '':
618        rd['docsignature'] = stripcomma(
619            replace('#docsign#', {'docsign': rd['docsign']}))
620    else:
621        rd['docsignature'] = replace('#docsign#[#docsignopt#]',
622                                     {'docsign': rd['docsign'],
623                                      'docsignopt': optargs,
624                                      })
625    rd['latexdocsignature'] = rd['docsignature'].replace('_', '\\_')
626    rd['latexdocsignature'] = rd['latexdocsignature'].replace(',', ', ')
627    rd['docstrsigns'] = []
628    rd['latexdocstrsigns'] = []
629    for k in ['docstrreq', 'docstropt', 'docstrout', 'docstrcbs']:
630        if k in rd and isinstance(rd[k], list):
631            rd['docstrsigns'] = rd['docstrsigns'] + rd[k]
632        k = 'latex' + k
633        if k in rd and isinstance(rd[k], list):
634            rd['latexdocstrsigns'] = rd['latexdocstrsigns'] + rd[k][0:1] +\
635                ['\\begin{description}'] + rd[k][1:] +\
636                ['\\end{description}']
637    if 'args' not in rd:
638        rd['args'] = ''
639        rd['args_td'] = ''
640        rd['args_nm'] = ''
641    if not (rd.get('args') or rd.get('optargs') or rd.get('strarglens')):
642        rd['noargs'] = 'void'
643
644    ar = applyrules(cb_routine_rules, rd)
645    cfuncs.callbacks[rd['name']] = ar['body']
646    if isinstance(ar['need'], str):
647        ar['need'] = [ar['need']]
648
649    if 'need' in rd:
650        for t in cfuncs.typedefs.keys():
651            if t in rd['need']:
652                ar['need'].append(t)
653
654    cfuncs.typedefs_generated[rd['name'] + '_typedef'] = ar['cbtypedefs']
655    ar['need'].append(rd['name'] + '_typedef')
656    cfuncs.needs[rd['name']] = ar['need']
657
658    capi_maps.lcb2_map[rd['name']] = {'maxnofargs': ar['maxnofargs'],
659                                      'nofoptargs': ar['nofoptargs'],
660                                      'docstr': ar['docstr'],
661                                      'latexdocstr': ar['latexdocstr'],
662                                      'argname': rd['argname']
663                                      }
664    outmess(f"      {ar['docstrshort']}\n")
665################## Build call-back function #############
666 
codekingpro/portable-devtools · Team Ai