rules.py 62 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629
  1. """
  2. Rules for building C/API module with f2py2e.
  3. Here is a skeleton of a new wrapper function (13Dec2001):
  4. wrapper_function(args)
  5. declarations
  6. get_python_arguments, say, `a' and `b'
  7. get_a_from_python
  8. if (successful) {
  9. get_b_from_python
  10. if (successful) {
  11. callfortran
  12. if (successful) {
  13. put_a_to_python
  14. if (successful) {
  15. put_b_to_python
  16. if (successful) {
  17. buildvalue = ...
  18. }
  19. }
  20. }
  21. }
  22. cleanup_b
  23. }
  24. cleanup_a
  25. return buildvalue
  26. Copyright 1999 -- 2011 Pearu Peterson all rights reserved.
  27. Copyright 2011 -- present NumPy Developers.
  28. Permission to use, modify, and distribute this software is given under the
  29. terms of the NumPy License.
  30. NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
  31. """
  32. import copy
  33. import os
  34. import sys
  35. import time
  36. from pathlib import Path
  37. # __version__.version is now the same as the NumPy version
  38. from . import (
  39. __version__,
  40. capi_maps,
  41. cfuncs,
  42. common_rules,
  43. f90mod_rules,
  44. func2subr,
  45. use_rules,
  46. )
  47. from .auxfuncs import (
  48. applyrules,
  49. debugcapi,
  50. dictappend,
  51. errmess,
  52. gentitle,
  53. getargs2,
  54. hascallstatement,
  55. hasexternals,
  56. hasinitvalue,
  57. hasnote,
  58. hasresultnote,
  59. isarray,
  60. isarrayofstrings,
  61. isattr_value,
  62. ischaracter,
  63. ischaracter_or_characterarray,
  64. ischaracterarray,
  65. iscomplex,
  66. iscomplexarray,
  67. iscomplexfunction,
  68. iscomplexfunction_warn,
  69. isdummyroutine,
  70. isexternal,
  71. isfunction,
  72. isfunction_wrap,
  73. isint1,
  74. isint1array,
  75. isintent_aux,
  76. isintent_c,
  77. isintent_callback,
  78. isintent_copy,
  79. isintent_hide,
  80. isintent_inout,
  81. isintent_nothide,
  82. isintent_out,
  83. isintent_overwrite,
  84. islogical,
  85. islong_complex,
  86. islong_double,
  87. islong_doublefunction,
  88. islong_long,
  89. islong_longfunction,
  90. ismoduleroutine,
  91. isoptional,
  92. isrequired,
  93. isscalar,
  94. issigned_long_longarray,
  95. isstring,
  96. isstringarray,
  97. isstringfunction,
  98. issubroutine,
  99. issubroutine_wrap,
  100. isthreadsafe,
  101. isunsigned,
  102. isunsigned_char,
  103. isunsigned_chararray,
  104. isunsigned_long_long,
  105. isunsigned_long_longarray,
  106. isunsigned_short,
  107. isunsigned_shortarray,
  108. l_and,
  109. l_not,
  110. l_or,
  111. outmess,
  112. replace,
  113. requiresf90wrapper,
  114. stripcomma,
  115. )
  116. f2py_version = __version__.version
  117. numpy_version = __version__.version
  118. options = {}
  119. sepdict = {}
  120. # for k in ['need_cfuncs']: sepdict[k]=','
  121. for k in ['decl',
  122. 'frompyobj',
  123. 'cleanupfrompyobj',
  124. 'topyarr', 'method',
  125. 'pyobjfrom', 'closepyobjfrom',
  126. 'freemem',
  127. 'userincludes',
  128. 'includes0', 'includes', 'typedefs', 'typedefs_generated',
  129. 'cppmacros', 'cfuncs', 'callbacks',
  130. 'latexdoc',
  131. 'restdoc',
  132. 'routine_defs', 'externroutines',
  133. 'initf2pywraphooks',
  134. 'commonhooks', 'initcommonhooks',
  135. 'f90modhooks', 'initf90modhooks']:
  136. sepdict[k] = '\n'
  137. #################### Rules for C/API module #################
  138. generationtime = int(os.environ.get('SOURCE_DATE_EPOCH', time.time()))
  139. module_rules = {
  140. 'modulebody': """\
  141. /* File: #modulename#module.c
  142. * This file is auto-generated with f2py (version:#f2py_version#).
  143. * f2py is a Fortran to Python Interface Generator (FPIG), Second Edition,
  144. * written by Pearu Peterson <pearu@cens.ioc.ee>.
  145. * Generation date: """ + time.asctime(time.gmtime(generationtime)) + """
  146. * Do not edit this file directly unless you know what you are doing!!!
  147. */
  148. #ifdef __cplusplus
  149. extern \"C\" {
  150. #endif
  151. #ifndef PY_SSIZE_T_CLEAN
  152. #define PY_SSIZE_T_CLEAN
  153. #endif /* PY_SSIZE_T_CLEAN */
  154. /* Unconditionally included */
  155. #include <Python.h>
  156. #include <numpy/npy_os.h>
  157. """ + gentitle("See f2py2e/cfuncs.py: includes") + """
  158. #includes#
  159. #includes0#
  160. """ + gentitle("See f2py2e/rules.py: mod_rules['modulebody']") + """
  161. static PyObject *#modulename#_error;
  162. static PyObject *#modulename#_module;
  163. """ + gentitle("See f2py2e/cfuncs.py: typedefs") + """
  164. #typedefs#
  165. """ + gentitle("See f2py2e/cfuncs.py: typedefs_generated") + """
  166. #typedefs_generated#
  167. """ + gentitle("See f2py2e/cfuncs.py: cppmacros") + """
  168. #cppmacros#
  169. """ + gentitle("See f2py2e/cfuncs.py: cfuncs") + """
  170. #cfuncs#
  171. """ + gentitle("See f2py2e/cfuncs.py: userincludes") + """
  172. #userincludes#
  173. """ + gentitle("See f2py2e/capi_rules.py: usercode") + """
  174. #usercode#
  175. /* See f2py2e/rules.py */
  176. #externroutines#
  177. """ + gentitle("See f2py2e/capi_rules.py: usercode1") + """
  178. #usercode1#
  179. """ + gentitle("See f2py2e/cb_rules.py: buildcallback") + """
  180. #callbacks#
  181. """ + gentitle("See f2py2e/rules.py: buildapi") + """
  182. #body#
  183. """ + gentitle("See f2py2e/f90mod_rules.py: buildhooks") + """
  184. #f90modhooks#
  185. """ + gentitle("See f2py2e/rules.py: module_rules['modulebody']") + """
  186. """ + gentitle("See f2py2e/common_rules.py: buildhooks") + """
  187. #commonhooks#
  188. """ + gentitle("See f2py2e/rules.py") + """
  189. static FortranDataDef f2py_routine_defs[] = {
  190. #routine_defs#
  191. {NULL}
  192. };
  193. static PyMethodDef f2py_module_methods[] = {
  194. #pymethoddef#
  195. {NULL,NULL}
  196. };
  197. static struct PyModuleDef moduledef = {
  198. PyModuleDef_HEAD_INIT,
  199. "#modulename#",
  200. NULL,
  201. -1,
  202. f2py_module_methods,
  203. NULL,
  204. NULL,
  205. NULL,
  206. NULL
  207. };
  208. PyMODINIT_FUNC PyInit_#modulename#(void) {
  209. int i;
  210. PyObject *m,*d, *s, *tmp;
  211. m = #modulename#_module = PyModule_Create(&moduledef);
  212. Py_SET_TYPE(&PyFortran_Type, &PyType_Type);
  213. import_array();
  214. if (PyErr_Occurred())
  215. {PyErr_SetString(PyExc_ImportError, \"can't initialize module #modulename# (failed to import numpy)\"); return m;}
  216. d = PyModule_GetDict(m);
  217. s = PyUnicode_FromString(\"#f2py_version#\");
  218. PyDict_SetItemString(d, \"__version__\", s);
  219. Py_DECREF(s);
  220. s = PyUnicode_FromString(
  221. \"This module '#modulename#' is auto-generated with f2py (version:#f2py_version#).\\nFunctions:\\n\"\n#docs#\".\");
  222. PyDict_SetItemString(d, \"__doc__\", s);
  223. Py_DECREF(s);
  224. s = PyUnicode_FromString(\"""" + numpy_version + """\");
  225. PyDict_SetItemString(d, \"__f2py_numpy_version__\", s);
  226. Py_DECREF(s);
  227. #modulename#_error = PyErr_NewException (\"#modulename#.error\", NULL, NULL);
  228. /*
  229. * Store the error object inside the dict, so that it could get deallocated.
  230. * (in practice, this is a module, so it likely will not and cannot.)
  231. */
  232. PyDict_SetItemString(d, \"_#modulename#_error\", #modulename#_error);
  233. Py_DECREF(#modulename#_error);
  234. for(i=0;f2py_routine_defs[i].name!=NULL;i++) {
  235. tmp = PyFortranObject_NewAsAttr(&f2py_routine_defs[i]);
  236. PyDict_SetItemString(d, f2py_routine_defs[i].name, tmp);
  237. Py_DECREF(tmp);
  238. }
  239. #initf2pywraphooks#
  240. #initf90modhooks#
  241. #initcommonhooks#
  242. #interface_usercode#
  243. #ifdef Py_GIL_DISABLED
  244. // signal whether this module supports running with the GIL disabled
  245. PyUnstable_Module_SetGIL(m , #gil_used#);
  246. #endif
  247. #ifdef F2PY_REPORT_ATEXIT
  248. if (! PyErr_Occurred())
  249. on_exit(f2py_report_on_exit,(void*)\"#modulename#\");
  250. #endif
  251. if (PyType_Ready(&PyFortran_Type) < 0) {
  252. return NULL;
  253. }
  254. return m;
  255. }
  256. #ifdef __cplusplus
  257. }
  258. #endif
  259. """,
  260. 'separatorsfor': {'latexdoc': '\n\n',
  261. 'restdoc': '\n\n'},
  262. 'latexdoc': ['\\section{Module \\texttt{#texmodulename#}}\n',
  263. '#modnote#\n',
  264. '#latexdoc#'],
  265. 'restdoc': ['Module #modulename#\n' + '=' * 80,
  266. '\n#restdoc#']
  267. }
  268. defmod_rules = [
  269. {'body': '/*eof body*/',
  270. 'method': '/*eof method*/',
  271. 'externroutines': '/*eof externroutines*/',
  272. 'routine_defs': '/*eof routine_defs*/',
  273. 'initf90modhooks': '/*eof initf90modhooks*/',
  274. 'initf2pywraphooks': '/*eof initf2pywraphooks*/',
  275. 'initcommonhooks': '/*eof initcommonhooks*/',
  276. 'latexdoc': '',
  277. 'restdoc': '',
  278. 'modnote': {hasnote: '#note#', l_not(hasnote): ''},
  279. }
  280. ]
  281. routine_rules = {
  282. 'separatorsfor': sepdict,
  283. 'body': """
  284. #begintitle#
  285. static char doc_#apiname#[] = \"\\\n#docreturn##name#(#docsignatureshort#)\\n\\nWrapper for ``#name#``.\\\n\\n#docstrsigns#\";
  286. /* #declfortranroutine# */
  287. static PyObject *#apiname#(const PyObject *capi_self,
  288. PyObject *capi_args,
  289. PyObject *capi_keywds,
  290. #functype# (*f2py_func)(#callprotoargument#)) {
  291. PyObject * volatile capi_buildvalue = NULL;
  292. volatile int f2py_success = 1;
  293. #decl#
  294. static char *capi_kwlist[] = {#kwlist##kwlistopt##kwlistxa#NULL};
  295. #usercode#
  296. #routdebugenter#
  297. #ifdef F2PY_REPORT_ATEXIT
  298. f2py_start_clock();
  299. #endif
  300. if (!PyArg_ParseTupleAndKeywords(capi_args,capi_keywds,\\
  301. \"#argformat#|#keyformat##xaformat#:#pyname#\",\\
  302. capi_kwlist#args_capi##keys_capi##keys_xa#))\n return NULL;
  303. #frompyobj#
  304. /*end of frompyobj*/
  305. #ifdef F2PY_REPORT_ATEXIT
  306. f2py_start_call_clock();
  307. #endif
  308. #callfortranroutine#
  309. if (PyErr_Occurred())
  310. f2py_success = 0;
  311. #ifdef F2PY_REPORT_ATEXIT
  312. f2py_stop_call_clock();
  313. #endif
  314. /*end of callfortranroutine*/
  315. if (f2py_success) {
  316. #pyobjfrom#
  317. /*end of pyobjfrom*/
  318. CFUNCSMESS(\"Building return value.\\n\");
  319. capi_buildvalue = Py_BuildValue(\"#returnformat#\"#return#);
  320. /*closepyobjfrom*/
  321. #closepyobjfrom#
  322. } /*if (f2py_success) after callfortranroutine*/
  323. /*cleanupfrompyobj*/
  324. #cleanupfrompyobj#
  325. if (capi_buildvalue == NULL) {
  326. #routdebugfailure#
  327. } else {
  328. #routdebugleave#
  329. }
  330. CFUNCSMESS(\"Freeing memory.\\n\");
  331. #freemem#
  332. #ifdef F2PY_REPORT_ATEXIT
  333. f2py_stop_clock();
  334. #endif
  335. return capi_buildvalue;
  336. }
  337. #endtitle#
  338. """,
  339. 'routine_defs': '#routine_def#',
  340. 'initf2pywraphooks': '#initf2pywraphook#',
  341. 'externroutines': '#declfortranroutine#',
  342. 'doc': '#docreturn##name#(#docsignature#)',
  343. 'docshort': '#docreturn##name#(#docsignatureshort#)',
  344. 'docs': '" #docreturn##name#(#docsignature#)\\n"\n',
  345. 'need': ['arrayobject.h', 'CFUNCSMESS', 'MINMAX'],
  346. 'cppmacros': {debugcapi: '#define DEBUGCFUNCS'},
  347. 'latexdoc': ['\\subsection{Wrapper function \\texttt{#texname#}}\n',
  348. """
  349. \\noindent{{}\\verb@#docreturn##name#@{}}\\texttt{(#latexdocsignatureshort#)}
  350. #routnote#
  351. #latexdocstrsigns#
  352. """],
  353. 'restdoc': ['Wrapped function ``#name#``\n' + '-' * 80,
  354. ]
  355. }
  356. ################## Rules for C/API function ##############
  357. rout_rules = [
  358. { # Init
  359. 'separatorsfor': {'callfortranroutine': '\n', 'routdebugenter': '\n', 'decl': '\n',
  360. 'routdebugleave': '\n', 'routdebugfailure': '\n',
  361. 'setjmpbuf': ' || ',
  362. 'docstrreq': '\n', 'docstropt': '\n', 'docstrout': '\n',
  363. 'docstrcbs': '\n', 'docstrsigns': '\\n"\n"',
  364. 'latexdocstrsigns': '\n',
  365. 'latexdocstrreq': '\n', 'latexdocstropt': '\n',
  366. 'latexdocstrout': '\n', 'latexdocstrcbs': '\n',
  367. },
  368. 'kwlist': '', 'kwlistopt': '', 'callfortran': '', 'callfortranappend': '',
  369. 'docsign': '', 'docsignopt': '', 'decl': '/*decl*/',
  370. 'freemem': '/*freemem*/',
  371. 'docsignshort': '', 'docsignoptshort': '',
  372. 'docstrsigns': '', 'latexdocstrsigns': '',
  373. 'docstrreq': '\\nParameters\\n----------',
  374. 'docstropt': '\\nOther Parameters\\n----------------',
  375. 'docstrout': '\\nReturns\\n-------',
  376. 'docstrcbs': '\\nNotes\\n-----\\nCall-back functions::\\n',
  377. 'latexdocstrreq': '\\noindent Required arguments:',
  378. 'latexdocstropt': '\\noindent Optional arguments:',
  379. 'latexdocstrout': '\\noindent Return objects:',
  380. 'latexdocstrcbs': '\\noindent Call-back functions:',
  381. 'args_capi': '', 'keys_capi': '', 'functype': '',
  382. 'frompyobj': '/*frompyobj*/',
  383. # this list will be reversed
  384. 'cleanupfrompyobj': ['/*end of cleanupfrompyobj*/'],
  385. 'pyobjfrom': '/*pyobjfrom*/',
  386. # this list will be reversed
  387. 'closepyobjfrom': ['/*end of closepyobjfrom*/'],
  388. 'topyarr': '/*topyarr*/', 'routdebugleave': '/*routdebugleave*/',
  389. 'routdebugenter': '/*routdebugenter*/',
  390. 'routdebugfailure': '/*routdebugfailure*/',
  391. 'callfortranroutine': '/*callfortranroutine*/',
  392. 'argformat': '', 'keyformat': '', 'need_cfuncs': '',
  393. 'docreturn': '', 'return': '', 'returnformat': '', 'rformat': '',
  394. 'kwlistxa': '', 'keys_xa': '', 'xaformat': '', 'docsignxa': '', 'docsignxashort': '',
  395. 'initf2pywraphook': '',
  396. 'routnote': {hasnote: '--- #note#', l_not(hasnote): ''},
  397. }, {
  398. 'apiname': 'f2py_rout_#modulename#_#name#',
  399. 'pyname': '#modulename#.#name#',
  400. 'decl': '',
  401. '_check': l_not(ismoduleroutine)
  402. }, {
  403. 'apiname': 'f2py_rout_#modulename#_#f90modulename#_#name#',
  404. 'pyname': '#modulename#.#f90modulename#.#name#',
  405. 'decl': '',
  406. '_check': ismoduleroutine
  407. }, { # Subroutine
  408. 'functype': 'void',
  409. 'declfortranroutine': {l_and(l_not(l_or(ismoduleroutine, isintent_c)), l_not(isdummyroutine)): 'extern void #F_FUNC#(#fortranname#,#FORTRANNAME#)(#callprotoargument#);',
  410. l_and(l_not(ismoduleroutine), isintent_c, l_not(isdummyroutine)): 'extern void #fortranname#(#callprotoargument#);',
  411. ismoduleroutine: '',
  412. isdummyroutine: ''
  413. },
  414. 'routine_def': {
  415. l_not(l_or(ismoduleroutine, isintent_c, isdummyroutine)):
  416. ' {\"#name#\",-1,{{-1}},0,0,(char *)'
  417. ' #F_FUNC#(#fortranname#,#FORTRANNAME#),'
  418. ' (f2py_init_func)#apiname#,doc_#apiname#},',
  419. l_and(l_not(ismoduleroutine), isintent_c, l_not(isdummyroutine)):
  420. ' {\"#name#\",-1,{{-1}},0,0,(char *)#fortranname#,'
  421. ' (f2py_init_func)#apiname#,doc_#apiname#},',
  422. l_and(l_not(ismoduleroutine), isdummyroutine):
  423. ' {\"#name#\",-1,{{-1}},0,0,NULL,'
  424. ' (f2py_init_func)#apiname#,doc_#apiname#},',
  425. },
  426. 'need': {l_and(l_not(l_or(ismoduleroutine, isintent_c)), l_not(isdummyroutine)): 'F_FUNC'},
  427. 'callfortranroutine': [
  428. {debugcapi: [
  429. """ fprintf(stderr,\"debug-capi:Fortran subroutine `#fortranname#(#callfortran#)\'\\n\");"""]},
  430. {hasexternals: """\
  431. if (#setjmpbuf#) {
  432. f2py_success = 0;
  433. } else {"""},
  434. {isthreadsafe: ' Py_BEGIN_ALLOW_THREADS'},
  435. {hascallstatement: ''' #callstatement#;
  436. /*(*f2py_func)(#callfortran#);*/'''},
  437. {l_not(l_or(hascallstatement, isdummyroutine))
  438. : ' (*f2py_func)(#callfortran#);'},
  439. {isthreadsafe: ' Py_END_ALLOW_THREADS'},
  440. {hasexternals: """ }"""}
  441. ],
  442. '_check': l_and(issubroutine, l_not(issubroutine_wrap)),
  443. }, { # Wrapped function
  444. 'functype': 'void',
  445. 'declfortranroutine': {l_not(l_or(ismoduleroutine, isdummyroutine)): 'extern void #F_WRAPPEDFUNC#(#name_lower#,#NAME#)(#callprotoargument#);',
  446. isdummyroutine: '',
  447. },
  448. 'routine_def': {
  449. l_not(l_or(ismoduleroutine, isdummyroutine)):
  450. ' {\"#name#\",-1,{{-1}},0,0,(char *)'
  451. ' #F_WRAPPEDFUNC#(#name_lower#,#NAME#),'
  452. ' (f2py_init_func)#apiname#,doc_#apiname#},',
  453. isdummyroutine:
  454. ' {\"#name#\",-1,{{-1}},0,0,NULL,'
  455. ' (f2py_init_func)#apiname#,doc_#apiname#},',
  456. },
  457. 'initf2pywraphook': {l_not(l_or(ismoduleroutine, isdummyroutine)): '''
  458. {
  459. extern #ctype# #F_FUNC#(#name_lower#,#NAME#)(void);
  460. PyObject* o = PyDict_GetItemString(d,"#name#");
  461. tmp = F2PyCapsule_FromVoidPtr((void*)#F_WRAPPEDFUNC#(#name_lower#,#NAME#),NULL);
  462. PyObject_SetAttrString(o,"_cpointer", tmp);
  463. Py_DECREF(tmp);
  464. s = PyUnicode_FromString("#name#");
  465. PyObject_SetAttrString(o,"__name__", s);
  466. Py_DECREF(s);
  467. }
  468. '''},
  469. 'need': {l_not(l_or(ismoduleroutine, isdummyroutine)): ['F_WRAPPEDFUNC', 'F_FUNC']},
  470. 'callfortranroutine': [
  471. {debugcapi: [
  472. """ fprintf(stderr,\"debug-capi:Fortran subroutine `f2pywrap#name_lower#(#callfortran#)\'\\n\");"""]},
  473. {hasexternals: """\
  474. if (#setjmpbuf#) {
  475. f2py_success = 0;
  476. } else {"""},
  477. {isthreadsafe: ' Py_BEGIN_ALLOW_THREADS'},
  478. {l_not(l_or(hascallstatement, isdummyroutine))
  479. : ' (*f2py_func)(#callfortran#);'},
  480. {hascallstatement:
  481. ' #callstatement#;\n /*(*f2py_func)(#callfortran#);*/'},
  482. {isthreadsafe: ' Py_END_ALLOW_THREADS'},
  483. {hasexternals: ' }'}
  484. ],
  485. '_check': isfunction_wrap,
  486. }, { # Wrapped subroutine
  487. 'functype': 'void',
  488. 'declfortranroutine': {l_not(l_or(ismoduleroutine, isdummyroutine)): 'extern void #F_WRAPPEDFUNC#(#name_lower#,#NAME#)(#callprotoargument#);',
  489. isdummyroutine: '',
  490. },
  491. 'routine_def': {
  492. l_not(l_or(ismoduleroutine, isdummyroutine)):
  493. ' {\"#name#\",-1,{{-1}},0,0,(char *)'
  494. ' #F_WRAPPEDFUNC#(#name_lower#,#NAME#),'
  495. ' (f2py_init_func)#apiname#,doc_#apiname#},',
  496. isdummyroutine:
  497. ' {\"#name#\",-1,{{-1}},0,0,NULL,'
  498. ' (f2py_init_func)#apiname#,doc_#apiname#},',
  499. },
  500. 'initf2pywraphook': {l_not(l_or(ismoduleroutine, isdummyroutine)): '''
  501. {
  502. extern void #F_FUNC#(#name_lower#,#NAME#)(void);
  503. PyObject* o = PyDict_GetItemString(d,"#name#");
  504. tmp = F2PyCapsule_FromVoidPtr((void*)#F_FUNC#(#name_lower#,#NAME#),NULL);
  505. PyObject_SetAttrString(o,"_cpointer", tmp);
  506. Py_DECREF(tmp);
  507. s = PyUnicode_FromString("#name#");
  508. PyObject_SetAttrString(o,"__name__", s);
  509. Py_DECREF(s);
  510. }
  511. '''},
  512. 'need': {l_not(l_or(ismoduleroutine, isdummyroutine)): ['F_WRAPPEDFUNC', 'F_FUNC']},
  513. 'callfortranroutine': [
  514. {debugcapi: [
  515. """ fprintf(stderr,\"debug-capi:Fortran subroutine `f2pywrap#name_lower#(#callfortran#)\'\\n\");"""]},
  516. {hasexternals: """\
  517. if (#setjmpbuf#) {
  518. f2py_success = 0;
  519. } else {"""},
  520. {isthreadsafe: ' Py_BEGIN_ALLOW_THREADS'},
  521. {l_not(l_or(hascallstatement, isdummyroutine))
  522. : ' (*f2py_func)(#callfortran#);'},
  523. {hascallstatement:
  524. ' #callstatement#;\n /*(*f2py_func)(#callfortran#);*/'},
  525. {isthreadsafe: ' Py_END_ALLOW_THREADS'},
  526. {hasexternals: ' }'}
  527. ],
  528. '_check': issubroutine_wrap,
  529. }, { # Function
  530. 'functype': '#ctype#',
  531. 'docreturn': {l_not(isintent_hide): '#rname#,'},
  532. 'docstrout': '#pydocsignout#',
  533. 'latexdocstrout': ['\\item[]{{}\\verb@#pydocsignout#@{}}',
  534. {hasresultnote: '--- #resultnote#'}],
  535. 'callfortranroutine': [{l_and(debugcapi, isstringfunction): """\
  536. #ifdef USESCOMPAQFORTRAN
  537. fprintf(stderr,\"debug-capi:Fortran function #ctype# #fortranname#(#callcompaqfortran#)\\n\");
  538. #else
  539. fprintf(stderr,\"debug-capi:Fortran function #ctype# #fortranname#(#callfortran#)\\n\");
  540. #endif
  541. """},
  542. {l_and(debugcapi, l_not(isstringfunction)): """\
  543. fprintf(stderr,\"debug-capi:Fortran function #ctype# #fortranname#(#callfortran#)\\n\");
  544. """}
  545. ],
  546. '_check': l_and(isfunction, l_not(isfunction_wrap))
  547. }, { # Scalar function
  548. 'declfortranroutine': {l_and(l_not(l_or(ismoduleroutine, isintent_c)), l_not(isdummyroutine)): 'extern #ctype# #F_FUNC#(#fortranname#,#FORTRANNAME#)(#callprotoargument#);',
  549. l_and(l_not(ismoduleroutine), isintent_c, l_not(isdummyroutine)): 'extern #ctype# #fortranname#(#callprotoargument#);',
  550. isdummyroutine: ''
  551. },
  552. 'routine_def': {
  553. l_and(l_not(l_or(ismoduleroutine, isintent_c)),
  554. l_not(isdummyroutine)):
  555. (' {\"#name#\",-1,{{-1}},0,0,(char *)'
  556. ' #F_FUNC#(#fortranname#,#FORTRANNAME#),'
  557. ' (f2py_init_func)#apiname#,doc_#apiname#},'),
  558. l_and(l_not(ismoduleroutine), isintent_c, l_not(isdummyroutine)):
  559. (' {\"#name#\",-1,{{-1}},0,0,(char *)#fortranname#,'
  560. ' (f2py_init_func)#apiname#,doc_#apiname#},'),
  561. isdummyroutine:
  562. ' {\"#name#\",-1,{{-1}},0,0,NULL,'
  563. '(f2py_init_func)#apiname#,doc_#apiname#},',
  564. },
  565. 'decl': [{iscomplexfunction_warn: ' #ctype# #name#_return_value={0,0};',
  566. l_not(iscomplexfunction): ' #ctype# #name#_return_value=0;'},
  567. {iscomplexfunction:
  568. ' PyObject *#name#_return_value_capi = Py_None;'}
  569. ],
  570. 'callfortranroutine': [
  571. {hasexternals: """\
  572. if (#setjmpbuf#) {
  573. f2py_success = 0;
  574. } else {"""},
  575. {isthreadsafe: ' Py_BEGIN_ALLOW_THREADS'},
  576. {hascallstatement: ''' #callstatement#;
  577. /* #name#_return_value = (*f2py_func)(#callfortran#);*/
  578. '''},
  579. {l_not(l_or(hascallstatement, isdummyroutine))
  580. : ' #name#_return_value = (*f2py_func)(#callfortran#);'},
  581. {isthreadsafe: ' Py_END_ALLOW_THREADS'},
  582. {hasexternals: ' }'},
  583. {l_and(debugcapi, iscomplexfunction)
  584. : ' fprintf(stderr,"#routdebugshowvalue#\\n",#name#_return_value.r,#name#_return_value.i);'},
  585. {l_and(debugcapi, l_not(iscomplexfunction)): ' fprintf(stderr,"#routdebugshowvalue#\\n",#name#_return_value);'}],
  586. 'pyobjfrom': {iscomplexfunction: ' #name#_return_value_capi = pyobj_from_#ctype#1(#name#_return_value);'},
  587. 'need': [{l_not(isdummyroutine): 'F_FUNC'},
  588. {iscomplexfunction: 'pyobj_from_#ctype#1'},
  589. {islong_longfunction: 'long_long'},
  590. {islong_doublefunction: 'long_double'}],
  591. 'returnformat': {l_not(isintent_hide): '#rformat#'},
  592. 'return': {iscomplexfunction: ',#name#_return_value_capi',
  593. l_not(l_or(iscomplexfunction, isintent_hide)): ',#name#_return_value'},
  594. '_check': l_and(isfunction, l_not(isstringfunction), l_not(isfunction_wrap))
  595. }, { # String function # in use for --no-wrap
  596. 'declfortranroutine': 'extern void #F_FUNC#(#fortranname#,#FORTRANNAME#)(#callprotoargument#);',
  597. 'routine_def': {l_not(l_or(ismoduleroutine, isintent_c)):
  598. ' {\"#name#\",-1,{{-1}},0,0,(char *)#F_FUNC#(#fortranname#,#FORTRANNAME#),(f2py_init_func)#apiname#,doc_#apiname#},',
  599. l_and(l_not(ismoduleroutine), isintent_c):
  600. ' {\"#name#\",-1,{{-1}},0,0,(char *)#fortranname#,(f2py_init_func)#apiname#,doc_#apiname#},'
  601. },
  602. 'decl': [' #ctype# #name#_return_value = NULL;',
  603. ' int #name#_return_value_len = 0;'],
  604. 'callfortran': '#name#_return_value,#name#_return_value_len,',
  605. 'callfortranroutine': [' #name#_return_value_len = #rlength#;',
  606. ' if ((#name#_return_value = (string)malloc(#name#_return_value_len+1) == NULL) {',
  607. ' PyErr_SetString(PyExc_MemoryError, \"out of memory\");',
  608. ' f2py_success = 0;',
  609. ' } else {',
  610. " (#name#_return_value)[#name#_return_value_len] = '\\0';",
  611. ' }',
  612. ' if (f2py_success) {',
  613. {hasexternals: """\
  614. if (#setjmpbuf#) {
  615. f2py_success = 0;
  616. } else {"""},
  617. {isthreadsafe: ' Py_BEGIN_ALLOW_THREADS'},
  618. """\
  619. #ifdef USESCOMPAQFORTRAN
  620. (*f2py_func)(#callcompaqfortran#);
  621. #else
  622. (*f2py_func)(#callfortran#);
  623. #endif
  624. """,
  625. {isthreadsafe: ' Py_END_ALLOW_THREADS'},
  626. {hasexternals: ' }'},
  627. {debugcapi:
  628. ' fprintf(stderr,"#routdebugshowvalue#\\n",#name#_return_value_len,#name#_return_value);'},
  629. ' } /* if (f2py_success) after (string)malloc */',
  630. ],
  631. 'returnformat': '#rformat#',
  632. 'return': ',#name#_return_value',
  633. 'freemem': ' STRINGFREE(#name#_return_value);',
  634. 'need': ['F_FUNC', '#ctype#', 'STRINGFREE'],
  635. '_check': l_and(isstringfunction, l_not(isfunction_wrap)) # ???obsolete
  636. },
  637. { # Debugging
  638. 'routdebugenter': ' fprintf(stderr,"debug-capi:Python C/API function #modulename#.#name#(#docsignature#)\\n");',
  639. 'routdebugleave': ' fprintf(stderr,"debug-capi:Python C/API function #modulename#.#name#: successful.\\n");',
  640. 'routdebugfailure': ' fprintf(stderr,"debug-capi:Python C/API function #modulename#.#name#: failure.\\n");',
  641. '_check': debugcapi
  642. }
  643. ]
  644. ################ Rules for arguments ##################
  645. typedef_need_dict = {islong_long: 'long_long',
  646. islong_double: 'long_double',
  647. islong_complex: 'complex_long_double',
  648. isunsigned_char: 'unsigned_char',
  649. isunsigned_short: 'unsigned_short',
  650. isunsigned: 'unsigned',
  651. isunsigned_long_long: 'unsigned_long_long',
  652. isunsigned_chararray: 'unsigned_char',
  653. isunsigned_shortarray: 'unsigned_short',
  654. isunsigned_long_longarray: 'unsigned_long_long',
  655. issigned_long_longarray: 'long_long',
  656. isint1: 'signed_char',
  657. ischaracter_or_characterarray: 'character',
  658. }
  659. aux_rules = [
  660. {
  661. 'separatorsfor': sepdict
  662. },
  663. { # Common
  664. 'frompyobj': [' /* Processing auxiliary variable #varname# */',
  665. {debugcapi: ' fprintf(stderr,"#vardebuginfo#\\n");'}, ],
  666. 'cleanupfrompyobj': ' /* End of cleaning variable #varname# */',
  667. 'need': typedef_need_dict,
  668. },
  669. # Scalars (not complex)
  670. { # Common
  671. 'decl': ' #ctype# #varname# = 0;',
  672. 'need': {hasinitvalue: 'math.h'},
  673. 'frompyobj': {hasinitvalue: ' #varname# = #init#;'},
  674. '_check': l_and(isscalar, l_not(iscomplex)),
  675. },
  676. {
  677. 'return': ',#varname#',
  678. 'docstrout': '#pydocsignout#',
  679. 'docreturn': '#outvarname#,',
  680. 'returnformat': '#varrformat#',
  681. '_check': l_and(isscalar, l_not(iscomplex), isintent_out),
  682. },
  683. # Complex scalars
  684. { # Common
  685. 'decl': ' #ctype# #varname#;',
  686. 'frompyobj': {hasinitvalue: ' #varname#.r = #init.r#, #varname#.i = #init.i#;'},
  687. '_check': iscomplex
  688. },
  689. # String
  690. { # Common
  691. 'decl': [' #ctype# #varname# = NULL;',
  692. ' int slen(#varname#);',
  693. ],
  694. 'need': ['len..'],
  695. '_check': isstring
  696. },
  697. # Array
  698. { # Common
  699. 'decl': [' #ctype# *#varname# = NULL;',
  700. ' npy_intp #varname#_Dims[#rank#] = {#rank*[-1]#};',
  701. ' const int #varname#_Rank = #rank#;',
  702. ],
  703. 'need': ['len..', {hasinitvalue: 'forcomb'}, {hasinitvalue: 'CFUNCSMESS'}],
  704. '_check': isarray
  705. },
  706. # Scalararray
  707. { # Common
  708. '_check': l_and(isarray, l_not(iscomplexarray))
  709. }, { # Not hidden
  710. '_check': l_and(isarray, l_not(iscomplexarray), isintent_nothide)
  711. },
  712. # Integer*1 array
  713. {'need': '#ctype#',
  714. '_check': isint1array,
  715. '_depend': ''
  716. },
  717. # Integer*-1 array
  718. {'need': '#ctype#',
  719. '_check': l_or(isunsigned_chararray, isunsigned_char),
  720. '_depend': ''
  721. },
  722. # Integer*-2 array
  723. {'need': '#ctype#',
  724. '_check': isunsigned_shortarray,
  725. '_depend': ''
  726. },
  727. # Integer*-8 array
  728. {'need': '#ctype#',
  729. '_check': isunsigned_long_longarray,
  730. '_depend': ''
  731. },
  732. # Complexarray
  733. {'need': '#ctype#',
  734. '_check': iscomplexarray,
  735. '_depend': ''
  736. },
  737. # Stringarray
  738. {
  739. 'callfortranappend': {isarrayofstrings: 'flen(#varname#),'},
  740. 'need': 'string',
  741. '_check': isstringarray
  742. }
  743. ]
  744. arg_rules = [
  745. {
  746. 'separatorsfor': sepdict
  747. },
  748. { # Common
  749. 'frompyobj': [' /* Processing variable #varname# */',
  750. {debugcapi: ' fprintf(stderr,"#vardebuginfo#\\n");'}, ],
  751. 'cleanupfrompyobj': ' /* End of cleaning variable #varname# */',
  752. '_depend': '',
  753. 'need': typedef_need_dict,
  754. },
  755. # Doc signatures
  756. {
  757. 'docstropt': {l_and(isoptional, isintent_nothide): '#pydocsign#'},
  758. 'docstrreq': {l_and(isrequired, isintent_nothide): '#pydocsign#'},
  759. 'docstrout': {isintent_out: '#pydocsignout#'},
  760. 'latexdocstropt': {l_and(isoptional, isintent_nothide): ['\\item[]{{}\\verb@#pydocsign#@{}}',
  761. {hasnote: '--- #note#'}]},
  762. 'latexdocstrreq': {l_and(isrequired, isintent_nothide): ['\\item[]{{}\\verb@#pydocsign#@{}}',
  763. {hasnote: '--- #note#'}]},
  764. 'latexdocstrout': {isintent_out: ['\\item[]{{}\\verb@#pydocsignout#@{}}',
  765. {l_and(hasnote, isintent_hide): '--- #note#',
  766. l_and(hasnote, isintent_nothide): '--- See above.'}]},
  767. 'depend': ''
  768. },
  769. # Required/Optional arguments
  770. {
  771. 'kwlist': '"#varname#",',
  772. 'docsign': '#varname#,',
  773. '_check': l_and(isintent_nothide, l_not(isoptional))
  774. },
  775. {
  776. 'kwlistopt': '"#varname#",',
  777. 'docsignopt': '#varname#=#showinit#,',
  778. 'docsignoptshort': '#varname#,',
  779. '_check': l_and(isintent_nothide, isoptional)
  780. },
  781. # Docstring/BuildValue
  782. {
  783. 'docreturn': '#outvarname#,',
  784. 'returnformat': '#varrformat#',
  785. '_check': isintent_out
  786. },
  787. # Externals (call-back functions)
  788. { # Common
  789. 'docsignxa': {isintent_nothide: '#varname#_extra_args=(),'},
  790. 'docsignxashort': {isintent_nothide: '#varname#_extra_args,'},
  791. 'docstropt': {isintent_nothide: '#varname#_extra_args : input tuple, optional\\n Default: ()'},
  792. 'docstrcbs': '#cbdocstr#',
  793. 'latexdocstrcbs': '\\item[] #cblatexdocstr#',
  794. 'latexdocstropt': {isintent_nothide: '\\item[]{{}\\verb@#varname#_extra_args := () input tuple@{}} --- Extra arguments for call-back function {{}\\verb@#varname#@{}}.'},
  795. 'decl': [' #cbname#_t #varname#_cb = { Py_None, NULL, 0 };',
  796. ' #cbname#_t *#varname#_cb_ptr = &#varname#_cb;',
  797. ' PyTupleObject *#varname#_xa_capi = NULL;',
  798. {l_not(isintent_callback):
  799. ' #cbname#_typedef #varname#_cptr;'}
  800. ],
  801. 'kwlistxa': {isintent_nothide: '"#varname#_extra_args",'},
  802. 'argformat': {isrequired: 'O'},
  803. 'keyformat': {isoptional: 'O'},
  804. 'xaformat': {isintent_nothide: 'O!'},
  805. 'args_capi': {isrequired: ',&#varname#_cb.capi'},
  806. 'keys_capi': {isoptional: ',&#varname#_cb.capi'},
  807. 'keys_xa': ',&PyTuple_Type,&#varname#_xa_capi',
  808. 'setjmpbuf': '(setjmp(#varname#_cb.jmpbuf))',
  809. 'callfortran': {l_not(isintent_callback): '#varname#_cptr,'},
  810. 'need': ['#cbname#', 'setjmp.h'],
  811. '_check': isexternal
  812. },
  813. {
  814. 'frompyobj': [{l_not(isintent_callback): """\
  815. if(F2PyCapsule_Check(#varname#_cb.capi)) {
  816. #varname#_cptr = F2PyCapsule_AsVoidPtr(#varname#_cb.capi);
  817. } else {
  818. #varname#_cptr = #cbname#;
  819. }
  820. """}, {isintent_callback: """\
  821. if (#varname#_cb.capi==Py_None) {
  822. #varname#_cb.capi = PyObject_GetAttrString(#modulename#_module,\"#varname#\");
  823. if (#varname#_cb.capi) {
  824. if (#varname#_xa_capi==NULL) {
  825. if (PyObject_HasAttrString(#modulename#_module,\"#varname#_extra_args\")) {
  826. PyObject* capi_tmp = PyObject_GetAttrString(#modulename#_module,\"#varname#_extra_args\");
  827. if (capi_tmp) {
  828. #varname#_xa_capi = (PyTupleObject *)PySequence_Tuple(capi_tmp);
  829. Py_DECREF(capi_tmp);
  830. }
  831. else {
  832. #varname#_xa_capi = (PyTupleObject *)Py_BuildValue(\"()\");
  833. }
  834. if (#varname#_xa_capi==NULL) {
  835. PyErr_SetString(#modulename#_error,\"Failed to convert #modulename#.#varname#_extra_args to tuple.\\n\");
  836. return NULL;
  837. }
  838. }
  839. }
  840. }
  841. if (#varname#_cb.capi==NULL) {
  842. PyErr_SetString(#modulename#_error,\"Callback #varname# not defined (as an argument or module #modulename# attribute).\\n\");
  843. return NULL;
  844. }
  845. }
  846. """},
  847. """\
  848. if (create_cb_arglist(#varname#_cb.capi,#varname#_xa_capi,#maxnofargs#,#nofoptargs#,&#varname#_cb.nofargs,&#varname#_cb.args_capi,\"failed in processing argument list for call-back #varname#.\")) {
  849. """,
  850. {debugcapi: ["""\
  851. fprintf(stderr,\"debug-capi:Assuming %d arguments; at most #maxnofargs#(-#nofoptargs#) is expected.\\n\",#varname#_cb.nofargs);
  852. CFUNCSMESSPY(\"for #varname#=\",#varname#_cb.capi);""",
  853. {l_not(isintent_callback): """ fprintf(stderr,\"#vardebugshowvalue# (call-back in C).\\n\",#cbname#);"""}]},
  854. """\
  855. CFUNCSMESS(\"Saving callback variables for `#varname#`.\\n\");
  856. #varname#_cb_ptr = swap_active_#cbname#(#varname#_cb_ptr);""",
  857. ],
  858. 'cleanupfrompyobj':
  859. """\
  860. CFUNCSMESS(\"Restoring callback variables for `#varname#`.\\n\");
  861. #varname#_cb_ptr = swap_active_#cbname#(#varname#_cb_ptr);
  862. Py_DECREF(#varname#_cb.args_capi);
  863. }""",
  864. 'need': ['SWAP', 'create_cb_arglist'],
  865. '_check': isexternal,
  866. '_depend': ''
  867. },
  868. # Scalars (not complex)
  869. { # Common
  870. 'decl': ' #ctype# #varname# = 0;',
  871. 'pyobjfrom': {debugcapi: ' fprintf(stderr,"#vardebugshowvalue#\\n",#varname#);'},
  872. 'callfortran': {l_or(isintent_c, isattr_value): '#varname#,', l_not(l_or(isintent_c, isattr_value)): '&#varname#,'},
  873. 'return': {isintent_out: ',#varname#'},
  874. '_check': l_and(isscalar, l_not(iscomplex))
  875. }, {
  876. 'need': {hasinitvalue: 'math.h'},
  877. '_check': l_and(isscalar, l_not(iscomplex)),
  878. }, { # Not hidden
  879. 'decl': ' PyObject *#varname#_capi = Py_None;',
  880. 'argformat': {isrequired: 'O'},
  881. 'keyformat': {isoptional: 'O'},
  882. 'args_capi': {isrequired: ',&#varname#_capi'},
  883. 'keys_capi': {isoptional: ',&#varname#_capi'},
  884. 'pyobjfrom': {isintent_inout: """\
  885. f2py_success = try_pyarr_from_#ctype#(#varname#_capi,&#varname#);
  886. if (f2py_success) {"""},
  887. 'closepyobjfrom': {isintent_inout: " } /*if (f2py_success) of #varname# pyobjfrom*/"},
  888. 'need': {isintent_inout: 'try_pyarr_from_#ctype#'},
  889. '_check': l_and(isscalar, l_not(iscomplex), l_not(isstring),
  890. isintent_nothide)
  891. }, {
  892. 'frompyobj': [
  893. # hasinitvalue...
  894. # if pyobj is None:
  895. # varname = init
  896. # else
  897. # from_pyobj(varname)
  898. #
  899. # isoptional and noinitvalue...
  900. # if pyobj is not None:
  901. # from_pyobj(varname)
  902. # else:
  903. # varname is uninitialized
  904. #
  905. # ...
  906. # from_pyobj(varname)
  907. #
  908. {hasinitvalue: ' if (#varname#_capi == Py_None) #varname# = #init#; else',
  909. '_depend': ''},
  910. {l_and(isoptional, l_not(hasinitvalue)): ' if (#varname#_capi != Py_None)',
  911. '_depend': ''},
  912. {l_not(islogical): '''\
  913. f2py_success = #ctype#_from_pyobj(&#varname#,#varname#_capi,"#pyname#() #nth# (#varname#) can\'t be converted to #ctype#");
  914. if (f2py_success) {'''},
  915. {islogical: '''\
  916. #varname# = (#ctype#)PyObject_IsTrue(#varname#_capi);
  917. f2py_success = 1;
  918. if (f2py_success) {'''},
  919. ],
  920. 'cleanupfrompyobj': ' } /*if (f2py_success) of #varname#*/',
  921. 'need': {l_not(islogical): '#ctype#_from_pyobj'},
  922. '_check': l_and(isscalar, l_not(iscomplex), isintent_nothide),
  923. '_depend': ''
  924. }, { # Hidden
  925. 'frompyobj': {hasinitvalue: ' #varname# = #init#;'},
  926. 'need': typedef_need_dict,
  927. '_check': l_and(isscalar, l_not(iscomplex), isintent_hide),
  928. '_depend': ''
  929. }, { # Common
  930. 'frompyobj': {debugcapi: ' fprintf(stderr,"#vardebugshowvalue#\\n",#varname#);'},
  931. '_check': l_and(isscalar, l_not(iscomplex)),
  932. '_depend': ''
  933. },
  934. # Complex scalars
  935. { # Common
  936. 'decl': ' #ctype# #varname#;',
  937. 'callfortran': {isintent_c: '#varname#,', l_not(isintent_c): '&#varname#,'},
  938. 'pyobjfrom': {debugcapi: ' fprintf(stderr,"#vardebugshowvalue#\\n",#varname#.r,#varname#.i);'},
  939. 'return': {isintent_out: ',#varname#_capi'},
  940. '_check': iscomplex
  941. }, { # Not hidden
  942. 'decl': ' PyObject *#varname#_capi = Py_None;',
  943. 'argformat': {isrequired: 'O'},
  944. 'keyformat': {isoptional: 'O'},
  945. 'args_capi': {isrequired: ',&#varname#_capi'},
  946. 'keys_capi': {isoptional: ',&#varname#_capi'},
  947. 'need': {isintent_inout: 'try_pyarr_from_#ctype#'},
  948. 'pyobjfrom': {isintent_inout: """\
  949. f2py_success = try_pyarr_from_#ctype#(#varname#_capi,&#varname#);
  950. if (f2py_success) {"""},
  951. 'closepyobjfrom': {isintent_inout: " } /*if (f2py_success) of #varname# pyobjfrom*/"},
  952. '_check': l_and(iscomplex, isintent_nothide)
  953. }, {
  954. 'frompyobj': [{hasinitvalue: ' if (#varname#_capi==Py_None) {#varname#.r = #init.r#, #varname#.i = #init.i#;} else'},
  955. {l_and(isoptional, l_not(hasinitvalue))
  956. : ' if (#varname#_capi != Py_None)'},
  957. ' f2py_success = #ctype#_from_pyobj(&#varname#,#varname#_capi,"#pyname#() #nth# (#varname#) can\'t be converted to #ctype#");'
  958. '\n if (f2py_success) {'],
  959. 'cleanupfrompyobj': ' } /*if (f2py_success) of #varname# frompyobj*/',
  960. 'need': ['#ctype#_from_pyobj'],
  961. '_check': l_and(iscomplex, isintent_nothide),
  962. '_depend': ''
  963. }, { # Hidden
  964. 'decl': {isintent_out: ' PyObject *#varname#_capi = Py_None;'},
  965. '_check': l_and(iscomplex, isintent_hide)
  966. }, {
  967. 'frompyobj': {hasinitvalue: ' #varname#.r = #init.r#, #varname#.i = #init.i#;'},
  968. '_check': l_and(iscomplex, isintent_hide),
  969. '_depend': ''
  970. }, { # Common
  971. 'pyobjfrom': {isintent_out: ' #varname#_capi = pyobj_from_#ctype#1(#varname#);'},
  972. 'need': ['pyobj_from_#ctype#1'],
  973. '_check': iscomplex
  974. }, {
  975. 'frompyobj': {debugcapi: ' fprintf(stderr,"#vardebugshowvalue#\\n",#varname#.r,#varname#.i);'},
  976. '_check': iscomplex,
  977. '_depend': ''
  978. },
  979. # String
  980. { # Common
  981. 'decl': [' #ctype# #varname# = NULL;',
  982. ' int slen(#varname#);',
  983. ' PyObject *#varname#_capi = Py_None;'],
  984. 'callfortran': '#varname#,',
  985. 'callfortranappend': 'slen(#varname#),',
  986. 'pyobjfrom': [
  987. {debugcapi:
  988. ' fprintf(stderr,'
  989. '"#vardebugshowvalue#\\n",slen(#varname#),#varname#);'},
  990. # The trailing null value for Fortran is blank.
  991. {l_and(isintent_out, l_not(isintent_c)):
  992. " STRINGPADN(#varname#, slen(#varname#), ' ', '\\0');"},
  993. ],
  994. 'return': {isintent_out: ',#varname#'},
  995. 'need': ['len..',
  996. {l_and(isintent_out, l_not(isintent_c)): 'STRINGPADN'}],
  997. '_check': isstring
  998. }, { # Common
  999. 'frompyobj': [
  1000. """\
  1001. slen(#varname#) = #elsize#;
  1002. f2py_success = #ctype#_from_pyobj(&#varname#,&slen(#varname#),#init#,"""
  1003. """#varname#_capi,\"#ctype#_from_pyobj failed in converting #nth#"""
  1004. """`#varname#\' of #pyname# to C #ctype#\");
  1005. if (f2py_success) {""",
  1006. # The trailing null value for Fortran is blank.
  1007. {l_not(isintent_c):
  1008. " STRINGPADN(#varname#, slen(#varname#), '\\0', ' ');"},
  1009. ],
  1010. 'cleanupfrompyobj': """\
  1011. STRINGFREE(#varname#);
  1012. } /*if (f2py_success) of #varname#*/""",
  1013. 'need': ['#ctype#_from_pyobj', 'len..', 'STRINGFREE',
  1014. {l_not(isintent_c): 'STRINGPADN'}],
  1015. '_check': isstring,
  1016. '_depend': ''
  1017. }, { # Not hidden
  1018. 'argformat': {isrequired: 'O'},
  1019. 'keyformat': {isoptional: 'O'},
  1020. 'args_capi': {isrequired: ',&#varname#_capi'},
  1021. 'keys_capi': {isoptional: ',&#varname#_capi'},
  1022. 'pyobjfrom': [
  1023. {l_and(isintent_inout, l_not(isintent_c)):
  1024. " STRINGPADN(#varname#, slen(#varname#), ' ', '\\0');"},
  1025. {isintent_inout: '''\
  1026. f2py_success = try_pyarr_from_#ctype#(#varname#_capi, #varname#,
  1027. slen(#varname#));
  1028. if (f2py_success) {'''}],
  1029. 'closepyobjfrom': {isintent_inout: ' } /*if (f2py_success) of #varname# pyobjfrom*/'},
  1030. 'need': {isintent_inout: 'try_pyarr_from_#ctype#',
  1031. l_and(isintent_inout, l_not(isintent_c)): 'STRINGPADN'},
  1032. '_check': l_and(isstring, isintent_nothide)
  1033. }, { # Hidden
  1034. '_check': l_and(isstring, isintent_hide)
  1035. }, {
  1036. 'frompyobj': {debugcapi: ' fprintf(stderr,"#vardebugshowvalue#\\n",slen(#varname#),#varname#);'},
  1037. '_check': isstring,
  1038. '_depend': ''
  1039. },
  1040. # Array
  1041. { # Common
  1042. 'decl': [' #ctype# *#varname# = NULL;',
  1043. ' npy_intp #varname#_Dims[#rank#] = {#rank*[-1]#};',
  1044. ' const int #varname#_Rank = #rank#;',
  1045. ' PyArrayObject *capi_#varname#_as_array = NULL;',
  1046. ' int capi_#varname#_intent = 0;',
  1047. {isstringarray: ' int slen(#varname#) = 0;'},
  1048. ],
  1049. 'callfortran': '#varname#,',
  1050. 'callfortranappend': {isstringarray: 'slen(#varname#),'},
  1051. 'return': {isintent_out: ',capi_#varname#_as_array'},
  1052. 'need': 'len..',
  1053. '_check': isarray
  1054. }, { # intent(overwrite) array
  1055. 'decl': ' int capi_overwrite_#varname# = 1;',
  1056. 'kwlistxa': '"overwrite_#varname#",',
  1057. 'xaformat': 'i',
  1058. 'keys_xa': ',&capi_overwrite_#varname#',
  1059. 'docsignxa': 'overwrite_#varname#=1,',
  1060. 'docsignxashort': 'overwrite_#varname#,',
  1061. 'docstropt': 'overwrite_#varname# : input int, optional\\n Default: 1',
  1062. '_check': l_and(isarray, isintent_overwrite),
  1063. }, {
  1064. 'frompyobj': ' capi_#varname#_intent |= (capi_overwrite_#varname#?0:F2PY_INTENT_COPY);',
  1065. '_check': l_and(isarray, isintent_overwrite),
  1066. '_depend': '',
  1067. },
  1068. { # intent(copy) array
  1069. 'decl': ' int capi_overwrite_#varname# = 0;',
  1070. 'kwlistxa': '"overwrite_#varname#",',
  1071. 'xaformat': 'i',
  1072. 'keys_xa': ',&capi_overwrite_#varname#',
  1073. 'docsignxa': 'overwrite_#varname#=0,',
  1074. 'docsignxashort': 'overwrite_#varname#,',
  1075. 'docstropt': 'overwrite_#varname# : input int, optional\\n Default: 0',
  1076. '_check': l_and(isarray, isintent_copy),
  1077. }, {
  1078. 'frompyobj': ' capi_#varname#_intent |= (capi_overwrite_#varname#?0:F2PY_INTENT_COPY);',
  1079. '_check': l_and(isarray, isintent_copy),
  1080. '_depend': '',
  1081. }, {
  1082. 'need': [{hasinitvalue: 'forcomb'}, {hasinitvalue: 'CFUNCSMESS'}],
  1083. '_check': isarray,
  1084. '_depend': ''
  1085. }, { # Not hidden
  1086. 'decl': ' PyObject *#varname#_capi = Py_None;',
  1087. 'argformat': {isrequired: 'O'},
  1088. 'keyformat': {isoptional: 'O'},
  1089. 'args_capi': {isrequired: ',&#varname#_capi'},
  1090. 'keys_capi': {isoptional: ',&#varname#_capi'},
  1091. '_check': l_and(isarray, isintent_nothide)
  1092. }, {
  1093. 'frompyobj': [
  1094. ' #setdims#;',
  1095. ' capi_#varname#_intent |= #intent#;',
  1096. (' const char capi_errmess[] = "#modulename#.#pyname#:'
  1097. ' failed to create array from the #nth# `#varname#`";'),
  1098. {isintent_hide:
  1099. ' capi_#varname#_as_array = ndarray_from_pyobj('
  1100. ' #atype#,#elsize#,#varname#_Dims,#varname#_Rank,'
  1101. ' capi_#varname#_intent,Py_None,capi_errmess);'},
  1102. {isintent_nothide:
  1103. ' capi_#varname#_as_array = ndarray_from_pyobj('
  1104. ' #atype#,#elsize#,#varname#_Dims,#varname#_Rank,'
  1105. ' capi_#varname#_intent,#varname#_capi,capi_errmess);'},
  1106. """\
  1107. if (capi_#varname#_as_array == NULL) {
  1108. PyObject* capi_err = PyErr_Occurred();
  1109. if (capi_err == NULL) {
  1110. capi_err = #modulename#_error;
  1111. PyErr_SetString(capi_err, capi_errmess);
  1112. }
  1113. } else {
  1114. #varname# = (#ctype# *)(PyArray_DATA(capi_#varname#_as_array));
  1115. """,
  1116. {isstringarray:
  1117. ' slen(#varname#) = f2py_itemsize(#varname#);'},
  1118. {hasinitvalue: [
  1119. {isintent_nothide:
  1120. ' if (#varname#_capi == Py_None) {'},
  1121. {isintent_hide: ' {'},
  1122. {iscomplexarray: ' #ctype# capi_c;'},
  1123. """\
  1124. int *_i,capi_i=0;
  1125. CFUNCSMESS(\"#name#: Initializing #varname#=#init#\\n\");
  1126. struct ForcombCache cache;
  1127. if (initforcomb(&cache, PyArray_DIMS(capi_#varname#_as_array),
  1128. PyArray_NDIM(capi_#varname#_as_array),1)) {
  1129. while ((_i = nextforcomb(&cache)))
  1130. #varname#[capi_i++] = #init#; /* fortran way */
  1131. } else {
  1132. PyObject *exc, *val, *tb;
  1133. PyErr_Fetch(&exc, &val, &tb);
  1134. PyErr_SetString(exc ? exc : #modulename#_error,
  1135. \"Initialization of #nth# #varname# failed (initforcomb).\");
  1136. npy_PyErr_ChainExceptionsCause(exc, val, tb);
  1137. f2py_success = 0;
  1138. }
  1139. }
  1140. if (f2py_success) {"""]},
  1141. ],
  1142. 'cleanupfrompyobj': [ # note that this list will be reversed
  1143. ' } '
  1144. '/* if (capi_#varname#_as_array == NULL) ... else of #varname# */',
  1145. {l_not(l_or(isintent_out, isintent_hide)): """\
  1146. if((PyObject *)capi_#varname#_as_array!=#varname#_capi) {
  1147. Py_XDECREF(capi_#varname#_as_array); }"""},
  1148. {l_and(isintent_hide, l_not(isintent_out))
  1149. : """ Py_XDECREF(capi_#varname#_as_array);"""},
  1150. {hasinitvalue: ' } /*if (f2py_success) of #varname# init*/'},
  1151. ],
  1152. '_check': isarray,
  1153. '_depend': ''
  1154. },
  1155. # Scalararray
  1156. { # Common
  1157. '_check': l_and(isarray, l_not(iscomplexarray))
  1158. }, { # Not hidden
  1159. '_check': l_and(isarray, l_not(iscomplexarray), isintent_nothide)
  1160. },
  1161. # Integer*1 array
  1162. {'need': '#ctype#',
  1163. '_check': isint1array,
  1164. '_depend': ''
  1165. },
  1166. # Integer*-1 array
  1167. {'need': '#ctype#',
  1168. '_check': isunsigned_chararray,
  1169. '_depend': ''
  1170. },
  1171. # Integer*-2 array
  1172. {'need': '#ctype#',
  1173. '_check': isunsigned_shortarray,
  1174. '_depend': ''
  1175. },
  1176. # Integer*-8 array
  1177. {'need': '#ctype#',
  1178. '_check': isunsigned_long_longarray,
  1179. '_depend': ''
  1180. },
  1181. # Complexarray
  1182. {'need': '#ctype#',
  1183. '_check': iscomplexarray,
  1184. '_depend': ''
  1185. },
  1186. # Character
  1187. {
  1188. 'need': 'string',
  1189. '_check': ischaracter,
  1190. },
  1191. # Character array
  1192. {
  1193. 'need': 'string',
  1194. '_check': ischaracterarray,
  1195. },
  1196. # Stringarray
  1197. {
  1198. 'callfortranappend': {isarrayofstrings: 'flen(#varname#),'},
  1199. 'need': 'string',
  1200. '_check': isstringarray
  1201. }
  1202. ]
  1203. ################# Rules for checking ###############
  1204. check_rules = [
  1205. {
  1206. 'frompyobj': {debugcapi: ' fprintf(stderr,\"debug-capi:Checking `#check#\'\\n\");'},
  1207. 'need': 'len..'
  1208. }, {
  1209. 'frompyobj': ' CHECKSCALAR(#check#,\"#check#\",\"#nth# #varname#\",\"#varshowvalue#\",#varname#) {',
  1210. 'cleanupfrompyobj': ' } /*CHECKSCALAR(#check#)*/',
  1211. 'need': 'CHECKSCALAR',
  1212. '_check': l_and(isscalar, l_not(iscomplex)),
  1213. '_break': ''
  1214. }, {
  1215. 'frompyobj': ' CHECKSTRING(#check#,\"#check#\",\"#nth# #varname#\",\"#varshowvalue#\",#varname#) {',
  1216. 'cleanupfrompyobj': ' } /*CHECKSTRING(#check#)*/',
  1217. 'need': 'CHECKSTRING',
  1218. '_check': isstring,
  1219. '_break': ''
  1220. }, {
  1221. 'need': 'CHECKARRAY',
  1222. 'frompyobj': ' CHECKARRAY(#check#,\"#check#\",\"#nth# #varname#\") {',
  1223. 'cleanupfrompyobj': ' } /*CHECKARRAY(#check#)*/',
  1224. '_check': isarray,
  1225. '_break': ''
  1226. }, {
  1227. 'need': 'CHECKGENERIC',
  1228. 'frompyobj': ' CHECKGENERIC(#check#,\"#check#\",\"#nth# #varname#\") {',
  1229. 'cleanupfrompyobj': ' } /*CHECKGENERIC(#check#)*/',
  1230. }
  1231. ]
  1232. ########## Applying the rules. No need to modify what follows #############
  1233. #################### Build C/API module #######################
  1234. def buildmodule(m, um):
  1235. """
  1236. Return
  1237. """
  1238. outmess(f" Building module \"{m['name']}\"...\n")
  1239. ret = {}
  1240. mod_rules = defmod_rules[:]
  1241. vrd = capi_maps.modsign2map(m)
  1242. rd = dictappend({'f2py_version': f2py_version}, vrd)
  1243. funcwrappers = []
  1244. funcwrappers2 = [] # F90 codes
  1245. for n in m['interfaced']:
  1246. nb = None
  1247. for bi in m['body']:
  1248. if bi['block'] not in ['interface', 'abstract interface']:
  1249. errmess('buildmodule: Expected interface block. Skipping.\n')
  1250. continue
  1251. for b in bi['body']:
  1252. if b['name'] == n:
  1253. nb = b
  1254. break
  1255. if not nb:
  1256. print(
  1257. f'buildmodule: Could not find the body of interfaced routine "{n}". Skipping.\n', file=sys.stderr)
  1258. continue
  1259. nb_list = [nb]
  1260. if 'entry' in nb:
  1261. for k, a in nb['entry'].items():
  1262. nb1 = copy.deepcopy(nb)
  1263. del nb1['entry']
  1264. nb1['name'] = k
  1265. nb1['args'] = a
  1266. nb_list.append(nb1)
  1267. for nb in nb_list:
  1268. # requiresf90wrapper must be called before buildapi as it
  1269. # rewrites assumed shape arrays as automatic arrays.
  1270. isf90 = requiresf90wrapper(nb)
  1271. # options is in scope here
  1272. if options['emptygen']:
  1273. b_path = options['buildpath']
  1274. m_name = vrd['modulename']
  1275. outmess(' Generating possibly empty wrappers"\n')
  1276. Path(f"{b_path}/{vrd['coutput']}").touch()
  1277. if isf90:
  1278. # f77 + f90 wrappers
  1279. outmess(f' Maybe empty "{m_name}-f2pywrappers2.f90"\n')
  1280. Path(f'{b_path}/{m_name}-f2pywrappers2.f90').touch()
  1281. outmess(f' Maybe empty "{m_name}-f2pywrappers.f"\n')
  1282. Path(f'{b_path}/{m_name}-f2pywrappers.f').touch()
  1283. else:
  1284. # only f77 wrappers
  1285. outmess(f' Maybe empty "{m_name}-f2pywrappers.f"\n')
  1286. Path(f'{b_path}/{m_name}-f2pywrappers.f').touch()
  1287. api, wrap = buildapi(nb)
  1288. if wrap:
  1289. if isf90:
  1290. funcwrappers2.append(wrap)
  1291. else:
  1292. funcwrappers.append(wrap)
  1293. ar = applyrules(api, vrd)
  1294. rd = dictappend(rd, ar)
  1295. # Construct COMMON block support
  1296. cr, wrap = common_rules.buildhooks(m)
  1297. if wrap:
  1298. funcwrappers.append(wrap)
  1299. ar = applyrules(cr, vrd)
  1300. rd = dictappend(rd, ar)
  1301. # Construct F90 module support
  1302. mr, wrap = f90mod_rules.buildhooks(m)
  1303. if wrap:
  1304. funcwrappers2.append(wrap)
  1305. ar = applyrules(mr, vrd)
  1306. rd = dictappend(rd, ar)
  1307. for u in um:
  1308. ar = use_rules.buildusevars(u, m['use'][u['name']])
  1309. rd = dictappend(rd, ar)
  1310. needs = cfuncs.get_needs()
  1311. # Add mapped definitions
  1312. needs['typedefs'] += [cvar for cvar in capi_maps.f2cmap_mapped #
  1313. if cvar in typedef_need_dict.values()]
  1314. code = {}
  1315. for n in needs.keys():
  1316. code[n] = []
  1317. for k in needs[n]:
  1318. c = ''
  1319. if k in cfuncs.includes0:
  1320. c = cfuncs.includes0[k]
  1321. elif k in cfuncs.includes:
  1322. c = cfuncs.includes[k]
  1323. elif k in cfuncs.userincludes:
  1324. c = cfuncs.userincludes[k]
  1325. elif k in cfuncs.typedefs:
  1326. c = cfuncs.typedefs[k]
  1327. elif k in cfuncs.typedefs_generated:
  1328. c = cfuncs.typedefs_generated[k]
  1329. elif k in cfuncs.cppmacros:
  1330. c = cfuncs.cppmacros[k]
  1331. elif k in cfuncs.cfuncs:
  1332. c = cfuncs.cfuncs[k]
  1333. elif k in cfuncs.callbacks:
  1334. c = cfuncs.callbacks[k]
  1335. elif k in cfuncs.f90modhooks:
  1336. c = cfuncs.f90modhooks[k]
  1337. elif k in cfuncs.commonhooks:
  1338. c = cfuncs.commonhooks[k]
  1339. else:
  1340. errmess(f'buildmodule: unknown need {repr(k)}.\n')
  1341. continue
  1342. code[n].append(c)
  1343. mod_rules.append(code)
  1344. for r in mod_rules:
  1345. if ('_check' in r and r['_check'](m)) or ('_check' not in r):
  1346. ar = applyrules(r, vrd, m)
  1347. rd = dictappend(rd, ar)
  1348. ar = applyrules(module_rules, rd)
  1349. fn = os.path.join(options['buildpath'], vrd['coutput'])
  1350. ret['csrc'] = fn
  1351. with open(fn, 'w') as f:
  1352. f.write(ar['modulebody'].replace('\t', 2 * ' '))
  1353. outmess(f" Wrote C/API module \"{m['name']}\" to file \"{fn}\"\n")
  1354. if options['dorestdoc']:
  1355. fn = os.path.join(
  1356. options['buildpath'], vrd['modulename'] + 'module.rest')
  1357. with open(fn, 'w') as f:
  1358. f.write('.. -*- rest -*-\n')
  1359. f.write('\n'.join(ar['restdoc']))
  1360. outmess(' ReST Documentation is saved to file "%s/%smodule.rest"\n' %
  1361. (options['buildpath'], vrd['modulename']))
  1362. if options['dolatexdoc']:
  1363. fn = os.path.join(
  1364. options['buildpath'], vrd['modulename'] + 'module.tex')
  1365. ret['ltx'] = fn
  1366. with open(fn, 'w') as f:
  1367. f.write(
  1368. f'% This file is auto-generated with f2py (version:{f2py_version})\n')
  1369. if 'shortlatex' not in options:
  1370. f.write(
  1371. '\\documentclass{article}\n\\usepackage{a4wide}\n\\begin{document}\n\\tableofcontents\n\n')
  1372. f.write('\n'.join(ar['latexdoc']))
  1373. if 'shortlatex' not in options:
  1374. f.write('\\end{document}')
  1375. outmess(' Documentation is saved to file "%s/%smodule.tex"\n' %
  1376. (options['buildpath'], vrd['modulename']))
  1377. if funcwrappers:
  1378. wn = os.path.join(options['buildpath'], vrd['f2py_wrapper_output'])
  1379. ret['fsrc'] = wn
  1380. with open(wn, 'w') as f:
  1381. f.write('C -*- fortran -*-\n')
  1382. f.write(
  1383. f'C This file is autogenerated with f2py (version:{f2py_version})\n')
  1384. f.write(
  1385. 'C It contains Fortran 77 wrappers to fortran functions.\n')
  1386. lines = []
  1387. for l in ('\n\n'.join(funcwrappers) + '\n').split('\n'):
  1388. if 0 <= l.find('!') < 66:
  1389. # don't split comment lines
  1390. lines.append(l + '\n')
  1391. elif l and l[0] == ' ':
  1392. while len(l) >= 66:
  1393. lines.append(l[:66] + '\n &')
  1394. l = l[66:]
  1395. lines.append(l + '\n')
  1396. else:
  1397. lines.append(l + '\n')
  1398. lines = ''.join(lines).replace('\n &\n', '\n')
  1399. f.write(lines)
  1400. outmess(f' Fortran 77 wrappers are saved to "{wn}\"\n')
  1401. if funcwrappers2:
  1402. wn = os.path.join(
  1403. options['buildpath'], f"{vrd['modulename']}-f2pywrappers2.f90")
  1404. ret['fsrc'] = wn
  1405. with open(wn, 'w') as f:
  1406. f.write('! -*- f90 -*-\n')
  1407. f.write(
  1408. f'! This file is autogenerated with f2py (version:{f2py_version})\n')
  1409. f.write(
  1410. '! It contains Fortran 90 wrappers to fortran functions.\n')
  1411. lines = []
  1412. for l in ('\n\n'.join(funcwrappers2) + '\n').split('\n'):
  1413. if 0 <= l.find('!') < 72:
  1414. # don't split comment lines
  1415. lines.append(l + '\n')
  1416. elif len(l) > 72 and l[0] == ' ':
  1417. lines.append(l[:72] + '&\n &')
  1418. l = l[72:]
  1419. while len(l) > 66:
  1420. lines.append(l[:66] + '&\n &')
  1421. l = l[66:]
  1422. lines.append(l + '\n')
  1423. else:
  1424. lines.append(l + '\n')
  1425. lines = ''.join(lines).replace('\n &\n', '\n')
  1426. f.write(lines)
  1427. outmess(f' Fortran 90 wrappers are saved to "{wn}\"\n')
  1428. return ret
  1429. ################## Build C/API function #############
  1430. stnd = {1: 'st', 2: 'nd', 3: 'rd', 4: 'th', 5: 'th',
  1431. 6: 'th', 7: 'th', 8: 'th', 9: 'th', 0: 'th'}
  1432. def buildapi(rout):
  1433. rout, wrap = func2subr.assubr(rout)
  1434. args, depargs = getargs2(rout)
  1435. capi_maps.depargs = depargs
  1436. var = rout['vars']
  1437. if ismoduleroutine(rout):
  1438. outmess(' Constructing wrapper function "%s.%s"...\n' %
  1439. (rout['modulename'], rout['name']))
  1440. else:
  1441. outmess(f" Constructing wrapper function \"{rout['name']}\"...\n")
  1442. # Routine
  1443. vrd = capi_maps.routsign2map(rout)
  1444. rd = dictappend({}, vrd)
  1445. for r in rout_rules:
  1446. if ('_check' in r and r['_check'](rout)) or ('_check' not in r):
  1447. ar = applyrules(r, vrd, rout)
  1448. rd = dictappend(rd, ar)
  1449. # Args
  1450. nth, nthk = 0, 0
  1451. savevrd = {}
  1452. for a in args:
  1453. vrd = capi_maps.sign2map(a, var[a])
  1454. if isintent_aux(var[a]):
  1455. _rules = aux_rules
  1456. else:
  1457. _rules = arg_rules
  1458. if not isintent_hide(var[a]):
  1459. if not isoptional(var[a]):
  1460. nth = nth + 1
  1461. vrd['nth'] = repr(nth) + stnd[nth % 10] + ' argument'
  1462. else:
  1463. nthk = nthk + 1
  1464. vrd['nth'] = repr(nthk) + stnd[nthk % 10] + ' keyword'
  1465. else:
  1466. vrd['nth'] = 'hidden'
  1467. savevrd[a] = vrd
  1468. for r in _rules:
  1469. if '_depend' in r:
  1470. continue
  1471. if ('_check' in r and r['_check'](var[a])) or ('_check' not in r):
  1472. ar = applyrules(r, vrd, var[a])
  1473. rd = dictappend(rd, ar)
  1474. if '_break' in r:
  1475. break
  1476. for a in depargs:
  1477. if isintent_aux(var[a]):
  1478. _rules = aux_rules
  1479. else:
  1480. _rules = arg_rules
  1481. vrd = savevrd[a]
  1482. for r in _rules:
  1483. if '_depend' not in r:
  1484. continue
  1485. if ('_check' in r and r['_check'](var[a])) or ('_check' not in r):
  1486. ar = applyrules(r, vrd, var[a])
  1487. rd = dictappend(rd, ar)
  1488. if '_break' in r:
  1489. break
  1490. if 'check' in var[a]:
  1491. for c in var[a]['check']:
  1492. vrd['check'] = c
  1493. ar = applyrules(check_rules, vrd, var[a])
  1494. rd = dictappend(rd, ar)
  1495. if isinstance(rd['cleanupfrompyobj'], list):
  1496. rd['cleanupfrompyobj'].reverse()
  1497. if isinstance(rd['closepyobjfrom'], list):
  1498. rd['closepyobjfrom'].reverse()
  1499. rd['docsignature'] = stripcomma(replace('#docsign##docsignopt##docsignxa#',
  1500. {'docsign': rd['docsign'],
  1501. 'docsignopt': rd['docsignopt'],
  1502. 'docsignxa': rd['docsignxa']}))
  1503. optargs = stripcomma(replace('#docsignopt##docsignxa#',
  1504. {'docsignxa': rd['docsignxashort'],
  1505. 'docsignopt': rd['docsignoptshort']}
  1506. ))
  1507. if optargs == '':
  1508. rd['docsignatureshort'] = stripcomma(
  1509. replace('#docsign#', {'docsign': rd['docsign']}))
  1510. else:
  1511. rd['docsignatureshort'] = replace('#docsign#[#docsignopt#]',
  1512. {'docsign': rd['docsign'],
  1513. 'docsignopt': optargs,
  1514. })
  1515. rd['latexdocsignatureshort'] = rd['docsignatureshort'].replace('_', '\\_')
  1516. rd['latexdocsignatureshort'] = rd[
  1517. 'latexdocsignatureshort'].replace(',', ', ')
  1518. cfs = stripcomma(replace('#callfortran##callfortranappend#', {
  1519. 'callfortran': rd['callfortran'], 'callfortranappend': rd['callfortranappend']}))
  1520. if len(rd['callfortranappend']) > 1:
  1521. rd['callcompaqfortran'] = stripcomma(replace('#callfortran# 0,#callfortranappend#', {
  1522. 'callfortran': rd['callfortran'], 'callfortranappend': rd['callfortranappend']}))
  1523. else:
  1524. rd['callcompaqfortran'] = cfs
  1525. rd['callfortran'] = cfs
  1526. if isinstance(rd['docreturn'], list):
  1527. rd['docreturn'] = stripcomma(
  1528. replace('#docreturn#', {'docreturn': rd['docreturn']})) + ' = '
  1529. rd['docstrsigns'] = []
  1530. rd['latexdocstrsigns'] = []
  1531. for k in ['docstrreq', 'docstropt', 'docstrout', 'docstrcbs']:
  1532. if k in rd and isinstance(rd[k], list):
  1533. rd['docstrsigns'] = rd['docstrsigns'] + rd[k]
  1534. k = 'latex' + k
  1535. if k in rd and isinstance(rd[k], list):
  1536. rd['latexdocstrsigns'] = rd['latexdocstrsigns'] + rd[k][0:1] +\
  1537. ['\\begin{description}'] + rd[k][1:] +\
  1538. ['\\end{description}']
  1539. ar = applyrules(routine_rules, rd)
  1540. if ismoduleroutine(rout):
  1541. outmess(f" {ar['docshort']}\n")
  1542. else:
  1543. outmess(f" {ar['docshort']}\n")
  1544. return ar, wrap
  1545. #################### EOF rules.py #######################