recompiler.py 63 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579
  1. import os, sys, io
  2. from . import ffiplatform, model
  3. from .error import VerificationError
  4. from .cffi_opcode import *
  5. VERSION_BASE = 0x2601
  6. VERSION_EMBEDDED = 0x2701
  7. VERSION_CHAR16CHAR32 = 0x2801
  8. USE_LIMITED_API = (sys.platform != 'win32' or sys.version_info < (3, 0) or
  9. sys.version_info >= (3, 5))
  10. class GlobalExpr:
  11. def __init__(self, name, address, type_op, size=0, check_value=0):
  12. self.name = name
  13. self.address = address
  14. self.type_op = type_op
  15. self.size = size
  16. self.check_value = check_value
  17. def as_c_expr(self):
  18. return ' { "%s", (void *)%s, %s, (void *)%s },' % (
  19. self.name, self.address, self.type_op.as_c_expr(), self.size)
  20. def as_python_expr(self):
  21. return "b'%s%s',%d" % (self.type_op.as_python_bytes(), self.name,
  22. self.check_value)
  23. class FieldExpr:
  24. def __init__(self, name, field_offset, field_size, fbitsize, field_type_op):
  25. self.name = name
  26. self.field_offset = field_offset
  27. self.field_size = field_size
  28. self.fbitsize = fbitsize
  29. self.field_type_op = field_type_op
  30. def as_c_expr(self):
  31. spaces = " " * len(self.name)
  32. return (' { "%s", %s,\n' % (self.name, self.field_offset) +
  33. ' %s %s,\n' % (spaces, self.field_size) +
  34. ' %s %s },' % (spaces, self.field_type_op.as_c_expr()))
  35. def as_python_expr(self):
  36. raise NotImplementedError
  37. def as_field_python_expr(self):
  38. if self.field_type_op.op == OP_NOOP:
  39. size_expr = ''
  40. elif self.field_type_op.op == OP_BITFIELD:
  41. size_expr = format_four_bytes(self.fbitsize)
  42. else:
  43. raise NotImplementedError
  44. return "b'%s%s%s'" % (self.field_type_op.as_python_bytes(),
  45. size_expr,
  46. self.name)
  47. class StructUnionExpr:
  48. def __init__(self, name, type_index, flags, size, alignment, comment,
  49. first_field_index, c_fields):
  50. self.name = name
  51. self.type_index = type_index
  52. self.flags = flags
  53. self.size = size
  54. self.alignment = alignment
  55. self.comment = comment
  56. self.first_field_index = first_field_index
  57. self.c_fields = c_fields
  58. def as_c_expr(self):
  59. return (' { "%s", %d, %s,' % (self.name, self.type_index, self.flags)
  60. + '\n %s, %s, ' % (self.size, self.alignment)
  61. + '%d, %d ' % (self.first_field_index, len(self.c_fields))
  62. + ('/* %s */ ' % self.comment if self.comment else '')
  63. + '},')
  64. def as_python_expr(self):
  65. flags = eval(self.flags, G_FLAGS)
  66. fields_expr = [c_field.as_field_python_expr()
  67. for c_field in self.c_fields]
  68. return "(b'%s%s%s',%s)" % (
  69. format_four_bytes(self.type_index),
  70. format_four_bytes(flags),
  71. self.name,
  72. ','.join(fields_expr))
  73. class EnumExpr:
  74. def __init__(self, name, type_index, size, signed, allenums):
  75. self.name = name
  76. self.type_index = type_index
  77. self.size = size
  78. self.signed = signed
  79. self.allenums = allenums
  80. def as_c_expr(self):
  81. return (' { "%s", %d, _cffi_prim_int(%s, %s),\n'
  82. ' "%s" },' % (self.name, self.type_index,
  83. self.size, self.signed, self.allenums))
  84. def as_python_expr(self):
  85. prim_index = {
  86. (1, 0): PRIM_UINT8, (1, 1): PRIM_INT8,
  87. (2, 0): PRIM_UINT16, (2, 1): PRIM_INT16,
  88. (4, 0): PRIM_UINT32, (4, 1): PRIM_INT32,
  89. (8, 0): PRIM_UINT64, (8, 1): PRIM_INT64,
  90. }[self.size, self.signed]
  91. return "b'%s%s%s\\x00%s'" % (format_four_bytes(self.type_index),
  92. format_four_bytes(prim_index),
  93. self.name, self.allenums)
  94. class TypenameExpr:
  95. def __init__(self, name, type_index):
  96. self.name = name
  97. self.type_index = type_index
  98. def as_c_expr(self):
  99. return ' { "%s", %d },' % (self.name, self.type_index)
  100. def as_python_expr(self):
  101. return "b'%s%s'" % (format_four_bytes(self.type_index), self.name)
  102. # ____________________________________________________________
  103. class Recompiler:
  104. _num_externpy = 0
  105. def __init__(self, ffi, module_name, target_is_python=False):
  106. self.ffi = ffi
  107. self.module_name = module_name
  108. self.target_is_python = target_is_python
  109. self._version = VERSION_BASE
  110. def needs_version(self, ver):
  111. self._version = max(self._version, ver)
  112. def collect_type_table(self):
  113. self._typesdict = {}
  114. self._generate("collecttype")
  115. #
  116. all_decls = sorted(self._typesdict, key=str)
  117. #
  118. # prepare all FUNCTION bytecode sequences first
  119. self.cffi_types = []
  120. for tp in all_decls:
  121. if tp.is_raw_function:
  122. assert self._typesdict[tp] is None
  123. self._typesdict[tp] = len(self.cffi_types)
  124. self.cffi_types.append(tp) # placeholder
  125. for tp1 in tp.args:
  126. assert isinstance(tp1, (model.VoidType,
  127. model.BasePrimitiveType,
  128. model.PointerType,
  129. model.StructOrUnionOrEnum,
  130. model.FunctionPtrType))
  131. if self._typesdict[tp1] is None:
  132. self._typesdict[tp1] = len(self.cffi_types)
  133. self.cffi_types.append(tp1) # placeholder
  134. self.cffi_types.append('END') # placeholder
  135. #
  136. # prepare all OTHER bytecode sequences
  137. for tp in all_decls:
  138. if not tp.is_raw_function and self._typesdict[tp] is None:
  139. self._typesdict[tp] = len(self.cffi_types)
  140. self.cffi_types.append(tp) # placeholder
  141. if tp.is_array_type and tp.length is not None:
  142. self.cffi_types.append('LEN') # placeholder
  143. assert None not in self._typesdict.values()
  144. #
  145. # collect all structs and unions and enums
  146. self._struct_unions = {}
  147. self._enums = {}
  148. for tp in all_decls:
  149. if isinstance(tp, model.StructOrUnion):
  150. self._struct_unions[tp] = None
  151. elif isinstance(tp, model.EnumType):
  152. self._enums[tp] = None
  153. for i, tp in enumerate(sorted(self._struct_unions,
  154. key=lambda tp: tp.name)):
  155. self._struct_unions[tp] = i
  156. for i, tp in enumerate(sorted(self._enums,
  157. key=lambda tp: tp.name)):
  158. self._enums[tp] = i
  159. #
  160. # emit all bytecode sequences now
  161. for tp in all_decls:
  162. method = getattr(self, '_emit_bytecode_' + tp.__class__.__name__)
  163. method(tp, self._typesdict[tp])
  164. #
  165. # consistency check
  166. for op in self.cffi_types:
  167. assert isinstance(op, CffiOp)
  168. self.cffi_types = tuple(self.cffi_types) # don't change any more
  169. def _enum_fields(self, tp):
  170. # When producing C, expand all anonymous struct/union fields.
  171. # That's necessary to have C code checking the offsets of the
  172. # individual fields contained in them. When producing Python,
  173. # don't do it and instead write it like it is, with the
  174. # corresponding fields having an empty name. Empty names are
  175. # recognized at runtime when we import the generated Python
  176. # file.
  177. expand_anonymous_struct_union = not self.target_is_python
  178. return tp.enumfields(expand_anonymous_struct_union)
  179. def _do_collect_type(self, tp):
  180. if not isinstance(tp, model.BaseTypeByIdentity):
  181. if isinstance(tp, tuple):
  182. for x in tp:
  183. self._do_collect_type(x)
  184. return
  185. if tp not in self._typesdict:
  186. self._typesdict[tp] = None
  187. if isinstance(tp, model.FunctionPtrType):
  188. self._do_collect_type(tp.as_raw_function())
  189. elif isinstance(tp, model.StructOrUnion):
  190. if tp.fldtypes is not None and (
  191. tp not in self.ffi._parser._included_declarations):
  192. for name1, tp1, _, _ in self._enum_fields(tp):
  193. self._do_collect_type(self._field_type(tp, name1, tp1))
  194. else:
  195. for _, x in tp._get_items():
  196. self._do_collect_type(x)
  197. def _generate(self, step_name):
  198. lst = self.ffi._parser._declarations.items()
  199. for name, (tp, quals) in sorted(lst):
  200. kind, realname = name.split(' ', 1)
  201. try:
  202. method = getattr(self, '_generate_cpy_%s_%s' % (kind,
  203. step_name))
  204. except AttributeError:
  205. raise VerificationError(
  206. "not implemented in recompile(): %r" % name)
  207. try:
  208. self._current_quals = quals
  209. method(tp, realname)
  210. except Exception as e:
  211. model.attach_exception_info(e, name)
  212. raise
  213. # ----------
  214. ALL_STEPS = ["global", "field", "struct_union", "enum", "typename"]
  215. def collect_step_tables(self):
  216. # collect the declarations for '_cffi_globals', '_cffi_typenames', etc.
  217. self._lsts = {}
  218. for step_name in self.ALL_STEPS:
  219. self._lsts[step_name] = []
  220. self._seen_struct_unions = set()
  221. self._generate("ctx")
  222. self._add_missing_struct_unions()
  223. #
  224. for step_name in self.ALL_STEPS:
  225. lst = self._lsts[step_name]
  226. if step_name != "field":
  227. lst.sort(key=lambda entry: entry.name)
  228. self._lsts[step_name] = tuple(lst) # don't change any more
  229. #
  230. # check for a possible internal inconsistency: _cffi_struct_unions
  231. # should have been generated with exactly self._struct_unions
  232. lst = self._lsts["struct_union"]
  233. for tp, i in self._struct_unions.items():
  234. assert i < len(lst)
  235. assert lst[i].name == tp.name
  236. assert len(lst) == len(self._struct_unions)
  237. # same with enums
  238. lst = self._lsts["enum"]
  239. for tp, i in self._enums.items():
  240. assert i < len(lst)
  241. assert lst[i].name == tp.name
  242. assert len(lst) == len(self._enums)
  243. # ----------
  244. def _prnt(self, what=''):
  245. self._f.write(what + '\n')
  246. def write_source_to_f(self, f, preamble):
  247. if self.target_is_python:
  248. assert preamble is None
  249. self.write_py_source_to_f(f)
  250. else:
  251. assert preamble is not None
  252. self.write_c_source_to_f(f, preamble)
  253. def _rel_readlines(self, filename):
  254. import pkgutil
  255. return pkgutil.get_data('cffi', filename).decode('utf-8').splitlines(True)
  256. def write_c_source_to_f(self, f, preamble):
  257. self._f = f
  258. prnt = self._prnt
  259. if self.ffi._embedding is not None:
  260. prnt('#define _CFFI_USE_EMBEDDING')
  261. if not USE_LIMITED_API:
  262. prnt('#define _CFFI_NO_LIMITED_API')
  263. #
  264. # first the '#include' (actually done by inlining the file's content)
  265. lines = self._rel_readlines('_cffi_include.h')
  266. i = lines.index('#include "parse_c_type.h"\n')
  267. lines[i:i+1] = self._rel_readlines('parse_c_type.h')
  268. prnt(''.join(lines))
  269. #
  270. # if we have ffi._embedding != None, we give it here as a macro
  271. # and include an extra file
  272. base_module_name = self.module_name.split('.')[-1]
  273. if self.ffi._embedding is not None:
  274. prnt('#define _CFFI_MODULE_NAME "%s"' % (self.module_name,))
  275. prnt('static const char _CFFI_PYTHON_STARTUP_CODE[] = {')
  276. self._print_string_literal_in_array(self.ffi._embedding)
  277. prnt('0 };')
  278. prnt('#ifdef PYPY_VERSION')
  279. prnt('# define _CFFI_PYTHON_STARTUP_FUNC _cffi_pypyinit_%s' % (
  280. base_module_name,))
  281. prnt('#elif PY_MAJOR_VERSION >= 3')
  282. prnt('# define _CFFI_PYTHON_STARTUP_FUNC PyInit_%s' % (
  283. base_module_name,))
  284. prnt('#else')
  285. prnt('# define _CFFI_PYTHON_STARTUP_FUNC init%s' % (
  286. base_module_name,))
  287. prnt('#endif')
  288. lines = self._rel_readlines('_embedding.h')
  289. i = lines.index('#include "_cffi_errors.h"\n')
  290. lines[i:i+1] = self._rel_readlines('_cffi_errors.h')
  291. prnt(''.join(lines))
  292. self.needs_version(VERSION_EMBEDDED)
  293. #
  294. # then paste the C source given by the user, verbatim.
  295. prnt('/************************************************************/')
  296. prnt()
  297. prnt(preamble)
  298. prnt()
  299. prnt('/************************************************************/')
  300. prnt()
  301. #
  302. # the declaration of '_cffi_types'
  303. prnt('static void *_cffi_types[] = {')
  304. typeindex2type = dict([(i, tp) for (tp, i) in self._typesdict.items()])
  305. for i, op in enumerate(self.cffi_types):
  306. comment = ''
  307. if i in typeindex2type:
  308. comment = ' // ' + typeindex2type[i]._get_c_name()
  309. prnt('/* %2d */ %s,%s' % (i, op.as_c_expr(), comment))
  310. if not self.cffi_types:
  311. prnt(' 0')
  312. prnt('};')
  313. prnt()
  314. #
  315. # call generate_cpy_xxx_decl(), for every xxx found from
  316. # ffi._parser._declarations. This generates all the functions.
  317. self._seen_constants = set()
  318. self._generate("decl")
  319. #
  320. # the declaration of '_cffi_globals' and '_cffi_typenames'
  321. nums = {}
  322. for step_name in self.ALL_STEPS:
  323. lst = self._lsts[step_name]
  324. nums[step_name] = len(lst)
  325. if nums[step_name] > 0:
  326. prnt('static const struct _cffi_%s_s _cffi_%ss[] = {' % (
  327. step_name, step_name))
  328. for entry in lst:
  329. prnt(entry.as_c_expr())
  330. prnt('};')
  331. prnt()
  332. #
  333. # the declaration of '_cffi_includes'
  334. if self.ffi._included_ffis:
  335. prnt('static const char * const _cffi_includes[] = {')
  336. for ffi_to_include in self.ffi._included_ffis:
  337. try:
  338. included_module_name, included_source = (
  339. ffi_to_include._assigned_source[:2])
  340. except AttributeError:
  341. raise VerificationError(
  342. "ffi object %r includes %r, but the latter has not "
  343. "been prepared with set_source()" % (
  344. self.ffi, ffi_to_include,))
  345. if included_source is None:
  346. raise VerificationError(
  347. "not implemented yet: ffi.include() of a Python-based "
  348. "ffi inside a C-based ffi")
  349. prnt(' "%s",' % (included_module_name,))
  350. prnt(' NULL')
  351. prnt('};')
  352. prnt()
  353. #
  354. # the declaration of '_cffi_type_context'
  355. prnt('static const struct _cffi_type_context_s _cffi_type_context = {')
  356. prnt(' _cffi_types,')
  357. for step_name in self.ALL_STEPS:
  358. if nums[step_name] > 0:
  359. prnt(' _cffi_%ss,' % step_name)
  360. else:
  361. prnt(' NULL, /* no %ss */' % step_name)
  362. for step_name in self.ALL_STEPS:
  363. if step_name != "field":
  364. prnt(' %d, /* num_%ss */' % (nums[step_name], step_name))
  365. if self.ffi._included_ffis:
  366. prnt(' _cffi_includes,')
  367. else:
  368. prnt(' NULL, /* no includes */')
  369. prnt(' %d, /* num_types */' % (len(self.cffi_types),))
  370. flags = 0
  371. if self._num_externpy > 0 or self.ffi._embedding is not None:
  372. flags |= 1 # set to mean that we use extern "Python"
  373. prnt(' %d, /* flags */' % flags)
  374. prnt('};')
  375. prnt()
  376. #
  377. # the init function
  378. prnt('#ifdef __GNUC__')
  379. prnt('# pragma GCC visibility push(default) /* for -fvisibility= */')
  380. prnt('#endif')
  381. prnt()
  382. prnt('#ifdef PYPY_VERSION')
  383. prnt('PyMODINIT_FUNC')
  384. prnt('_cffi_pypyinit_%s(const void *p[])' % (base_module_name,))
  385. prnt('{')
  386. if flags & 1:
  387. prnt(' if (((intptr_t)p[0]) >= 0x0A03) {')
  388. prnt(' _cffi_call_python_org = '
  389. '(void(*)(struct _cffi_externpy_s *, char *))p[1];')
  390. prnt(' }')
  391. prnt(' p[0] = (const void *)0x%x;' % self._version)
  392. prnt(' p[1] = &_cffi_type_context;')
  393. prnt('#if PY_MAJOR_VERSION >= 3')
  394. prnt(' return NULL;')
  395. prnt('#endif')
  396. prnt('}')
  397. # on Windows, distutils insists on putting init_cffi_xyz in
  398. # 'export_symbols', so instead of fighting it, just give up and
  399. # give it one
  400. prnt('# ifdef _MSC_VER')
  401. prnt(' PyMODINIT_FUNC')
  402. prnt('# if PY_MAJOR_VERSION >= 3')
  403. prnt(' PyInit_%s(void) { return NULL; }' % (base_module_name,))
  404. prnt('# else')
  405. prnt(' init%s(void) { }' % (base_module_name,))
  406. prnt('# endif')
  407. prnt('# endif')
  408. prnt('#elif PY_MAJOR_VERSION >= 3')
  409. prnt('PyMODINIT_FUNC')
  410. prnt('PyInit_%s(void)' % (base_module_name,))
  411. prnt('{')
  412. prnt(' return _cffi_init("%s", 0x%x, &_cffi_type_context);' % (
  413. self.module_name, self._version))
  414. prnt('}')
  415. prnt('#else')
  416. prnt('PyMODINIT_FUNC')
  417. prnt('init%s(void)' % (base_module_name,))
  418. prnt('{')
  419. prnt(' _cffi_init("%s", 0x%x, &_cffi_type_context);' % (
  420. self.module_name, self._version))
  421. prnt('}')
  422. prnt('#endif')
  423. prnt()
  424. prnt('#ifdef __GNUC__')
  425. prnt('# pragma GCC visibility pop')
  426. prnt('#endif')
  427. self._version = None
  428. def _to_py(self, x):
  429. if isinstance(x, str):
  430. return "b'%s'" % (x,)
  431. if isinstance(x, (list, tuple)):
  432. rep = [self._to_py(item) for item in x]
  433. if len(rep) == 1:
  434. rep.append('')
  435. return "(%s)" % (','.join(rep),)
  436. return x.as_python_expr() # Py2: unicode unexpected; Py3: bytes unexp.
  437. def write_py_source_to_f(self, f):
  438. self._f = f
  439. prnt = self._prnt
  440. #
  441. # header
  442. prnt("# auto-generated file")
  443. prnt("import _cffi_backend")
  444. #
  445. # the 'import' of the included ffis
  446. num_includes = len(self.ffi._included_ffis or ())
  447. for i in range(num_includes):
  448. ffi_to_include = self.ffi._included_ffis[i]
  449. try:
  450. included_module_name, included_source = (
  451. ffi_to_include._assigned_source[:2])
  452. except AttributeError:
  453. raise VerificationError(
  454. "ffi object %r includes %r, but the latter has not "
  455. "been prepared with set_source()" % (
  456. self.ffi, ffi_to_include,))
  457. if included_source is not None:
  458. raise VerificationError(
  459. "not implemented yet: ffi.include() of a C-based "
  460. "ffi inside a Python-based ffi")
  461. prnt('from %s import ffi as _ffi%d' % (included_module_name, i))
  462. prnt()
  463. prnt("ffi = _cffi_backend.FFI('%s'," % (self.module_name,))
  464. prnt(" _version = 0x%x," % (self._version,))
  465. self._version = None
  466. #
  467. # the '_types' keyword argument
  468. self.cffi_types = tuple(self.cffi_types) # don't change any more
  469. types_lst = [op.as_python_bytes() for op in self.cffi_types]
  470. prnt(' _types = %s,' % (self._to_py(''.join(types_lst)),))
  471. typeindex2type = dict([(i, tp) for (tp, i) in self._typesdict.items()])
  472. #
  473. # the keyword arguments from ALL_STEPS
  474. for step_name in self.ALL_STEPS:
  475. lst = self._lsts[step_name]
  476. if len(lst) > 0 and step_name != "field":
  477. prnt(' _%ss = %s,' % (step_name, self._to_py(lst)))
  478. #
  479. # the '_includes' keyword argument
  480. if num_includes > 0:
  481. prnt(' _includes = (%s,),' % (
  482. ', '.join(['_ffi%d' % i for i in range(num_includes)]),))
  483. #
  484. # the footer
  485. prnt(')')
  486. # ----------
  487. def _gettypenum(self, type):
  488. # a KeyError here is a bug. please report it! :-)
  489. return self._typesdict[type]
  490. def _convert_funcarg_to_c(self, tp, fromvar, tovar, errcode):
  491. extraarg = ''
  492. if isinstance(tp, model.BasePrimitiveType) and not tp.is_complex_type():
  493. if tp.is_integer_type() and tp.name != '_Bool':
  494. converter = '_cffi_to_c_int'
  495. extraarg = ', %s' % tp.name
  496. elif isinstance(tp, model.UnknownFloatType):
  497. # don't check with is_float_type(): it may be a 'long
  498. # double' here, and _cffi_to_c_double would loose precision
  499. converter = '(%s)_cffi_to_c_double' % (tp.get_c_name(''),)
  500. else:
  501. cname = tp.get_c_name('')
  502. converter = '(%s)_cffi_to_c_%s' % (cname,
  503. tp.name.replace(' ', '_'))
  504. if cname in ('char16_t', 'char32_t'):
  505. self.needs_version(VERSION_CHAR16CHAR32)
  506. errvalue = '-1'
  507. #
  508. elif isinstance(tp, model.PointerType):
  509. self._convert_funcarg_to_c_ptr_or_array(tp, fromvar,
  510. tovar, errcode)
  511. return
  512. #
  513. elif (isinstance(tp, model.StructOrUnionOrEnum) or
  514. isinstance(tp, model.BasePrimitiveType)):
  515. # a struct (not a struct pointer) as a function argument;
  516. # or, a complex (the same code works)
  517. self._prnt(' if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)'
  518. % (tovar, self._gettypenum(tp), fromvar))
  519. self._prnt(' %s;' % errcode)
  520. return
  521. #
  522. elif isinstance(tp, model.FunctionPtrType):
  523. converter = '(%s)_cffi_to_c_pointer' % tp.get_c_name('')
  524. extraarg = ', _cffi_type(%d)' % self._gettypenum(tp)
  525. errvalue = 'NULL'
  526. #
  527. else:
  528. raise NotImplementedError(tp)
  529. #
  530. self._prnt(' %s = %s(%s%s);' % (tovar, converter, fromvar, extraarg))
  531. self._prnt(' if (%s == (%s)%s && PyErr_Occurred())' % (
  532. tovar, tp.get_c_name(''), errvalue))
  533. self._prnt(' %s;' % errcode)
  534. def _extra_local_variables(self, tp, localvars, freelines):
  535. if isinstance(tp, model.PointerType):
  536. localvars.add('Py_ssize_t datasize')
  537. localvars.add('struct _cffi_freeme_s *large_args_free = NULL')
  538. freelines.add('if (large_args_free != NULL)'
  539. ' _cffi_free_array_arguments(large_args_free);')
  540. def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode):
  541. self._prnt(' datasize = _cffi_prepare_pointer_call_argument(')
  542. self._prnt(' _cffi_type(%d), %s, (char **)&%s);' % (
  543. self._gettypenum(tp), fromvar, tovar))
  544. self._prnt(' if (datasize != 0) {')
  545. self._prnt(' %s = ((size_t)datasize) <= 640 ? '
  546. '(%s)alloca((size_t)datasize) : NULL;' % (
  547. tovar, tp.get_c_name('')))
  548. self._prnt(' if (_cffi_convert_array_argument(_cffi_type(%d), %s, '
  549. '(char **)&%s,' % (self._gettypenum(tp), fromvar, tovar))
  550. self._prnt(' datasize, &large_args_free) < 0)')
  551. self._prnt(' %s;' % errcode)
  552. self._prnt(' }')
  553. def _convert_expr_from_c(self, tp, var, context):
  554. if isinstance(tp, model.BasePrimitiveType):
  555. if tp.is_integer_type() and tp.name != '_Bool':
  556. return '_cffi_from_c_int(%s, %s)' % (var, tp.name)
  557. elif isinstance(tp, model.UnknownFloatType):
  558. return '_cffi_from_c_double(%s)' % (var,)
  559. elif tp.name != 'long double' and not tp.is_complex_type():
  560. cname = tp.name.replace(' ', '_')
  561. if cname in ('char16_t', 'char32_t'):
  562. self.needs_version(VERSION_CHAR16CHAR32)
  563. return '_cffi_from_c_%s(%s)' % (cname, var)
  564. else:
  565. return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % (
  566. var, self._gettypenum(tp))
  567. elif isinstance(tp, (model.PointerType, model.FunctionPtrType)):
  568. return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % (
  569. var, self._gettypenum(tp))
  570. elif isinstance(tp, model.ArrayType):
  571. return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % (
  572. var, self._gettypenum(model.PointerType(tp.item)))
  573. elif isinstance(tp, model.StructOrUnion):
  574. if tp.fldnames is None:
  575. raise TypeError("'%s' is used as %s, but is opaque" % (
  576. tp._get_c_name(), context))
  577. return '_cffi_from_c_struct((char *)&%s, _cffi_type(%d))' % (
  578. var, self._gettypenum(tp))
  579. elif isinstance(tp, model.EnumType):
  580. return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % (
  581. var, self._gettypenum(tp))
  582. else:
  583. raise NotImplementedError(tp)
  584. # ----------
  585. # typedefs
  586. def _typedef_type(self, tp, name):
  587. return self._global_type(tp, "(*(%s *)0)" % (name,))
  588. def _generate_cpy_typedef_collecttype(self, tp, name):
  589. self._do_collect_type(self._typedef_type(tp, name))
  590. def _generate_cpy_typedef_decl(self, tp, name):
  591. pass
  592. def _typedef_ctx(self, tp, name):
  593. type_index = self._typesdict[tp]
  594. self._lsts["typename"].append(TypenameExpr(name, type_index))
  595. def _generate_cpy_typedef_ctx(self, tp, name):
  596. tp = self._typedef_type(tp, name)
  597. self._typedef_ctx(tp, name)
  598. if getattr(tp, "origin", None) == "unknown_type":
  599. self._struct_ctx(tp, tp.name, approxname=None)
  600. elif isinstance(tp, model.NamedPointerType):
  601. self._struct_ctx(tp.totype, tp.totype.name, approxname=tp.name,
  602. named_ptr=tp)
  603. # ----------
  604. # function declarations
  605. def _generate_cpy_function_collecttype(self, tp, name):
  606. self._do_collect_type(tp.as_raw_function())
  607. if tp.ellipsis and not self.target_is_python:
  608. self._do_collect_type(tp)
  609. def _generate_cpy_function_decl(self, tp, name):
  610. assert not self.target_is_python
  611. assert isinstance(tp, model.FunctionPtrType)
  612. if tp.ellipsis:
  613. # cannot support vararg functions better than this: check for its
  614. # exact type (including the fixed arguments), and build it as a
  615. # constant function pointer (no CPython wrapper)
  616. self._generate_cpy_constant_decl(tp, name)
  617. return
  618. prnt = self._prnt
  619. numargs = len(tp.args)
  620. if numargs == 0:
  621. argname = 'noarg'
  622. elif numargs == 1:
  623. argname = 'arg0'
  624. else:
  625. argname = 'args'
  626. #
  627. # ------------------------------
  628. # the 'd' version of the function, only for addressof(lib, 'func')
  629. arguments = []
  630. call_arguments = []
  631. context = 'argument of %s' % name
  632. for i, type in enumerate(tp.args):
  633. arguments.append(type.get_c_name(' x%d' % i, context))
  634. call_arguments.append('x%d' % i)
  635. repr_arguments = ', '.join(arguments)
  636. repr_arguments = repr_arguments or 'void'
  637. if tp.abi:
  638. abi = tp.abi + ' '
  639. else:
  640. abi = ''
  641. name_and_arguments = '%s_cffi_d_%s(%s)' % (abi, name, repr_arguments)
  642. prnt('static %s' % (tp.result.get_c_name(name_and_arguments),))
  643. prnt('{')
  644. call_arguments = ', '.join(call_arguments)
  645. result_code = 'return '
  646. if isinstance(tp.result, model.VoidType):
  647. result_code = ''
  648. prnt(' %s%s(%s);' % (result_code, name, call_arguments))
  649. prnt('}')
  650. #
  651. prnt('#ifndef PYPY_VERSION') # ------------------------------
  652. #
  653. prnt('static PyObject *')
  654. prnt('_cffi_f_%s(PyObject *self, PyObject *%s)' % (name, argname))
  655. prnt('{')
  656. #
  657. context = 'argument of %s' % name
  658. for i, type in enumerate(tp.args):
  659. arg = type.get_c_name(' x%d' % i, context)
  660. prnt(' %s;' % arg)
  661. #
  662. localvars = set()
  663. freelines = set()
  664. for type in tp.args:
  665. self._extra_local_variables(type, localvars, freelines)
  666. for decl in sorted(localvars):
  667. prnt(' %s;' % (decl,))
  668. #
  669. if not isinstance(tp.result, model.VoidType):
  670. result_code = 'result = '
  671. context = 'result of %s' % name
  672. result_decl = ' %s;' % tp.result.get_c_name(' result', context)
  673. prnt(result_decl)
  674. prnt(' PyObject *pyresult;')
  675. else:
  676. result_decl = None
  677. result_code = ''
  678. #
  679. if len(tp.args) > 1:
  680. rng = range(len(tp.args))
  681. for i in rng:
  682. prnt(' PyObject *arg%d;' % i)
  683. prnt()
  684. prnt(' if (!PyArg_UnpackTuple(args, "%s", %d, %d, %s))' % (
  685. name, len(rng), len(rng),
  686. ', '.join(['&arg%d' % i for i in rng])))
  687. prnt(' return NULL;')
  688. prnt()
  689. #
  690. for i, type in enumerate(tp.args):
  691. self._convert_funcarg_to_c(type, 'arg%d' % i, 'x%d' % i,
  692. 'return NULL')
  693. prnt()
  694. #
  695. prnt(' Py_BEGIN_ALLOW_THREADS')
  696. prnt(' _cffi_restore_errno();')
  697. call_arguments = ['x%d' % i for i in range(len(tp.args))]
  698. call_arguments = ', '.join(call_arguments)
  699. prnt(' { %s%s(%s); }' % (result_code, name, call_arguments))
  700. prnt(' _cffi_save_errno();')
  701. prnt(' Py_END_ALLOW_THREADS')
  702. prnt()
  703. #
  704. prnt(' (void)self; /* unused */')
  705. if numargs == 0:
  706. prnt(' (void)noarg; /* unused */')
  707. if result_code:
  708. prnt(' pyresult = %s;' %
  709. self._convert_expr_from_c(tp.result, 'result', 'result type'))
  710. for freeline in freelines:
  711. prnt(' ' + freeline)
  712. prnt(' return pyresult;')
  713. else:
  714. for freeline in freelines:
  715. prnt(' ' + freeline)
  716. prnt(' Py_INCREF(Py_None);')
  717. prnt(' return Py_None;')
  718. prnt('}')
  719. #
  720. prnt('#else') # ------------------------------
  721. #
  722. # the PyPy version: need to replace struct/union arguments with
  723. # pointers, and if the result is a struct/union, insert a first
  724. # arg that is a pointer to the result. We also do that for
  725. # complex args and return type.
  726. def need_indirection(type):
  727. return (isinstance(type, model.StructOrUnion) or
  728. (isinstance(type, model.PrimitiveType) and
  729. type.is_complex_type()))
  730. difference = False
  731. arguments = []
  732. call_arguments = []
  733. context = 'argument of %s' % name
  734. for i, type in enumerate(tp.args):
  735. indirection = ''
  736. if need_indirection(type):
  737. indirection = '*'
  738. difference = True
  739. arg = type.get_c_name(' %sx%d' % (indirection, i), context)
  740. arguments.append(arg)
  741. call_arguments.append('%sx%d' % (indirection, i))
  742. tp_result = tp.result
  743. if need_indirection(tp_result):
  744. context = 'result of %s' % name
  745. arg = tp_result.get_c_name(' *result', context)
  746. arguments.insert(0, arg)
  747. tp_result = model.void_type
  748. result_decl = None
  749. result_code = '*result = '
  750. difference = True
  751. if difference:
  752. repr_arguments = ', '.join(arguments)
  753. repr_arguments = repr_arguments or 'void'
  754. name_and_arguments = '%s_cffi_f_%s(%s)' % (abi, name,
  755. repr_arguments)
  756. prnt('static %s' % (tp_result.get_c_name(name_and_arguments),))
  757. prnt('{')
  758. if result_decl:
  759. prnt(result_decl)
  760. call_arguments = ', '.join(call_arguments)
  761. prnt(' { %s%s(%s); }' % (result_code, name, call_arguments))
  762. if result_decl:
  763. prnt(' return result;')
  764. prnt('}')
  765. else:
  766. prnt('# define _cffi_f_%s _cffi_d_%s' % (name, name))
  767. #
  768. prnt('#endif') # ------------------------------
  769. prnt()
  770. def _generate_cpy_function_ctx(self, tp, name):
  771. if tp.ellipsis and not self.target_is_python:
  772. self._generate_cpy_constant_ctx(tp, name)
  773. return
  774. type_index = self._typesdict[tp.as_raw_function()]
  775. numargs = len(tp.args)
  776. if self.target_is_python:
  777. meth_kind = OP_DLOPEN_FUNC
  778. elif numargs == 0:
  779. meth_kind = OP_CPYTHON_BLTN_N # 'METH_NOARGS'
  780. elif numargs == 1:
  781. meth_kind = OP_CPYTHON_BLTN_O # 'METH_O'
  782. else:
  783. meth_kind = OP_CPYTHON_BLTN_V # 'METH_VARARGS'
  784. self._lsts["global"].append(
  785. GlobalExpr(name, '_cffi_f_%s' % name,
  786. CffiOp(meth_kind, type_index),
  787. size='_cffi_d_%s' % name))
  788. # ----------
  789. # named structs or unions
  790. def _field_type(self, tp_struct, field_name, tp_field):
  791. if isinstance(tp_field, model.ArrayType):
  792. actual_length = tp_field.length
  793. if actual_length == '...':
  794. ptr_struct_name = tp_struct.get_c_name('*')
  795. actual_length = '_cffi_array_len(((%s)0)->%s)' % (
  796. ptr_struct_name, field_name)
  797. tp_item = self._field_type(tp_struct, '%s[0]' % field_name,
  798. tp_field.item)
  799. tp_field = model.ArrayType(tp_item, actual_length)
  800. return tp_field
  801. def _struct_collecttype(self, tp):
  802. self._do_collect_type(tp)
  803. if self.target_is_python:
  804. # also requires nested anon struct/unions in ABI mode, recursively
  805. for fldtype in tp.anonymous_struct_fields():
  806. self._struct_collecttype(fldtype)
  807. def _struct_decl(self, tp, cname, approxname):
  808. if tp.fldtypes is None:
  809. return
  810. prnt = self._prnt
  811. checkfuncname = '_cffi_checkfld_%s' % (approxname,)
  812. prnt('_CFFI_UNUSED_FN')
  813. prnt('static void %s(%s *p)' % (checkfuncname, cname))
  814. prnt('{')
  815. prnt(' /* only to generate compile-time warnings or errors */')
  816. prnt(' (void)p;')
  817. for fname, ftype, fbitsize, fqual in self._enum_fields(tp):
  818. try:
  819. if ftype.is_integer_type() or fbitsize >= 0:
  820. # accept all integers, but complain on float or double
  821. if fname != '':
  822. prnt(" (void)((p->%s) | 0); /* check that '%s.%s' is "
  823. "an integer */" % (fname, cname, fname))
  824. continue
  825. # only accept exactly the type declared, except that '[]'
  826. # is interpreted as a '*' and so will match any array length.
  827. # (It would also match '*', but that's harder to detect...)
  828. while (isinstance(ftype, model.ArrayType)
  829. and (ftype.length is None or ftype.length == '...')):
  830. ftype = ftype.item
  831. fname = fname + '[0]'
  832. prnt(' { %s = &p->%s; (void)tmp; }' % (
  833. ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual),
  834. fname))
  835. except VerificationError as e:
  836. prnt(' /* %s */' % str(e)) # cannot verify it, ignore
  837. prnt('}')
  838. prnt('struct _cffi_align_%s { char x; %s y; };' % (approxname, cname))
  839. prnt()
  840. def _struct_ctx(self, tp, cname, approxname, named_ptr=None):
  841. type_index = self._typesdict[tp]
  842. reason_for_not_expanding = None
  843. flags = []
  844. if isinstance(tp, model.UnionType):
  845. flags.append("_CFFI_F_UNION")
  846. if tp.fldtypes is None:
  847. flags.append("_CFFI_F_OPAQUE")
  848. reason_for_not_expanding = "opaque"
  849. if (tp not in self.ffi._parser._included_declarations and
  850. (named_ptr is None or
  851. named_ptr not in self.ffi._parser._included_declarations)):
  852. if tp.fldtypes is None:
  853. pass # opaque
  854. elif tp.partial or any(tp.anonymous_struct_fields()):
  855. pass # field layout obtained silently from the C compiler
  856. else:
  857. flags.append("_CFFI_F_CHECK_FIELDS")
  858. if tp.packed:
  859. if tp.packed > 1:
  860. raise NotImplementedError(
  861. "%r is declared with 'pack=%r'; only 0 or 1 are "
  862. "supported in API mode (try to use \"...;\", which "
  863. "does not require a 'pack' declaration)" %
  864. (tp, tp.packed))
  865. flags.append("_CFFI_F_PACKED")
  866. else:
  867. flags.append("_CFFI_F_EXTERNAL")
  868. reason_for_not_expanding = "external"
  869. flags = '|'.join(flags) or '0'
  870. c_fields = []
  871. if reason_for_not_expanding is None:
  872. enumfields = list(self._enum_fields(tp))
  873. for fldname, fldtype, fbitsize, fqual in enumfields:
  874. fldtype = self._field_type(tp, fldname, fldtype)
  875. self._check_not_opaque(fldtype,
  876. "field '%s.%s'" % (tp.name, fldname))
  877. # cname is None for _add_missing_struct_unions() only
  878. op = OP_NOOP
  879. if fbitsize >= 0:
  880. op = OP_BITFIELD
  881. size = '%d /* bits */' % fbitsize
  882. elif cname is None or (
  883. isinstance(fldtype, model.ArrayType) and
  884. fldtype.length is None):
  885. size = '(size_t)-1'
  886. else:
  887. size = 'sizeof(((%s)0)->%s)' % (
  888. tp.get_c_name('*') if named_ptr is None
  889. else named_ptr.name,
  890. fldname)
  891. if cname is None or fbitsize >= 0:
  892. offset = '(size_t)-1'
  893. elif named_ptr is not None:
  894. offset = '((char *)&((%s)0)->%s) - (char *)0' % (
  895. named_ptr.name, fldname)
  896. else:
  897. offset = 'offsetof(%s, %s)' % (tp.get_c_name(''), fldname)
  898. c_fields.append(
  899. FieldExpr(fldname, offset, size, fbitsize,
  900. CffiOp(op, self._typesdict[fldtype])))
  901. first_field_index = len(self._lsts["field"])
  902. self._lsts["field"].extend(c_fields)
  903. #
  904. if cname is None: # unknown name, for _add_missing_struct_unions
  905. size = '(size_t)-2'
  906. align = -2
  907. comment = "unnamed"
  908. else:
  909. if named_ptr is not None:
  910. size = 'sizeof(*(%s)0)' % (named_ptr.name,)
  911. align = '-1 /* unknown alignment */'
  912. else:
  913. size = 'sizeof(%s)' % (cname,)
  914. align = 'offsetof(struct _cffi_align_%s, y)' % (approxname,)
  915. comment = None
  916. else:
  917. size = '(size_t)-1'
  918. align = -1
  919. first_field_index = -1
  920. comment = reason_for_not_expanding
  921. self._lsts["struct_union"].append(
  922. StructUnionExpr(tp.name, type_index, flags, size, align, comment,
  923. first_field_index, c_fields))
  924. self._seen_struct_unions.add(tp)
  925. def _check_not_opaque(self, tp, location):
  926. while isinstance(tp, model.ArrayType):
  927. tp = tp.item
  928. if isinstance(tp, model.StructOrUnion) and tp.fldtypes is None:
  929. raise TypeError(
  930. "%s is of an opaque type (not declared in cdef())" % location)
  931. def _add_missing_struct_unions(self):
  932. # not very nice, but some struct declarations might be missing
  933. # because they don't have any known C name. Check that they are
  934. # not partial (we can't complete or verify them!) and emit them
  935. # anonymously.
  936. lst = list(self._struct_unions.items())
  937. lst.sort(key=lambda tp_order: tp_order[1])
  938. for tp, order in lst:
  939. if tp not in self._seen_struct_unions:
  940. if tp.partial:
  941. raise NotImplementedError("internal inconsistency: %r is "
  942. "partial but was not seen at "
  943. "this point" % (tp,))
  944. if tp.name.startswith('$') and tp.name[1:].isdigit():
  945. approxname = tp.name[1:]
  946. elif tp.name == '_IO_FILE' and tp.forcename == 'FILE':
  947. approxname = 'FILE'
  948. self._typedef_ctx(tp, 'FILE')
  949. else:
  950. raise NotImplementedError("internal inconsistency: %r" %
  951. (tp,))
  952. self._struct_ctx(tp, None, approxname)
  953. def _generate_cpy_struct_collecttype(self, tp, name):
  954. self._struct_collecttype(tp)
  955. _generate_cpy_union_collecttype = _generate_cpy_struct_collecttype
  956. def _struct_names(self, tp):
  957. cname = tp.get_c_name('')
  958. if ' ' in cname:
  959. return cname, cname.replace(' ', '_')
  960. else:
  961. return cname, '_' + cname
  962. def _generate_cpy_struct_decl(self, tp, name):
  963. self._struct_decl(tp, *self._struct_names(tp))
  964. _generate_cpy_union_decl = _generate_cpy_struct_decl
  965. def _generate_cpy_struct_ctx(self, tp, name):
  966. self._struct_ctx(tp, *self._struct_names(tp))
  967. _generate_cpy_union_ctx = _generate_cpy_struct_ctx
  968. # ----------
  969. # 'anonymous' declarations. These are produced for anonymous structs
  970. # or unions; the 'name' is obtained by a typedef.
  971. def _generate_cpy_anonymous_collecttype(self, tp, name):
  972. if isinstance(tp, model.EnumType):
  973. self._generate_cpy_enum_collecttype(tp, name)
  974. else:
  975. self._struct_collecttype(tp)
  976. def _generate_cpy_anonymous_decl(self, tp, name):
  977. if isinstance(tp, model.EnumType):
  978. self._generate_cpy_enum_decl(tp)
  979. else:
  980. self._struct_decl(tp, name, 'typedef_' + name)
  981. def _generate_cpy_anonymous_ctx(self, tp, name):
  982. if isinstance(tp, model.EnumType):
  983. self._enum_ctx(tp, name)
  984. else:
  985. self._struct_ctx(tp, name, 'typedef_' + name)
  986. # ----------
  987. # constants, declared with "static const ..."
  988. def _generate_cpy_const(self, is_int, name, tp=None, category='const',
  989. check_value=None):
  990. if (category, name) in self._seen_constants:
  991. raise VerificationError(
  992. "duplicate declaration of %s '%s'" % (category, name))
  993. self._seen_constants.add((category, name))
  994. #
  995. prnt = self._prnt
  996. funcname = '_cffi_%s_%s' % (category, name)
  997. if is_int:
  998. prnt('static int %s(unsigned long long *o)' % funcname)
  999. prnt('{')
  1000. prnt(' int n = (%s) <= 0;' % (name,))
  1001. prnt(' *o = (unsigned long long)((%s) | 0);'
  1002. ' /* check that %s is an integer */' % (name, name))
  1003. if check_value is not None:
  1004. if check_value > 0:
  1005. check_value = '%dU' % (check_value,)
  1006. prnt(' if (!_cffi_check_int(*o, n, %s))' % (check_value,))
  1007. prnt(' n |= 2;')
  1008. prnt(' return n;')
  1009. prnt('}')
  1010. else:
  1011. assert check_value is None
  1012. prnt('static void %s(char *o)' % funcname)
  1013. prnt('{')
  1014. prnt(' *(%s)o = %s;' % (tp.get_c_name('*'), name))
  1015. prnt('}')
  1016. prnt()
  1017. def _generate_cpy_constant_collecttype(self, tp, name):
  1018. is_int = tp.is_integer_type()
  1019. if not is_int or self.target_is_python:
  1020. self._do_collect_type(tp)
  1021. def _generate_cpy_constant_decl(self, tp, name):
  1022. is_int = tp.is_integer_type()
  1023. self._generate_cpy_const(is_int, name, tp)
  1024. def _generate_cpy_constant_ctx(self, tp, name):
  1025. if not self.target_is_python and tp.is_integer_type():
  1026. type_op = CffiOp(OP_CONSTANT_INT, -1)
  1027. else:
  1028. if self.target_is_python:
  1029. const_kind = OP_DLOPEN_CONST
  1030. else:
  1031. const_kind = OP_CONSTANT
  1032. type_index = self._typesdict[tp]
  1033. type_op = CffiOp(const_kind, type_index)
  1034. self._lsts["global"].append(
  1035. GlobalExpr(name, '_cffi_const_%s' % name, type_op))
  1036. # ----------
  1037. # enums
  1038. def _generate_cpy_enum_collecttype(self, tp, name):
  1039. self._do_collect_type(tp)
  1040. def _generate_cpy_enum_decl(self, tp, name=None):
  1041. for enumerator in tp.enumerators:
  1042. self._generate_cpy_const(True, enumerator)
  1043. def _enum_ctx(self, tp, cname):
  1044. type_index = self._typesdict[tp]
  1045. type_op = CffiOp(OP_ENUM, -1)
  1046. if self.target_is_python:
  1047. tp.check_not_partial()
  1048. for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
  1049. self._lsts["global"].append(
  1050. GlobalExpr(enumerator, '_cffi_const_%s' % enumerator, type_op,
  1051. check_value=enumvalue))
  1052. #
  1053. if cname is not None and '$' not in cname and not self.target_is_python:
  1054. size = "sizeof(%s)" % cname
  1055. signed = "((%s)-1) <= 0" % cname
  1056. else:
  1057. basetp = tp.build_baseinttype(self.ffi, [])
  1058. size = self.ffi.sizeof(basetp)
  1059. signed = int(int(self.ffi.cast(basetp, -1)) < 0)
  1060. allenums = ",".join(tp.enumerators)
  1061. self._lsts["enum"].append(
  1062. EnumExpr(tp.name, type_index, size, signed, allenums))
  1063. def _generate_cpy_enum_ctx(self, tp, name):
  1064. self._enum_ctx(tp, tp._get_c_name())
  1065. # ----------
  1066. # macros: for now only for integers
  1067. def _generate_cpy_macro_collecttype(self, tp, name):
  1068. pass
  1069. def _generate_cpy_macro_decl(self, tp, name):
  1070. if tp == '...':
  1071. check_value = None
  1072. else:
  1073. check_value = tp # an integer
  1074. self._generate_cpy_const(True, name, check_value=check_value)
  1075. def _generate_cpy_macro_ctx(self, tp, name):
  1076. if tp == '...':
  1077. if self.target_is_python:
  1078. raise VerificationError(
  1079. "cannot use the syntax '...' in '#define %s ...' when "
  1080. "using the ABI mode" % (name,))
  1081. check_value = None
  1082. else:
  1083. check_value = tp # an integer
  1084. type_op = CffiOp(OP_CONSTANT_INT, -1)
  1085. self._lsts["global"].append(
  1086. GlobalExpr(name, '_cffi_const_%s' % name, type_op,
  1087. check_value=check_value))
  1088. # ----------
  1089. # global variables
  1090. def _global_type(self, tp, global_name):
  1091. if isinstance(tp, model.ArrayType):
  1092. actual_length = tp.length
  1093. if actual_length == '...':
  1094. actual_length = '_cffi_array_len(%s)' % (global_name,)
  1095. tp_item = self._global_type(tp.item, '%s[0]' % global_name)
  1096. tp = model.ArrayType(tp_item, actual_length)
  1097. return tp
  1098. def _generate_cpy_variable_collecttype(self, tp, name):
  1099. self._do_collect_type(self._global_type(tp, name))
  1100. def _generate_cpy_variable_decl(self, tp, name):
  1101. prnt = self._prnt
  1102. tp = self._global_type(tp, name)
  1103. if isinstance(tp, model.ArrayType) and tp.length is None:
  1104. tp = tp.item
  1105. ampersand = ''
  1106. else:
  1107. ampersand = '&'
  1108. # This code assumes that casts from "tp *" to "void *" is a
  1109. # no-op, i.e. a function that returns a "tp *" can be called
  1110. # as if it returned a "void *". This should be generally true
  1111. # on any modern machine. The only exception to that rule (on
  1112. # uncommon architectures, and as far as I can tell) might be
  1113. # if 'tp' were a function type, but that is not possible here.
  1114. # (If 'tp' is a function _pointer_ type, then casts from "fn_t
  1115. # **" to "void *" are again no-ops, as far as I can tell.)
  1116. decl = '*_cffi_var_%s(void)' % (name,)
  1117. prnt('static ' + tp.get_c_name(decl, quals=self._current_quals))
  1118. prnt('{')
  1119. prnt(' return %s(%s);' % (ampersand, name))
  1120. prnt('}')
  1121. prnt()
  1122. def _generate_cpy_variable_ctx(self, tp, name):
  1123. tp = self._global_type(tp, name)
  1124. type_index = self._typesdict[tp]
  1125. if self.target_is_python:
  1126. op = OP_GLOBAL_VAR
  1127. else:
  1128. op = OP_GLOBAL_VAR_F
  1129. self._lsts["global"].append(
  1130. GlobalExpr(name, '_cffi_var_%s' % name, CffiOp(op, type_index)))
  1131. # ----------
  1132. # extern "Python"
  1133. def _generate_cpy_extern_python_collecttype(self, tp, name):
  1134. assert isinstance(tp, model.FunctionPtrType)
  1135. self._do_collect_type(tp)
  1136. _generate_cpy_dllexport_python_collecttype = \
  1137. _generate_cpy_extern_python_plus_c_collecttype = \
  1138. _generate_cpy_extern_python_collecttype
  1139. def _extern_python_decl(self, tp, name, tag_and_space):
  1140. prnt = self._prnt
  1141. if isinstance(tp.result, model.VoidType):
  1142. size_of_result = '0'
  1143. else:
  1144. context = 'result of %s' % name
  1145. size_of_result = '(int)sizeof(%s)' % (
  1146. tp.result.get_c_name('', context),)
  1147. prnt('static struct _cffi_externpy_s _cffi_externpy__%s =' % name)
  1148. prnt(' { "%s.%s", %s, 0, 0 };' % (
  1149. self.module_name, name, size_of_result))
  1150. prnt()
  1151. #
  1152. arguments = []
  1153. context = 'argument of %s' % name
  1154. for i, type in enumerate(tp.args):
  1155. arg = type.get_c_name(' a%d' % i, context)
  1156. arguments.append(arg)
  1157. #
  1158. repr_arguments = ', '.join(arguments)
  1159. repr_arguments = repr_arguments or 'void'
  1160. name_and_arguments = '%s(%s)' % (name, repr_arguments)
  1161. if tp.abi == "__stdcall":
  1162. name_and_arguments = '_cffi_stdcall ' + name_and_arguments
  1163. #
  1164. def may_need_128_bits(tp):
  1165. return (isinstance(tp, model.PrimitiveType) and
  1166. tp.name == 'long double')
  1167. #
  1168. size_of_a = max(len(tp.args)*8, 8)
  1169. if may_need_128_bits(tp.result):
  1170. size_of_a = max(size_of_a, 16)
  1171. if isinstance(tp.result, model.StructOrUnion):
  1172. size_of_a = 'sizeof(%s) > %d ? sizeof(%s) : %d' % (
  1173. tp.result.get_c_name(''), size_of_a,
  1174. tp.result.get_c_name(''), size_of_a)
  1175. prnt('%s%s' % (tag_and_space, tp.result.get_c_name(name_and_arguments)))
  1176. prnt('{')
  1177. prnt(' char a[%s];' % size_of_a)
  1178. prnt(' char *p = a;')
  1179. for i, type in enumerate(tp.args):
  1180. arg = 'a%d' % i
  1181. if (isinstance(type, model.StructOrUnion) or
  1182. may_need_128_bits(type)):
  1183. arg = '&' + arg
  1184. type = model.PointerType(type)
  1185. prnt(' *(%s)(p + %d) = %s;' % (type.get_c_name('*'), i*8, arg))
  1186. prnt(' _cffi_call_python(&_cffi_externpy__%s, p);' % name)
  1187. if not isinstance(tp.result, model.VoidType):
  1188. prnt(' return *(%s)p;' % (tp.result.get_c_name('*'),))
  1189. prnt('}')
  1190. prnt()
  1191. self._num_externpy += 1
  1192. def _generate_cpy_extern_python_decl(self, tp, name):
  1193. self._extern_python_decl(tp, name, 'static ')
  1194. def _generate_cpy_dllexport_python_decl(self, tp, name):
  1195. self._extern_python_decl(tp, name, 'CFFI_DLLEXPORT ')
  1196. def _generate_cpy_extern_python_plus_c_decl(self, tp, name):
  1197. self._extern_python_decl(tp, name, '')
  1198. def _generate_cpy_extern_python_ctx(self, tp, name):
  1199. if self.target_is_python:
  1200. raise VerificationError(
  1201. "cannot use 'extern \"Python\"' in the ABI mode")
  1202. if tp.ellipsis:
  1203. raise NotImplementedError("a vararg function is extern \"Python\"")
  1204. type_index = self._typesdict[tp]
  1205. type_op = CffiOp(OP_EXTERN_PYTHON, type_index)
  1206. self._lsts["global"].append(
  1207. GlobalExpr(name, '&_cffi_externpy__%s' % name, type_op, name))
  1208. _generate_cpy_dllexport_python_ctx = \
  1209. _generate_cpy_extern_python_plus_c_ctx = \
  1210. _generate_cpy_extern_python_ctx
  1211. def _print_string_literal_in_array(self, s):
  1212. prnt = self._prnt
  1213. prnt('// # NB. this is not a string because of a size limit in MSVC')
  1214. if not isinstance(s, bytes): # unicode
  1215. s = s.encode('utf-8') # -> bytes
  1216. else:
  1217. s.decode('utf-8') # got bytes, check for valid utf-8
  1218. try:
  1219. s.decode('ascii')
  1220. except UnicodeDecodeError:
  1221. s = b'# -*- encoding: utf8 -*-\n' + s
  1222. for line in s.splitlines(True):
  1223. comment = line
  1224. if type('//') is bytes: # python2
  1225. line = map(ord, line) # make a list of integers
  1226. else: # python3
  1227. # type(line) is bytes, which enumerates like a list of integers
  1228. comment = ascii(comment)[1:-1]
  1229. prnt(('// ' + comment).rstrip())
  1230. printed_line = ''
  1231. for c in line:
  1232. if len(printed_line) >= 76:
  1233. prnt(printed_line)
  1234. printed_line = ''
  1235. printed_line += '%d,' % (c,)
  1236. prnt(printed_line)
  1237. # ----------
  1238. # emitting the opcodes for individual types
  1239. def _emit_bytecode_VoidType(self, tp, index):
  1240. self.cffi_types[index] = CffiOp(OP_PRIMITIVE, PRIM_VOID)
  1241. def _emit_bytecode_PrimitiveType(self, tp, index):
  1242. prim_index = PRIMITIVE_TO_INDEX[tp.name]
  1243. self.cffi_types[index] = CffiOp(OP_PRIMITIVE, prim_index)
  1244. def _emit_bytecode_UnknownIntegerType(self, tp, index):
  1245. s = ('_cffi_prim_int(sizeof(%s), (\n'
  1246. ' ((%s)-1) | 0 /* check that %s is an integer type */\n'
  1247. ' ) <= 0)' % (tp.name, tp.name, tp.name))
  1248. self.cffi_types[index] = CffiOp(OP_PRIMITIVE, s)
  1249. def _emit_bytecode_UnknownFloatType(self, tp, index):
  1250. s = ('_cffi_prim_float(sizeof(%s) *\n'
  1251. ' (((%s)1) / 2) * 2 /* integer => 0, float => 1 */\n'
  1252. ' )' % (tp.name, tp.name))
  1253. self.cffi_types[index] = CffiOp(OP_PRIMITIVE, s)
  1254. def _emit_bytecode_RawFunctionType(self, tp, index):
  1255. self.cffi_types[index] = CffiOp(OP_FUNCTION, self._typesdict[tp.result])
  1256. index += 1
  1257. for tp1 in tp.args:
  1258. realindex = self._typesdict[tp1]
  1259. if index != realindex:
  1260. if isinstance(tp1, model.PrimitiveType):
  1261. self._emit_bytecode_PrimitiveType(tp1, index)
  1262. else:
  1263. self.cffi_types[index] = CffiOp(OP_NOOP, realindex)
  1264. index += 1
  1265. flags = int(tp.ellipsis)
  1266. if tp.abi is not None:
  1267. if tp.abi == '__stdcall':
  1268. flags |= 2
  1269. else:
  1270. raise NotImplementedError("abi=%r" % (tp.abi,))
  1271. self.cffi_types[index] = CffiOp(OP_FUNCTION_END, flags)
  1272. def _emit_bytecode_PointerType(self, tp, index):
  1273. self.cffi_types[index] = CffiOp(OP_POINTER, self._typesdict[tp.totype])
  1274. _emit_bytecode_ConstPointerType = _emit_bytecode_PointerType
  1275. _emit_bytecode_NamedPointerType = _emit_bytecode_PointerType
  1276. def _emit_bytecode_FunctionPtrType(self, tp, index):
  1277. raw = tp.as_raw_function()
  1278. self.cffi_types[index] = CffiOp(OP_POINTER, self._typesdict[raw])
  1279. def _emit_bytecode_ArrayType(self, tp, index):
  1280. item_index = self._typesdict[tp.item]
  1281. if tp.length is None:
  1282. self.cffi_types[index] = CffiOp(OP_OPEN_ARRAY, item_index)
  1283. elif tp.length == '...':
  1284. raise VerificationError(
  1285. "type %s badly placed: the '...' array length can only be "
  1286. "used on global arrays or on fields of structures" % (
  1287. str(tp).replace('/*...*/', '...'),))
  1288. else:
  1289. assert self.cffi_types[index + 1] == 'LEN'
  1290. self.cffi_types[index] = CffiOp(OP_ARRAY, item_index)
  1291. self.cffi_types[index + 1] = CffiOp(None, str(tp.length))
  1292. def _emit_bytecode_StructType(self, tp, index):
  1293. struct_index = self._struct_unions[tp]
  1294. self.cffi_types[index] = CffiOp(OP_STRUCT_UNION, struct_index)
  1295. _emit_bytecode_UnionType = _emit_bytecode_StructType
  1296. def _emit_bytecode_EnumType(self, tp, index):
  1297. enum_index = self._enums[tp]
  1298. self.cffi_types[index] = CffiOp(OP_ENUM, enum_index)
  1299. if sys.version_info >= (3,):
  1300. NativeIO = io.StringIO
  1301. else:
  1302. class NativeIO(io.BytesIO):
  1303. def write(self, s):
  1304. if isinstance(s, unicode):
  1305. s = s.encode('ascii')
  1306. super(NativeIO, self).write(s)
  1307. def _make_c_or_py_source(ffi, module_name, preamble, target_file, verbose):
  1308. if verbose:
  1309. print("generating %s" % (target_file,))
  1310. recompiler = Recompiler(ffi, module_name,
  1311. target_is_python=(preamble is None))
  1312. recompiler.collect_type_table()
  1313. recompiler.collect_step_tables()
  1314. f = NativeIO()
  1315. recompiler.write_source_to_f(f, preamble)
  1316. output = f.getvalue()
  1317. try:
  1318. with open(target_file, 'r') as f1:
  1319. if f1.read(len(output) + 1) != output:
  1320. raise IOError
  1321. if verbose:
  1322. print("(already up-to-date)")
  1323. return False # already up-to-date
  1324. except IOError:
  1325. tmp_file = '%s.~%d' % (target_file, os.getpid())
  1326. with open(tmp_file, 'w') as f1:
  1327. f1.write(output)
  1328. try:
  1329. os.rename(tmp_file, target_file)
  1330. except OSError:
  1331. os.unlink(target_file)
  1332. os.rename(tmp_file, target_file)
  1333. return True
  1334. def make_c_source(ffi, module_name, preamble, target_c_file, verbose=False):
  1335. assert preamble is not None
  1336. return _make_c_or_py_source(ffi, module_name, preamble, target_c_file,
  1337. verbose)
  1338. def make_py_source(ffi, module_name, target_py_file, verbose=False):
  1339. return _make_c_or_py_source(ffi, module_name, None, target_py_file,
  1340. verbose)
  1341. def _modname_to_file(outputdir, modname, extension):
  1342. parts = modname.split('.')
  1343. try:
  1344. os.makedirs(os.path.join(outputdir, *parts[:-1]))
  1345. except OSError:
  1346. pass
  1347. parts[-1] += extension
  1348. return os.path.join(outputdir, *parts), parts
  1349. # Aaargh. Distutils is not tested at all for the purpose of compiling
  1350. # DLLs that are not extension modules. Here are some hacks to work
  1351. # around that, in the _patch_for_*() functions...
  1352. def _patch_meth(patchlist, cls, name, new_meth):
  1353. old = getattr(cls, name)
  1354. patchlist.append((cls, name, old))
  1355. setattr(cls, name, new_meth)
  1356. return old
  1357. def _unpatch_meths(patchlist):
  1358. for cls, name, old_meth in reversed(patchlist):
  1359. setattr(cls, name, old_meth)
  1360. def _patch_for_embedding(patchlist):
  1361. if sys.platform == 'win32':
  1362. # we must not remove the manifest when building for embedding!
  1363. from distutils.msvc9compiler import MSVCCompiler
  1364. _patch_meth(patchlist, MSVCCompiler, '_remove_visual_c_ref',
  1365. lambda self, manifest_file: manifest_file)
  1366. if sys.platform == 'darwin':
  1367. # we must not make a '-bundle', but a '-dynamiclib' instead
  1368. from distutils.ccompiler import CCompiler
  1369. def my_link_shared_object(self, *args, **kwds):
  1370. if '-bundle' in self.linker_so:
  1371. self.linker_so = list(self.linker_so)
  1372. i = self.linker_so.index('-bundle')
  1373. self.linker_so[i] = '-dynamiclib'
  1374. return old_link_shared_object(self, *args, **kwds)
  1375. old_link_shared_object = _patch_meth(patchlist, CCompiler,
  1376. 'link_shared_object',
  1377. my_link_shared_object)
  1378. def _patch_for_target(patchlist, target):
  1379. from distutils.command.build_ext import build_ext
  1380. # if 'target' is different from '*', we need to patch some internal
  1381. # method to just return this 'target' value, instead of having it
  1382. # built from module_name
  1383. if target.endswith('.*'):
  1384. target = target[:-2]
  1385. if sys.platform == 'win32':
  1386. target += '.dll'
  1387. elif sys.platform == 'darwin':
  1388. target += '.dylib'
  1389. else:
  1390. target += '.so'
  1391. _patch_meth(patchlist, build_ext, 'get_ext_filename',
  1392. lambda self, ext_name: target)
  1393. def recompile(ffi, module_name, preamble, tmpdir='.', call_c_compiler=True,
  1394. c_file=None, source_extension='.c', extradir=None,
  1395. compiler_verbose=1, target=None, debug=None, **kwds):
  1396. if not isinstance(module_name, str):
  1397. module_name = module_name.encode('ascii')
  1398. if ffi._windows_unicode:
  1399. ffi._apply_windows_unicode(kwds)
  1400. if preamble is not None:
  1401. embedding = (ffi._embedding is not None)
  1402. if embedding:
  1403. ffi._apply_embedding_fix(kwds)
  1404. if c_file is None:
  1405. c_file, parts = _modname_to_file(tmpdir, module_name,
  1406. source_extension)
  1407. if extradir:
  1408. parts = [extradir] + parts
  1409. ext_c_file = os.path.join(*parts)
  1410. else:
  1411. ext_c_file = c_file
  1412. #
  1413. if target is None:
  1414. if embedding:
  1415. target = '%s.*' % module_name
  1416. else:
  1417. target = '*'
  1418. #
  1419. ext = ffiplatform.get_extension(ext_c_file, module_name, **kwds)
  1420. updated = make_c_source(ffi, module_name, preamble, c_file,
  1421. verbose=compiler_verbose)
  1422. if call_c_compiler:
  1423. patchlist = []
  1424. cwd = os.getcwd()
  1425. try:
  1426. if embedding:
  1427. _patch_for_embedding(patchlist)
  1428. if target != '*':
  1429. _patch_for_target(patchlist, target)
  1430. if compiler_verbose:
  1431. if tmpdir == '.':
  1432. msg = 'the current directory is'
  1433. else:
  1434. msg = 'setting the current directory to'
  1435. print('%s %r' % (msg, os.path.abspath(tmpdir)))
  1436. os.chdir(tmpdir)
  1437. outputfilename = ffiplatform.compile('.', ext,
  1438. compiler_verbose, debug)
  1439. finally:
  1440. os.chdir(cwd)
  1441. _unpatch_meths(patchlist)
  1442. return outputfilename
  1443. else:
  1444. return ext, updated
  1445. else:
  1446. if c_file is None:
  1447. c_file, _ = _modname_to_file(tmpdir, module_name, '.py')
  1448. updated = make_py_source(ffi, module_name, c_file,
  1449. verbose=compiler_verbose)
  1450. if call_c_compiler:
  1451. return c_file
  1452. else:
  1453. return None, updated