capi_maps.py 31 KB

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