capi_maps.py 30 KB

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