PageRenderTime 57ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/pypy/module/cpyext/cparser.py

https://bitbucket.org/timfel/pypy
Python | 897 lines | 798 code | 26 blank | 73 comment | 136 complexity | 55d9aa7d43910581a4b6d16226e64b45 MD5 | raw file
Possible License(s): Apache-2.0, AGPL-3.0, BSD-3-Clause
  1. from collections import OrderedDict
  2. from itertools import izip
  3. from . import cmodel as model
  4. from .commontypes import COMMON_TYPES, resolve_common_type
  5. from .error import FFIError, CDefError
  6. try:
  7. from cffi import _pycparser as pycparser
  8. except ImportError:
  9. import pycparser
  10. import weakref, re, sys
  11. from rpython.translator.tool.cbuild import ExternalCompilationInfo
  12. from rpython.rlib.rfile import FILEP
  13. from rpython.rtyper.lltypesystem import rffi, lltype
  14. from rpython.rtyper.tool import rfficache, rffi_platform
  15. from rpython.flowspace.model import Constant, const
  16. from rpython.flowspace.specialcase import register_flow_sc
  17. from rpython.flowspace.flowcontext import FlowingError
  18. _r_comment = re.compile(r"/\*.*?\*/|//([^\n\\]|\\.)*?$",
  19. re.DOTALL | re.MULTILINE)
  20. _r_define = re.compile(r"^\s*#\s*define\s+([A-Za-z_][A-Za-z_0-9]*)"
  21. r"\b((?:[^\n\\]|\\.)*?)$",
  22. re.DOTALL | re.MULTILINE)
  23. _r_words = re.compile(r"\w+|\S")
  24. _parser_cache = None
  25. _r_int_literal = re.compile(r"-?0?x?[0-9a-f]+[lu]*$", re.IGNORECASE)
  26. _r_stdcall1 = re.compile(r"\b(__stdcall|WINAPI)\b")
  27. _r_stdcall2 = re.compile(r"[(]\s*(__stdcall|WINAPI)\b")
  28. _r_cdecl = re.compile(r"\b__cdecl\b")
  29. _r_star_const_space = re.compile( # matches "* const "
  30. r"[*]\s*((const|volatile|restrict)\b\s*)+")
  31. def _get_parser():
  32. global _parser_cache
  33. if _parser_cache is None:
  34. _parser_cache = pycparser.CParser()
  35. return _parser_cache
  36. def _preprocess(csource, macros):
  37. # Remove comments. NOTE: this only work because the cdef() section
  38. # should not contain any string literal!
  39. csource = _r_comment.sub(' ', csource)
  40. # Remove the "#define FOO x" lines
  41. for match in _r_define.finditer(csource):
  42. macroname, macrovalue = match.groups()
  43. macrovalue = macrovalue.replace('\\\n', '').strip()
  44. macros[macroname] = macrovalue
  45. csource = _r_define.sub('', csource)
  46. #
  47. # BIG HACK: replace WINAPI or __stdcall with "volatile const".
  48. # It doesn't make sense for the return type of a function to be
  49. # "volatile volatile const", so we abuse it to detect __stdcall...
  50. # Hack number 2 is that "int(volatile *fptr)();" is not valid C
  51. # syntax, so we place the "volatile" before the opening parenthesis.
  52. csource = _r_stdcall2.sub(' volatile volatile const(', csource)
  53. csource = _r_stdcall1.sub(' volatile volatile const ', csource)
  54. csource = _r_cdecl.sub(' ', csource)
  55. for name, value in reversed(macros.items()):
  56. csource = re.sub(r'\b%s\b' % name, value, csource)
  57. return csource, macros
  58. def _common_type_names(csource):
  59. # Look in the source for what looks like usages of types from the
  60. # list of common types. A "usage" is approximated here as the
  61. # appearance of the word, minus a "definition" of the type, which
  62. # is the last word in a "typedef" statement. Approximative only
  63. # but should be fine for all the common types.
  64. look_for_words = set(COMMON_TYPES)
  65. look_for_words.add(';')
  66. look_for_words.add(',')
  67. look_for_words.add('(')
  68. look_for_words.add(')')
  69. look_for_words.add('typedef')
  70. words_used = set()
  71. is_typedef = False
  72. paren = 0
  73. previous_word = ''
  74. for word in _r_words.findall(csource):
  75. if word in look_for_words:
  76. if word == ';':
  77. if is_typedef:
  78. words_used.discard(previous_word)
  79. look_for_words.discard(previous_word)
  80. is_typedef = False
  81. elif word == 'typedef':
  82. is_typedef = True
  83. paren = 0
  84. elif word == '(':
  85. paren += 1
  86. elif word == ')':
  87. paren -= 1
  88. elif word == ',':
  89. if is_typedef and paren == 0:
  90. words_used.discard(previous_word)
  91. look_for_words.discard(previous_word)
  92. else: # word in COMMON_TYPES
  93. words_used.add(word)
  94. previous_word = word
  95. return words_used
  96. class Parser(object):
  97. def __init__(self):
  98. self._declarations = OrderedDict()
  99. self._included_declarations = set()
  100. self._anonymous_counter = 0
  101. self._structnode2type = weakref.WeakKeyDictionary()
  102. self._options = {}
  103. self._int_constants = {}
  104. self._recomplete = []
  105. self._macros = OrderedDict()
  106. def _parse(self, csource):
  107. # modifies self._macros in-place
  108. csource, macros = _preprocess(csource, self._macros)
  109. # XXX: for more efficiency we would need to poke into the
  110. # internals of CParser... the following registers the
  111. # typedefs, because their presence or absence influences the
  112. # parsing itself (but what they are typedef'ed to plays no role)
  113. ctn = _common_type_names(csource)
  114. typenames = []
  115. for name in sorted(self._declarations):
  116. if name.startswith('typedef '):
  117. name = name[8:]
  118. typenames.append(name)
  119. ctn.discard(name)
  120. typenames += sorted(ctn)
  121. #
  122. csourcelines = ['typedef int %s;' % typename for typename in typenames]
  123. csourcelines.append('typedef int __dotdotdot__;')
  124. csourcelines.append(csource)
  125. csource = '\n'.join(csourcelines)
  126. try:
  127. ast = _get_parser().parse(csource)
  128. except pycparser.c_parser.ParseError as e:
  129. self.convert_pycparser_error(e, csource)
  130. # csource will be used to find buggy source text
  131. return ast, macros, csource
  132. def _convert_pycparser_error(self, e, csource):
  133. # xxx look for ":NUM:" at the start of str(e) and try to interpret
  134. # it as a line number
  135. line = None
  136. msg = str(e)
  137. if msg.startswith(':') and ':' in msg[1:]:
  138. linenum = msg[1:msg.find(':',1)]
  139. if linenum.isdigit():
  140. linenum = int(linenum, 10)
  141. csourcelines = csource.splitlines()
  142. if 1 <= linenum <= len(csourcelines):
  143. line = csourcelines[linenum-1]
  144. return line
  145. def convert_pycparser_error(self, e, csource):
  146. line = self._convert_pycparser_error(e, csource)
  147. msg = str(e)
  148. if line:
  149. msg = 'cannot parse "%s"\n%s' % (line.strip(), msg)
  150. else:
  151. msg = 'parse error\n%s' % (msg,)
  152. raise CDefError(msg)
  153. def parse(self, csource, override=False, packed=False, dllexport=False):
  154. prev_options = self._options
  155. try:
  156. self._options = {'override': override,
  157. 'packed': packed,
  158. 'dllexport': dllexport}
  159. self._internal_parse(csource)
  160. finally:
  161. self._options = prev_options
  162. def _internal_parse(self, csource):
  163. ast, macros, csource = self._parse(csource)
  164. # add the macros
  165. self._process_macros(macros)
  166. # find the first "__dotdotdot__" and use that as a separator
  167. # between the repeated typedefs and the real csource
  168. iterator = iter(ast.ext)
  169. for decl in iterator:
  170. if decl.name == '__dotdotdot__':
  171. break
  172. #
  173. try:
  174. for decl in iterator:
  175. if isinstance(decl, pycparser.c_ast.Decl):
  176. self._parse_decl(decl)
  177. elif isinstance(decl, pycparser.c_ast.Typedef):
  178. self._parse_typedef(decl)
  179. elif decl.__class__.__name__ == 'Pragma':
  180. pass # skip pragma, only in pycparser 2.15
  181. else:
  182. raise CDefError("unrecognized construct", decl)
  183. except FFIError as e:
  184. msg = self._convert_pycparser_error(e, csource)
  185. if msg:
  186. e.args = (e.args[0] + "\n *** Err: %s" % msg,)
  187. raise
  188. def _add_constants(self, key, val):
  189. if key in self._int_constants:
  190. if self._int_constants[key] == val:
  191. return # ignore identical double declarations
  192. raise FFIError(
  193. "multiple declarations of constant: %s" % (key,))
  194. self._int_constants[key] = val
  195. def _add_integer_constant(self, name, int_str):
  196. int_str = int_str.lower().rstrip("ul")
  197. neg = int_str.startswith('-')
  198. if neg:
  199. int_str = int_str[1:]
  200. # "010" is not valid oct in py3
  201. if (int_str.startswith("0") and int_str != '0'
  202. and not int_str.startswith("0x")):
  203. int_str = "0o" + int_str[1:]
  204. pyvalue = int(int_str, 0)
  205. if neg:
  206. pyvalue = -pyvalue
  207. self._add_constants(name, pyvalue)
  208. self._declare('macro ' + name, pyvalue)
  209. def _process_macros(self, macros):
  210. for key, value in macros.items():
  211. value = value.strip()
  212. if _r_int_literal.match(value):
  213. self._add_integer_constant(key, value)
  214. else:
  215. self._declare('macro ' + key, value)
  216. def _declare_function(self, tp, quals, decl):
  217. tp = self._get_type_pointer(tp, quals)
  218. if self._options.get('dllexport'):
  219. tag = 'dllexport_python '
  220. else:
  221. tag = 'function '
  222. self._declare(tag + decl.name, tp)
  223. def _parse_typedef(self, decl):
  224. if not decl.name:
  225. raise CDefError("typedef does not declare any name", decl)
  226. realtype, quals = self._get_type_and_quals(
  227. decl.type, name=decl.name, partial_length_ok=True)
  228. tp = model.DefinedType(decl.name, realtype, quals)
  229. self._declare('typedef ' + decl.name, tp)
  230. def _parse_decl(self, decl):
  231. node = decl.type
  232. if isinstance(node, pycparser.c_ast.FuncDecl):
  233. tp, quals = self._get_type_and_quals(node, name=decl.name)
  234. assert isinstance(tp, model.RawFunctionType)
  235. self._declare_function(tp, quals, decl)
  236. else:
  237. if isinstance(node, pycparser.c_ast.Struct):
  238. self._get_struct_union_enum_type('struct', node)
  239. elif isinstance(node, pycparser.c_ast.Union):
  240. self._get_struct_union_enum_type('union', node)
  241. elif isinstance(node, pycparser.c_ast.Enum):
  242. self._get_struct_union_enum_type('enum', node)
  243. elif not decl.name:
  244. raise CDefError("construct does not declare any variable",
  245. decl)
  246. #
  247. if decl.name:
  248. tp, quals = self._get_type_and_quals(node,
  249. partial_length_ok=True)
  250. if tp.is_raw_function:
  251. self._declare_function(tp, quals, decl)
  252. elif (tp.is_integer_type() and
  253. hasattr(decl, 'init') and
  254. hasattr(decl.init, 'value') and
  255. _r_int_literal.match(decl.init.value)):
  256. self._add_integer_constant(decl.name, decl.init.value)
  257. elif (tp.is_integer_type() and
  258. isinstance(decl.init, pycparser.c_ast.UnaryOp) and
  259. decl.init.op == '-' and
  260. hasattr(decl.init.expr, 'value') and
  261. _r_int_literal.match(decl.init.expr.value)):
  262. self._add_integer_constant(decl.name,
  263. '-' + decl.init.expr.value)
  264. else:
  265. if (quals & model.Q_CONST) and not tp.is_array_type:
  266. self._declare('constant ' + decl.name, tp, quals=quals)
  267. else:
  268. self._declare('variable ' + decl.name, tp, quals=quals)
  269. def parse_type(self, cdecl):
  270. return self.parse_type_and_quals(cdecl)[0]
  271. def parse_type_and_quals(self, cdecl):
  272. ast, _, _ = self._parse('void __dummy(\n%s\n);' % cdecl)
  273. exprnode = ast.ext[-1].type.args.params[0]
  274. if isinstance(exprnode, pycparser.c_ast.ID):
  275. raise CDefError("unknown identifier '%s'" % (exprnode.name,))
  276. return self._get_type_and_quals(exprnode.type)
  277. def _declare(self, name, obj, included=False, quals=0):
  278. if name in self._declarations:
  279. prevobj, prevquals = self._declarations[name]
  280. if prevobj is obj and prevquals == quals:
  281. return
  282. self._declarations[name] = (obj, quals)
  283. if included:
  284. self._included_declarations.add(obj)
  285. def _extract_quals(self, type):
  286. quals = 0
  287. if isinstance(type, (pycparser.c_ast.TypeDecl,
  288. pycparser.c_ast.PtrDecl)):
  289. if 'const' in type.quals:
  290. quals |= model.Q_CONST
  291. if 'volatile' in type.quals:
  292. quals |= model.Q_VOLATILE
  293. if 'restrict' in type.quals:
  294. quals |= model.Q_RESTRICT
  295. return quals
  296. def _get_type_pointer(self, type, quals, declname=None):
  297. if isinstance(type, model.RawFunctionType):
  298. return type.as_function_pointer()
  299. if (isinstance(type, model.StructOrUnionOrEnum) and
  300. type.name.startswith('$') and type.name[1:].isdigit() and
  301. type.forcename is None and declname is not None):
  302. return model.NamedPointerType(type, declname, quals)
  303. return model.PointerType(type, quals)
  304. def _get_type_and_quals(self, typenode, name=None, partial_length_ok=False):
  305. if isinstance(typenode, pycparser.c_ast.ArrayDecl):
  306. # array type
  307. if typenode.dim is None:
  308. length = None
  309. else:
  310. length = self._parse_constant(
  311. typenode.dim, partial_length_ok=partial_length_ok)
  312. tp, quals = self._get_type_and_quals(typenode.type,
  313. partial_length_ok=partial_length_ok)
  314. return model.ArrayType(tp, length), quals
  315. #
  316. if isinstance(typenode, pycparser.c_ast.PtrDecl):
  317. # pointer type
  318. itemtype, itemquals = self._get_type_and_quals(typenode.type)
  319. tp = self._get_type_pointer(itemtype, itemquals, declname=name)
  320. quals = self._extract_quals(typenode)
  321. return tp, quals
  322. #
  323. if isinstance(typenode, pycparser.c_ast.TypeDecl):
  324. quals = self._extract_quals(typenode)
  325. type = typenode.type
  326. if isinstance(type, pycparser.c_ast.IdentifierType):
  327. # first, dereference typedefs, if we have it already parsed, we're good
  328. if (len(type.names) == 1 and
  329. ('typedef ' + type.names[0]) in self._declarations):
  330. tp0, quals0 = self._declarations['typedef ' + type.names[0]]
  331. return tp0, (quals | quals0)
  332. # assume a primitive type. get it from .names, but reduce
  333. # synonyms to a single chosen combination
  334. names = list(type.names)
  335. if names != ['signed', 'char']: # keep this unmodified
  336. prefixes = {}
  337. while names:
  338. name = names[0]
  339. if name in ('short', 'long', 'signed', 'unsigned'):
  340. prefixes[name] = prefixes.get(name, 0) + 1
  341. del names[0]
  342. else:
  343. break
  344. # ignore the 'signed' prefix below, and reorder the others
  345. newnames = []
  346. for prefix in ('unsigned', 'short', 'long'):
  347. for i in range(prefixes.get(prefix, 0)):
  348. newnames.append(prefix)
  349. if not names:
  350. names = ['int'] # implicitly
  351. if names == ['int']: # but kill it if 'short' or 'long'
  352. if 'short' in prefixes or 'long' in prefixes:
  353. names = []
  354. names = newnames + names
  355. ident = ' '.join(names)
  356. if ident == 'void':
  357. return model.void_type, quals
  358. tp0, quals0 = resolve_common_type(self, ident)
  359. return tp0, (quals | quals0)
  360. #
  361. if isinstance(type, pycparser.c_ast.Struct):
  362. # 'struct foobar'
  363. tp = self._get_struct_union_enum_type('struct', type, name)
  364. return tp, quals
  365. #
  366. if isinstance(type, pycparser.c_ast.Union):
  367. # 'union foobar'
  368. tp = self._get_struct_union_enum_type('union', type, name)
  369. return tp, quals
  370. #
  371. if isinstance(type, pycparser.c_ast.Enum):
  372. # 'enum foobar'
  373. tp = self._get_struct_union_enum_type('enum', type, name)
  374. return tp, quals
  375. #
  376. if isinstance(typenode, pycparser.c_ast.FuncDecl):
  377. # a function type
  378. return self._parse_function_type(typenode, name), 0
  379. #
  380. # nested anonymous structs or unions end up here
  381. if isinstance(typenode, pycparser.c_ast.Struct):
  382. return self._get_struct_union_enum_type('struct', typenode, name,
  383. nested=True), 0
  384. if isinstance(typenode, pycparser.c_ast.Union):
  385. return self._get_struct_union_enum_type('union', typenode, name,
  386. nested=True), 0
  387. #
  388. raise FFIError(":%d: bad or unsupported type declaration" %
  389. typenode.coord.line)
  390. def _parse_function_type(self, typenode, funcname=None):
  391. params = list(getattr(typenode.args, 'params', []))
  392. for i, arg in enumerate(params):
  393. if not hasattr(arg, 'type'):
  394. raise CDefError("%s arg %d: unknown type '%s'"
  395. " (if you meant to use the old C syntax of giving"
  396. " untyped arguments, it is not supported)"
  397. % (funcname or 'in expression', i + 1,
  398. getattr(arg, 'name', '?')))
  399. ellipsis = (
  400. len(params) > 0 and
  401. isinstance(params[-1].type, pycparser.c_ast.TypeDecl) and
  402. isinstance(params[-1].type.type,
  403. pycparser.c_ast.IdentifierType) and
  404. params[-1].type.type.names == ['__dotdotdot__'])
  405. if ellipsis:
  406. params.pop()
  407. if not params:
  408. raise CDefError(
  409. "%s: a function with only '(...)' as argument"
  410. " is not correct C" % (funcname or 'in expression'))
  411. args = [self._as_func_arg(*self._get_type_and_quals(argdeclnode.type))
  412. for argdeclnode in params]
  413. if not ellipsis and args == [model.void_type]:
  414. args = []
  415. result, quals = self._get_type_and_quals(typenode.type)
  416. # the 'quals' on the result type are ignored. HACK: we absure them
  417. # to detect __stdcall functions: we textually replace "__stdcall"
  418. # with "volatile volatile const" above.
  419. abi = None
  420. if hasattr(typenode.type, 'quals'): # else, probable syntax error anyway
  421. if typenode.type.quals[-3:] == ['volatile', 'volatile', 'const']:
  422. abi = '__stdcall'
  423. return model.RawFunctionType(tuple(args), result, ellipsis, abi)
  424. def _as_func_arg(self, type, quals):
  425. if isinstance(type, model.ArrayType):
  426. return model.PointerType(type.item, quals)
  427. elif isinstance(type, model.RawFunctionType):
  428. return type.as_function_pointer()
  429. else:
  430. return type
  431. def _get_struct_union_enum_type(self, kind, type, name=None, nested=False):
  432. # First, a level of caching on the exact 'type' node of the AST.
  433. # This is obscure, but needed because pycparser "unrolls" declarations
  434. # such as "typedef struct { } foo_t, *foo_p" and we end up with
  435. # an AST that is not a tree, but a DAG, with the "type" node of the
  436. # two branches foo_t and foo_p of the trees being the same node.
  437. # It's a bit silly but detecting "DAG-ness" in the AST tree seems
  438. # to be the only way to distinguish this case from two independent
  439. # structs. See test_struct_with_two_usages.
  440. try:
  441. return self._structnode2type[type]
  442. except KeyError:
  443. pass
  444. #
  445. # Note that this must handle parsing "struct foo" any number of
  446. # times and always return the same StructType object. Additionally,
  447. # one of these times (not necessarily the first), the fields of
  448. # the struct can be specified with "struct foo { ...fields... }".
  449. # If no name is given, then we have to create a new anonymous struct
  450. # with no caching; in this case, the fields are either specified
  451. # right now or never.
  452. #
  453. force_name = name
  454. name = type.name
  455. #
  456. # get the type or create it if needed
  457. if name is None:
  458. # 'force_name' is used to guess a more readable name for
  459. # anonymous structs, for the common case "typedef struct { } foo".
  460. if force_name is not None:
  461. explicit_name = '$%s' % force_name
  462. else:
  463. self._anonymous_counter += 1
  464. explicit_name = '$%d' % self._anonymous_counter
  465. tp = None
  466. else:
  467. explicit_name = name
  468. key = '%s %s' % (kind, name)
  469. tp, _ = self._declarations.get(key, (None, None))
  470. #
  471. if tp is None:
  472. if kind == 'struct':
  473. tp = model.StructType(explicit_name, None, None, None)
  474. elif kind == 'union':
  475. tp = model.UnionType(explicit_name, None, None, None)
  476. elif kind == 'enum':
  477. tp = self._build_enum_type(explicit_name, type.values)
  478. else:
  479. raise AssertionError("kind = %r" % (kind,))
  480. if name is not None:
  481. self._declare(key, tp)
  482. else:
  483. if kind == 'enum' and type.values is not None:
  484. raise NotImplementedError(
  485. "enum %s: the '{}' declaration should appear on the first "
  486. "time the enum is mentioned, not later" % explicit_name)
  487. if not tp.forcename:
  488. tp.force_the_name(force_name)
  489. if tp.forcename and '$' in tp.name:
  490. self._declare('anonymous %s' % tp.forcename, tp)
  491. #
  492. self._structnode2type[type] = tp
  493. #
  494. # enums: done here
  495. if kind == 'enum':
  496. return tp
  497. #
  498. # is there a 'type.decls'? If yes, then this is the place in the
  499. # C sources that declare the fields. If no, then just return the
  500. # existing type, possibly still incomplete.
  501. if type.decls is None:
  502. return tp
  503. #
  504. if tp.fldnames is not None:
  505. raise CDefError("duplicate declaration of struct %s" % name)
  506. fldnames = []
  507. fldtypes = []
  508. fldbitsize = []
  509. fldquals = []
  510. for decl in type.decls:
  511. if decl.bitsize is None:
  512. bitsize = -1
  513. else:
  514. bitsize = self._parse_constant(decl.bitsize)
  515. self._partial_length = False
  516. type, fqual = self._get_type_and_quals(decl.type,
  517. partial_length_ok=True)
  518. if self._partial_length:
  519. self._make_partial(tp, nested)
  520. if isinstance(type, model.StructType) and type.partial:
  521. self._make_partial(tp, nested)
  522. fldnames.append(decl.name or '')
  523. fldtypes.append(type)
  524. fldbitsize.append(bitsize)
  525. fldquals.append(fqual)
  526. tp.fldnames = tuple(fldnames)
  527. tp.fldtypes = tuple(fldtypes)
  528. tp.fldbitsize = tuple(fldbitsize)
  529. tp.fldquals = tuple(fldquals)
  530. if fldbitsize != [-1] * len(fldbitsize):
  531. if isinstance(tp, model.StructType) and tp.partial:
  532. raise NotImplementedError("%s: using both bitfields and '...;'"
  533. % (tp,))
  534. tp.packed = self._options.get('packed')
  535. if tp.completed: # must be re-completed: it is not opaque any more
  536. tp.completed = 0
  537. self._recomplete.append(tp)
  538. return tp
  539. def _make_partial(self, tp, nested):
  540. if not isinstance(tp, model.StructOrUnion):
  541. raise CDefError("%s cannot be partial" % (tp,))
  542. if not tp.has_c_name() and not nested:
  543. raise NotImplementedError("%s is partial but has no C name" %(tp,))
  544. tp.partial = True
  545. def _parse_constant(self, exprnode, partial_length_ok=False):
  546. # for now, limited to expressions that are an immediate number
  547. # or positive/negative number
  548. if isinstance(exprnode, pycparser.c_ast.Constant):
  549. s = exprnode.value
  550. if s.startswith('0'):
  551. if s.startswith('0x') or s.startswith('0X'):
  552. return int(s, 16)
  553. return int(s, 8)
  554. elif '1' <= s[0] <= '9':
  555. return int(s, 10)
  556. elif s[0] == "'" and s[-1] == "'" and (
  557. len(s) == 3 or (len(s) == 4 and s[1] == "\\")):
  558. return ord(s[-2])
  559. else:
  560. raise CDefError("invalid constant %r" % (s,))
  561. #
  562. if (isinstance(exprnode, pycparser.c_ast.UnaryOp) and
  563. exprnode.op == '+'):
  564. return self._parse_constant(exprnode.expr)
  565. #
  566. if (isinstance(exprnode, pycparser.c_ast.UnaryOp) and
  567. exprnode.op == '-'):
  568. return -self._parse_constant(exprnode.expr)
  569. # load previously defined int constant
  570. if (isinstance(exprnode, pycparser.c_ast.ID) and
  571. exprnode.name in self._int_constants):
  572. return self._int_constants[exprnode.name]
  573. #
  574. if (isinstance(exprnode, pycparser.c_ast.ID) and
  575. exprnode.name == '__dotdotdotarray__'):
  576. if partial_length_ok:
  577. self._partial_length = True
  578. return '...'
  579. raise FFIError(":%d: unsupported '[...]' here, cannot derive "
  580. "the actual array length in this context"
  581. % exprnode.coord.line)
  582. #
  583. raise FFIError(":%d: unsupported expression: expected a "
  584. "simple numeric constant" % exprnode.coord.line)
  585. def _build_enum_type(self, explicit_name, decls):
  586. if decls is not None:
  587. partial = False
  588. enumerators = []
  589. enumvalues = []
  590. nextenumvalue = 0
  591. for enum in decls.enumerators:
  592. if enum.value is not None:
  593. nextenumvalue = self._parse_constant(enum.value)
  594. enumerators.append(enum.name)
  595. enumvalues.append(nextenumvalue)
  596. self._add_constants(enum.name, nextenumvalue)
  597. nextenumvalue += 1
  598. enumerators = tuple(enumerators)
  599. enumvalues = tuple(enumvalues)
  600. tp = model.EnumType(explicit_name, enumerators, enumvalues)
  601. tp.partial = partial
  602. else: # opaque enum
  603. tp = model.EnumType(explicit_name, (), ())
  604. return tp
  605. def include(self, other):
  606. for name, (tp, quals) in other._declarations.items():
  607. if name.startswith('anonymous $enum_$'):
  608. continue # fix for test_anonymous_enum_include
  609. kind = name.split(' ', 1)[0]
  610. if kind in ('struct', 'union', 'enum', 'anonymous', 'typedef', 'macro'):
  611. self._declare(name, tp, included=True, quals=quals)
  612. for k, v in other._int_constants.items():
  613. self._add_constants(k, v)
  614. for k, v in other._macros.items():
  615. self._macros[k] = v
  616. CNAME_TO_LLTYPE = {
  617. 'char': rffi.CHAR,
  618. 'double': rffi.DOUBLE, 'long double': rffi.LONGDOUBLE,
  619. 'float': rffi.FLOAT, 'FILE': FILEP.TO}
  620. def add_inttypes():
  621. for name in rffi.TYPES:
  622. if name.startswith('unsigned'):
  623. rname = 'u' + name[9:]
  624. else:
  625. rname = name
  626. rname = rname.replace(' ', '').upper()
  627. CNAME_TO_LLTYPE[name] = rfficache.platform.types[rname]
  628. add_inttypes()
  629. CNAME_TO_LLTYPE['int'] = rffi.INT_real
  630. CNAME_TO_LLTYPE['wchar_t'] = lltype.UniChar
  631. if 'ssize_t' not in CNAME_TO_LLTYPE: # on Windows
  632. CNAME_TO_LLTYPE['ssize_t'] = CNAME_TO_LLTYPE['long']
  633. def cname_to_lltype(name):
  634. return CNAME_TO_LLTYPE[name]
  635. class DelayedStruct(object):
  636. def __init__(self, name, fields, TYPE):
  637. self.struct_name = name
  638. self.type_name = None
  639. self.fields = fields
  640. self.TYPE = TYPE
  641. def get_type_name(self):
  642. if self.type_name is not None:
  643. return self.type_name
  644. elif not self.struct_name.startswith('$'):
  645. return 'struct %s' % self.struct_name
  646. else:
  647. raise ValueError('Anonymous struct')
  648. def __repr__(self):
  649. return "<struct {struct_name}>".format(**vars(self))
  650. class CTypeSpace(object):
  651. def __init__(self, parser=None, definitions=None, macros=None,
  652. headers=None, includes=None):
  653. self.definitions = definitions if definitions is not None else {}
  654. self.macros = macros if macros is not None else {}
  655. self.structs = {}
  656. self.ctx = parser if parser else Parser()
  657. self.headers = headers if headers is not None else ['sys/types.h']
  658. self.parsed_headers = []
  659. self.sources = []
  660. self._config_entries = OrderedDict()
  661. self.includes = []
  662. self.struct_typedefs = {}
  663. self._handled = set()
  664. self._frozen = False
  665. if includes is not None:
  666. for header in includes:
  667. self.include(header)
  668. def include(self, other):
  669. self.ctx.include(other.ctx)
  670. self.structs.update(other.structs)
  671. self.includes.append(other)
  672. def parse_source(self, source):
  673. self.sources.append(source)
  674. self.ctx.parse(source)
  675. self.configure_types()
  676. def parse_header(self, header_path):
  677. self.headers.append(str(header_path))
  678. self.parsed_headers.append(header_path)
  679. self.ctx.parse(header_path.read())
  680. self.configure_types()
  681. def add_typedef(self, name, obj, quals):
  682. assert name not in self.definitions
  683. tp = self.convert_type(obj, quals)
  684. if isinstance(tp, DelayedStruct):
  685. if tp.type_name is None:
  686. tp.type_name = name
  687. tp = self.realize_struct(tp)
  688. self.definitions[name] = tp
  689. def add_macro(self, name, value):
  690. assert name not in self.macros
  691. self.macros[name] = value
  692. def new_struct(self, obj):
  693. if obj.name == '_IO_FILE': # cffi weirdness
  694. return cname_to_lltype('FILE')
  695. struct = DelayedStruct(obj.name, None, lltype.ForwardReference())
  696. # Cache it early, to avoid infinite recursion
  697. self.structs[obj] = struct
  698. if obj.fldtypes is not None:
  699. struct.fields = zip(
  700. obj.fldnames,
  701. [self.convert_field(field) for field in obj.fldtypes])
  702. return struct
  703. def convert_field(self, obj):
  704. tp = self.convert_type(obj)
  705. if isinstance(tp, DelayedStruct):
  706. tp = tp.TYPE
  707. return tp
  708. def realize_struct(self, struct):
  709. type_name = struct.get_type_name()
  710. entry = rffi_platform.Struct(type_name, struct.fields)
  711. self._config_entries[entry] = struct.TYPE
  712. return struct.TYPE
  713. def build_eci(self):
  714. all_sources = []
  715. for cts in self.includes:
  716. all_sources.extend(cts.sources)
  717. all_sources.extend(self.sources)
  718. all_headers = self.headers
  719. for x in self.includes:
  720. for hdr in x.headers:
  721. if hdr not in all_headers:
  722. all_headers.append(hdr)
  723. if sys.platform == 'win32':
  724. compile_extra = ['-Dssize_t=long']
  725. else:
  726. compile_extra = []
  727. return ExternalCompilationInfo(
  728. post_include_bits=all_sources, includes=all_headers,
  729. compile_extra=compile_extra)
  730. def configure_types(self):
  731. for name, (obj, quals) in self.ctx._declarations.iteritems():
  732. if obj in self.ctx._included_declarations:
  733. continue
  734. if name in self._handled:
  735. continue
  736. self._handled.add(name)
  737. if name.startswith('typedef '):
  738. name = name[8:]
  739. self.add_typedef(name, obj, quals)
  740. elif name.startswith('macro '):
  741. name = name[6:]
  742. self.add_macro(name, obj)
  743. if not self._config_entries:
  744. return
  745. eci = self.build_eci()
  746. result = rffi_platform.configure_entries(list(self._config_entries), eci)
  747. for entry, TYPE in izip(self._config_entries, result):
  748. # hack: prevent the source from being pasted into common_header.h
  749. del TYPE._hints['eci']
  750. self._config_entries[entry].become(TYPE)
  751. self._config_entries.clear()
  752. def convert_type(self, obj, quals=0):
  753. if isinstance(obj, model.DefinedType):
  754. return self.convert_type(obj.realtype, obj.quals)
  755. if isinstance(obj, model.PrimitiveType):
  756. return cname_to_lltype(obj.name)
  757. elif isinstance(obj, model.StructType):
  758. if obj in self.structs:
  759. return self.structs[obj]
  760. return self.new_struct(obj)
  761. elif isinstance(obj, model.PointerType):
  762. TO = self.convert_type(obj.totype)
  763. if TO is lltype.Void:
  764. return rffi.VOIDP
  765. elif isinstance(TO, DelayedStruct):
  766. TO = TO.TYPE
  767. if isinstance(TO, lltype.ContainerType):
  768. return lltype.Ptr(TO)
  769. else:
  770. if obj.quals & model.Q_CONST:
  771. return lltype.Ptr(lltype.Array(
  772. TO, hints={'nolength': True, 'render_as_const': True}))
  773. else:
  774. return rffi.CArrayPtr(TO)
  775. elif isinstance(obj, model.FunctionPtrType):
  776. if obj.ellipsis:
  777. raise NotImplementedError
  778. args = [self.convert_type(arg) for arg in obj.args]
  779. res = self.convert_type(obj.result)
  780. return lltype.Ptr(lltype.FuncType(args, res))
  781. elif isinstance(obj, model.VoidType):
  782. return lltype.Void
  783. elif isinstance(obj, model.ArrayType):
  784. return rffi.CFixedArray(self.convert_type(obj.item), obj.length)
  785. else:
  786. raise NotImplementedError
  787. def gettype(self, cdecl):
  788. obj = self.ctx.parse_type(cdecl)
  789. result = self.convert_type(obj)
  790. if isinstance(result, DelayedStruct):
  791. result = result.TYPE
  792. return result
  793. def cast(self, cdecl, value):
  794. return rffi.cast(self.gettype(cdecl), value)
  795. def parse_func(self, cdecl):
  796. cdecl = cdecl.strip()
  797. if cdecl[-1] != ';':
  798. cdecl += ';'
  799. ast, _, _ = self.ctx._parse(cdecl)
  800. decl = ast.ext[-1]
  801. tp, quals = self.ctx._get_type_and_quals(decl.type, name=decl.name)
  802. return FunctionDeclaration(decl.name, tp)
  803. def _freeze_(self):
  804. if self._frozen:
  805. return True
  806. @register_flow_sc(self.cast)
  807. def sc_cast(ctx, v_decl, v_arg):
  808. if not isinstance(v_decl, Constant):
  809. raise FlowingError(
  810. "The first argument of cts.cast() must be a constant.")
  811. TP = self.gettype(v_decl.value)
  812. return ctx.appcall(rffi.cast, const(TP), v_arg)
  813. @register_flow_sc(self.gettype)
  814. def sc_gettype(ctx, v_decl):
  815. if not isinstance(v_decl, Constant):
  816. raise FlowingError(
  817. "The argument of cts.gettype() must be a constant.")
  818. return const(self.gettype(v_decl.value))
  819. self._frozen = True
  820. return True
  821. class FunctionDeclaration(object):
  822. def __init__(self, name, tp):
  823. self.name = name
  824. self.tp = tp
  825. def get_llargs(self, cts):
  826. return [cts.convert_type(arg) for arg in self.tp.args]
  827. def get_llresult(self, cts):
  828. return cts.convert_type(self.tp.result)
  829. def parse_source(source, includes=None, headers=None, configure_now=True):
  830. cts = CTypeSpace(headers=headers, includes=includes)
  831. cts.parse_source(source)
  832. return cts