github.com/whamcloud/lemur@v0.0.0-20190827193804-4655df8a52af/packaging/ci/lambda/GitPullS3/cffi/vengine_gen.py (about)

     1  #
     2  # DEPRECATED: implementation for ffi.verify()
     3  #
     4  import sys, os
     5  import types
     6  
     7  from . import model, ffiplatform
     8  
     9  
    10  class VGenericEngine(object):
    11      _class_key = 'g'
    12      _gen_python_module = False
    13  
    14      def __init__(self, verifier):
    15          self.verifier = verifier
    16          self.ffi = verifier.ffi
    17          self.export_symbols = []
    18          self._struct_pending_verification = {}
    19  
    20      def patch_extension_kwds(self, kwds):
    21          # add 'export_symbols' to the dictionary.  Note that we add the
    22          # list before filling it.  When we fill it, it will thus also show
    23          # up in kwds['export_symbols'].
    24          kwds.setdefault('export_symbols', self.export_symbols)
    25  
    26      def find_module(self, module_name, path, so_suffixes):
    27          for so_suffix in so_suffixes:
    28              basename = module_name + so_suffix
    29              if path is None:
    30                  path = sys.path
    31              for dirname in path:
    32                  filename = os.path.join(dirname, basename)
    33                  if os.path.isfile(filename):
    34                      return filename
    35  
    36      def collect_types(self):
    37          pass      # not needed in the generic engine
    38  
    39      def _prnt(self, what=''):
    40          self._f.write(what + '\n')
    41  
    42      def write_source_to_f(self):
    43          prnt = self._prnt
    44          # first paste some standard set of lines that are mostly '#include'
    45          prnt(cffimod_header)
    46          # then paste the C source given by the user, verbatim.
    47          prnt(self.verifier.preamble)
    48          #
    49          # call generate_gen_xxx_decl(), for every xxx found from
    50          # ffi._parser._declarations.  This generates all the functions.
    51          self._generate('decl')
    52          #
    53          # on Windows, distutils insists on putting init_cffi_xyz in
    54          # 'export_symbols', so instead of fighting it, just give up and
    55          # give it one
    56          if sys.platform == 'win32':
    57              if sys.version_info >= (3,):
    58                  prefix = 'PyInit_'
    59              else:
    60                  prefix = 'init'
    61              modname = self.verifier.get_module_name()
    62              prnt("void %s%s(void) { }\n" % (prefix, modname))
    63  
    64      def load_library(self, flags=0):
    65          # import it with the CFFI backend
    66          backend = self.ffi._backend
    67          # needs to make a path that contains '/', on Posix
    68          filename = os.path.join(os.curdir, self.verifier.modulefilename)
    69          module = backend.load_library(filename, flags)
    70          #
    71          # call loading_gen_struct() to get the struct layout inferred by
    72          # the C compiler
    73          self._load(module, 'loading')
    74  
    75          # build the FFILibrary class and instance, this is a module subclass
    76          # because modules are expected to have usually-constant-attributes and
    77          # in PyPy this means the JIT is able to treat attributes as constant,
    78          # which we want.
    79          class FFILibrary(types.ModuleType):
    80              _cffi_generic_module = module
    81              _cffi_ffi = self.ffi
    82              _cffi_dir = []
    83              def __dir__(self):
    84                  return FFILibrary._cffi_dir
    85          library = FFILibrary("")
    86          #
    87          # finally, call the loaded_gen_xxx() functions.  This will set
    88          # up the 'library' object.
    89          self._load(module, 'loaded', library=library)
    90          return library
    91  
    92      def _get_declarations(self):
    93          lst = [(key, tp) for (key, (tp, qual)) in
    94                                  self.ffi._parser._declarations.items()]
    95          lst.sort()
    96          return lst
    97  
    98      def _generate(self, step_name):
    99          for name, tp in self._get_declarations():
   100              kind, realname = name.split(' ', 1)
   101              try:
   102                  method = getattr(self, '_generate_gen_%s_%s' % (kind,
   103                                                                  step_name))
   104              except AttributeError:
   105                  raise ffiplatform.VerificationError(
   106                      "not implemented in verify(): %r" % name)
   107              try:
   108                  method(tp, realname)
   109              except Exception as e:
   110                  model.attach_exception_info(e, name)
   111                  raise
   112  
   113      def _load(self, module, step_name, **kwds):
   114          for name, tp in self._get_declarations():
   115              kind, realname = name.split(' ', 1)
   116              method = getattr(self, '_%s_gen_%s' % (step_name, kind))
   117              try:
   118                  method(tp, realname, module, **kwds)
   119              except Exception as e:
   120                  model.attach_exception_info(e, name)
   121                  raise
   122  
   123      def _generate_nothing(self, tp, name):
   124          pass
   125  
   126      def _loaded_noop(self, tp, name, module, **kwds):
   127          pass
   128  
   129      # ----------
   130      # typedefs: generates no code so far
   131  
   132      _generate_gen_typedef_decl   = _generate_nothing
   133      _loading_gen_typedef         = _loaded_noop
   134      _loaded_gen_typedef          = _loaded_noop
   135  
   136      # ----------
   137      # function declarations
   138  
   139      def _generate_gen_function_decl(self, tp, name):
   140          assert isinstance(tp, model.FunctionPtrType)
   141          if tp.ellipsis:
   142              # cannot support vararg functions better than this: check for its
   143              # exact type (including the fixed arguments), and build it as a
   144              # constant function pointer (no _cffi_f_%s wrapper)
   145              self._generate_gen_const(False, name, tp)
   146              return
   147          prnt = self._prnt
   148          numargs = len(tp.args)
   149          argnames = []
   150          for i, type in enumerate(tp.args):
   151              indirection = ''
   152              if isinstance(type, model.StructOrUnion):
   153                  indirection = '*'
   154              argnames.append('%sx%d' % (indirection, i))
   155          context = 'argument of %s' % name
   156          arglist = [type.get_c_name(' %s' % arg, context)
   157                     for type, arg in zip(tp.args, argnames)]
   158          tpresult = tp.result
   159          if isinstance(tpresult, model.StructOrUnion):
   160              arglist.insert(0, tpresult.get_c_name(' *r', context))
   161              tpresult = model.void_type
   162          arglist = ', '.join(arglist) or 'void'
   163          wrappername = '_cffi_f_%s' % name
   164          self.export_symbols.append(wrappername)
   165          if tp.abi:
   166              abi = tp.abi + ' '
   167          else:
   168              abi = ''
   169          funcdecl = ' %s%s(%s)' % (abi, wrappername, arglist)
   170          context = 'result of %s' % name
   171          prnt(tpresult.get_c_name(funcdecl, context))
   172          prnt('{')
   173          #
   174          if isinstance(tp.result, model.StructOrUnion):
   175              result_code = '*r = '
   176          elif not isinstance(tp.result, model.VoidType):
   177              result_code = 'return '
   178          else:
   179              result_code = ''
   180          prnt('  %s%s(%s);' % (result_code, name, ', '.join(argnames)))
   181          prnt('}')
   182          prnt()
   183  
   184      _loading_gen_function = _loaded_noop
   185  
   186      def _loaded_gen_function(self, tp, name, module, library):
   187          assert isinstance(tp, model.FunctionPtrType)
   188          if tp.ellipsis:
   189              newfunction = self._load_constant(False, tp, name, module)
   190          else:
   191              indirections = []
   192              base_tp = tp
   193              if (any(isinstance(typ, model.StructOrUnion) for typ in tp.args)
   194                      or isinstance(tp.result, model.StructOrUnion)):
   195                  indirect_args = []
   196                  for i, typ in enumerate(tp.args):
   197                      if isinstance(typ, model.StructOrUnion):
   198                          typ = model.PointerType(typ)
   199                          indirections.append((i, typ))
   200                      indirect_args.append(typ)
   201                  indirect_result = tp.result
   202                  if isinstance(indirect_result, model.StructOrUnion):
   203                      if indirect_result.fldtypes is None:
   204                          raise TypeError("'%s' is used as result type, "
   205                                          "but is opaque" % (
   206                                              indirect_result._get_c_name(),))
   207                      indirect_result = model.PointerType(indirect_result)
   208                      indirect_args.insert(0, indirect_result)
   209                      indirections.insert(0, ("result", indirect_result))
   210                      indirect_result = model.void_type
   211                  tp = model.FunctionPtrType(tuple(indirect_args),
   212                                             indirect_result, tp.ellipsis)
   213              BFunc = self.ffi._get_cached_btype(tp)
   214              wrappername = '_cffi_f_%s' % name
   215              newfunction = module.load_function(BFunc, wrappername)
   216              for i, typ in indirections:
   217                  newfunction = self._make_struct_wrapper(newfunction, i, typ,
   218                                                          base_tp)
   219          setattr(library, name, newfunction)
   220          type(library)._cffi_dir.append(name)
   221  
   222      def _make_struct_wrapper(self, oldfunc, i, tp, base_tp):
   223          backend = self.ffi._backend
   224          BType = self.ffi._get_cached_btype(tp)
   225          if i == "result":
   226              ffi = self.ffi
   227              def newfunc(*args):
   228                  res = ffi.new(BType)
   229                  oldfunc(res, *args)
   230                  return res[0]
   231          else:
   232              def newfunc(*args):
   233                  args = args[:i] + (backend.newp(BType, args[i]),) + args[i+1:]
   234                  return oldfunc(*args)
   235          newfunc._cffi_base_type = base_tp
   236          return newfunc
   237  
   238      # ----------
   239      # named structs
   240  
   241      def _generate_gen_struct_decl(self, tp, name):
   242          assert name == tp.name
   243          self._generate_struct_or_union_decl(tp, 'struct', name)
   244  
   245      def _loading_gen_struct(self, tp, name, module):
   246          self._loading_struct_or_union(tp, 'struct', name, module)
   247  
   248      def _loaded_gen_struct(self, tp, name, module, **kwds):
   249          self._loaded_struct_or_union(tp)
   250  
   251      def _generate_gen_union_decl(self, tp, name):
   252          assert name == tp.name
   253          self._generate_struct_or_union_decl(tp, 'union', name)
   254  
   255      def _loading_gen_union(self, tp, name, module):
   256          self._loading_struct_or_union(tp, 'union', name, module)
   257  
   258      def _loaded_gen_union(self, tp, name, module, **kwds):
   259          self._loaded_struct_or_union(tp)
   260  
   261      def _generate_struct_or_union_decl(self, tp, prefix, name):
   262          if tp.fldnames is None:
   263              return     # nothing to do with opaque structs
   264          checkfuncname = '_cffi_check_%s_%s' % (prefix, name)
   265          layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name)
   266          cname = ('%s %s' % (prefix, name)).strip()
   267          #
   268          prnt = self._prnt
   269          prnt('static void %s(%s *p)' % (checkfuncname, cname))
   270          prnt('{')
   271          prnt('  /* only to generate compile-time warnings or errors */')
   272          prnt('  (void)p;')
   273          for fname, ftype, fbitsize, fqual in tp.enumfields():
   274              if (isinstance(ftype, model.PrimitiveType)
   275                  and ftype.is_integer_type()) or fbitsize >= 0:
   276                  # accept all integers, but complain on float or double
   277                  prnt('  (void)((p->%s) << 1);' % fname)
   278              else:
   279                  # only accept exactly the type declared.
   280                  try:
   281                      prnt('  { %s = &p->%s; (void)tmp; }' % (
   282                          ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual),
   283                          fname))
   284                  except ffiplatform.VerificationError as e:
   285                      prnt('  /* %s */' % str(e))   # cannot verify it, ignore
   286          prnt('}')
   287          self.export_symbols.append(layoutfuncname)
   288          prnt('intptr_t %s(intptr_t i)' % (layoutfuncname,))
   289          prnt('{')
   290          prnt('  struct _cffi_aligncheck { char x; %s y; };' % cname)
   291          prnt('  static intptr_t nums[] = {')
   292          prnt('    sizeof(%s),' % cname)
   293          prnt('    offsetof(struct _cffi_aligncheck, y),')
   294          for fname, ftype, fbitsize, fqual in tp.enumfields():
   295              if fbitsize >= 0:
   296                  continue      # xxx ignore fbitsize for now
   297              prnt('    offsetof(%s, %s),' % (cname, fname))
   298              if isinstance(ftype, model.ArrayType) and ftype.length is None:
   299                  prnt('    0,  /* %s */' % ftype._get_c_name())
   300              else:
   301                  prnt('    sizeof(((%s *)0)->%s),' % (cname, fname))
   302          prnt('    -1')
   303          prnt('  };')
   304          prnt('  return nums[i];')
   305          prnt('  /* the next line is not executed, but compiled */')
   306          prnt('  %s(0);' % (checkfuncname,))
   307          prnt('}')
   308          prnt()
   309  
   310      def _loading_struct_or_union(self, tp, prefix, name, module):
   311          if tp.fldnames is None:
   312              return     # nothing to do with opaque structs
   313          layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name)
   314          #
   315          BFunc = self.ffi._typeof_locked("intptr_t(*)(intptr_t)")[0]
   316          function = module.load_function(BFunc, layoutfuncname)
   317          layout = []
   318          num = 0
   319          while True:
   320              x = function(num)
   321              if x < 0: break
   322              layout.append(x)
   323              num += 1
   324          if isinstance(tp, model.StructOrUnion) and tp.partial:
   325              # use the function()'s sizes and offsets to guide the
   326              # layout of the struct
   327              totalsize = layout[0]
   328              totalalignment = layout[1]
   329              fieldofs = layout[2::2]
   330              fieldsize = layout[3::2]
   331              tp.force_flatten()
   332              assert len(fieldofs) == len(fieldsize) == len(tp.fldnames)
   333              tp.fixedlayout = fieldofs, fieldsize, totalsize, totalalignment
   334          else:
   335              cname = ('%s %s' % (prefix, name)).strip()
   336              self._struct_pending_verification[tp] = layout, cname
   337  
   338      def _loaded_struct_or_union(self, tp):
   339          if tp.fldnames is None:
   340              return     # nothing to do with opaque structs
   341          self.ffi._get_cached_btype(tp)   # force 'fixedlayout' to be considered
   342  
   343          if tp in self._struct_pending_verification:
   344              # check that the layout sizes and offsets match the real ones
   345              def check(realvalue, expectedvalue, msg):
   346                  if realvalue != expectedvalue:
   347                      raise ffiplatform.VerificationError(
   348                          "%s (we have %d, but C compiler says %d)"
   349                          % (msg, expectedvalue, realvalue))
   350              ffi = self.ffi
   351              BStruct = ffi._get_cached_btype(tp)
   352              layout, cname = self._struct_pending_verification.pop(tp)
   353              check(layout[0], ffi.sizeof(BStruct), "wrong total size")
   354              check(layout[1], ffi.alignof(BStruct), "wrong total alignment")
   355              i = 2
   356              for fname, ftype, fbitsize, fqual in tp.enumfields():
   357                  if fbitsize >= 0:
   358                      continue        # xxx ignore fbitsize for now
   359                  check(layout[i], ffi.offsetof(BStruct, fname),
   360                        "wrong offset for field %r" % (fname,))
   361                  if layout[i+1] != 0:
   362                      BField = ffi._get_cached_btype(ftype)
   363                      check(layout[i+1], ffi.sizeof(BField),
   364                            "wrong size for field %r" % (fname,))
   365                  i += 2
   366              assert i == len(layout)
   367  
   368      # ----------
   369      # 'anonymous' declarations.  These are produced for anonymous structs
   370      # or unions; the 'name' is obtained by a typedef.
   371  
   372      def _generate_gen_anonymous_decl(self, tp, name):
   373          if isinstance(tp, model.EnumType):
   374              self._generate_gen_enum_decl(tp, name, '')
   375          else:
   376              self._generate_struct_or_union_decl(tp, '', name)
   377  
   378      def _loading_gen_anonymous(self, tp, name, module):
   379          if isinstance(tp, model.EnumType):
   380              self._loading_gen_enum(tp, name, module, '')
   381          else:
   382              self._loading_struct_or_union(tp, '', name, module)
   383  
   384      def _loaded_gen_anonymous(self, tp, name, module, **kwds):
   385          if isinstance(tp, model.EnumType):
   386              self._loaded_gen_enum(tp, name, module, **kwds)
   387          else:
   388              self._loaded_struct_or_union(tp)
   389  
   390      # ----------
   391      # constants, likely declared with '#define'
   392  
   393      def _generate_gen_const(self, is_int, name, tp=None, category='const',
   394                              check_value=None):
   395          prnt = self._prnt
   396          funcname = '_cffi_%s_%s' % (category, name)
   397          self.export_symbols.append(funcname)
   398          if check_value is not None:
   399              assert is_int
   400              assert category == 'const'
   401              prnt('int %s(char *out_error)' % funcname)
   402              prnt('{')
   403              self._check_int_constant_value(name, check_value)
   404              prnt('  return 0;')
   405              prnt('}')
   406          elif is_int:
   407              assert category == 'const'
   408              prnt('int %s(long long *out_value)' % funcname)
   409              prnt('{')
   410              prnt('  *out_value = (long long)(%s);' % (name,))
   411              prnt('  return (%s) <= 0;' % (name,))
   412              prnt('}')
   413          else:
   414              assert tp is not None
   415              assert check_value is None
   416              if category == 'var':
   417                  ampersand = '&'
   418              else:
   419                  ampersand = ''
   420              extra = ''
   421              if category == 'const' and isinstance(tp, model.StructOrUnion):
   422                  extra = 'const *'
   423                  ampersand = '&'
   424              prnt(tp.get_c_name(' %s%s(void)' % (extra, funcname), name))
   425              prnt('{')
   426              prnt('  return (%s%s);' % (ampersand, name))
   427              prnt('}')
   428          prnt()
   429  
   430      def _generate_gen_constant_decl(self, tp, name):
   431          is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type()
   432          self._generate_gen_const(is_int, name, tp)
   433  
   434      _loading_gen_constant = _loaded_noop
   435  
   436      def _load_constant(self, is_int, tp, name, module, check_value=None):
   437          funcname = '_cffi_const_%s' % name
   438          if check_value is not None:
   439              assert is_int
   440              self._load_known_int_constant(module, funcname)
   441              value = check_value
   442          elif is_int:
   443              BType = self.ffi._typeof_locked("long long*")[0]
   444              BFunc = self.ffi._typeof_locked("int(*)(long long*)")[0]
   445              function = module.load_function(BFunc, funcname)
   446              p = self.ffi.new(BType)
   447              negative = function(p)
   448              value = int(p[0])
   449              if value < 0 and not negative:
   450                  BLongLong = self.ffi._typeof_locked("long long")[0]
   451                  value += (1 << (8*self.ffi.sizeof(BLongLong)))
   452          else:
   453              assert check_value is None
   454              fntypeextra = '(*)(void)'
   455              if isinstance(tp, model.StructOrUnion):
   456                  fntypeextra = '*' + fntypeextra
   457              BFunc = self.ffi._typeof_locked(tp.get_c_name(fntypeextra, name))[0]
   458              function = module.load_function(BFunc, funcname)
   459              value = function()
   460              if isinstance(tp, model.StructOrUnion):
   461                  value = value[0]
   462          return value
   463  
   464      def _loaded_gen_constant(self, tp, name, module, library):
   465          is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type()
   466          value = self._load_constant(is_int, tp, name, module)
   467          setattr(library, name, value)
   468          type(library)._cffi_dir.append(name)
   469  
   470      # ----------
   471      # enums
   472  
   473      def _check_int_constant_value(self, name, value):
   474          prnt = self._prnt
   475          if value <= 0:
   476              prnt('  if ((%s) > 0 || (long)(%s) != %dL) {' % (
   477                  name, name, value))
   478          else:
   479              prnt('  if ((%s) <= 0 || (unsigned long)(%s) != %dUL) {' % (
   480                  name, name, value))
   481          prnt('    char buf[64];')
   482          prnt('    if ((%s) <= 0)' % name)
   483          prnt('        sprintf(buf, "%%ld", (long)(%s));' % name)
   484          prnt('    else')
   485          prnt('        sprintf(buf, "%%lu", (unsigned long)(%s));' %
   486               name)
   487          prnt('    sprintf(out_error, "%s has the real value %s, not %s",')
   488          prnt('            "%s", buf, "%d");' % (name[:100], value))
   489          prnt('    return -1;')
   490          prnt('  }')
   491  
   492      def _load_known_int_constant(self, module, funcname):
   493          BType = self.ffi._typeof_locked("char[]")[0]
   494          BFunc = self.ffi._typeof_locked("int(*)(char*)")[0]
   495          function = module.load_function(BFunc, funcname)
   496          p = self.ffi.new(BType, 256)
   497          if function(p) < 0:
   498              error = self.ffi.string(p)
   499              if sys.version_info >= (3,):
   500                  error = str(error, 'utf-8')
   501              raise ffiplatform.VerificationError(error)
   502  
   503      def _enum_funcname(self, prefix, name):
   504          # "$enum_$1" => "___D_enum____D_1"
   505          name = name.replace('$', '___D_')
   506          return '_cffi_e_%s_%s' % (prefix, name)
   507  
   508      def _generate_gen_enum_decl(self, tp, name, prefix='enum'):
   509          if tp.partial:
   510              for enumerator in tp.enumerators:
   511                  self._generate_gen_const(True, enumerator)
   512              return
   513          #
   514          funcname = self._enum_funcname(prefix, name)
   515          self.export_symbols.append(funcname)
   516          prnt = self._prnt
   517          prnt('int %s(char *out_error)' % funcname)
   518          prnt('{')
   519          for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
   520              self._check_int_constant_value(enumerator, enumvalue)
   521          prnt('  return 0;')
   522          prnt('}')
   523          prnt()
   524  
   525      def _loading_gen_enum(self, tp, name, module, prefix='enum'):
   526          if tp.partial:
   527              enumvalues = [self._load_constant(True, tp, enumerator, module)
   528                            for enumerator in tp.enumerators]
   529              tp.enumvalues = tuple(enumvalues)
   530              tp.partial_resolved = True
   531          else:
   532              funcname = self._enum_funcname(prefix, name)
   533              self._load_known_int_constant(module, funcname)
   534  
   535      def _loaded_gen_enum(self, tp, name, module, library):
   536          for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
   537              setattr(library, enumerator, enumvalue)
   538              type(library)._cffi_dir.append(enumerator)
   539  
   540      # ----------
   541      # macros: for now only for integers
   542  
   543      def _generate_gen_macro_decl(self, tp, name):
   544          if tp == '...':
   545              check_value = None
   546          else:
   547              check_value = tp     # an integer
   548          self._generate_gen_const(True, name, check_value=check_value)
   549  
   550      _loading_gen_macro = _loaded_noop
   551  
   552      def _loaded_gen_macro(self, tp, name, module, library):
   553          if tp == '...':
   554              check_value = None
   555          else:
   556              check_value = tp     # an integer
   557          value = self._load_constant(True, tp, name, module,
   558                                      check_value=check_value)
   559          setattr(library, name, value)
   560          type(library)._cffi_dir.append(name)
   561  
   562      # ----------
   563      # global variables
   564  
   565      def _generate_gen_variable_decl(self, tp, name):
   566          if isinstance(tp, model.ArrayType):
   567              if tp.length == '...':
   568                  prnt = self._prnt
   569                  funcname = '_cffi_sizeof_%s' % (name,)
   570                  self.export_symbols.append(funcname)
   571                  prnt("size_t %s(void)" % funcname)
   572                  prnt("{")
   573                  prnt("  return sizeof(%s);" % (name,))
   574                  prnt("}")
   575              tp_ptr = model.PointerType(tp.item)
   576              self._generate_gen_const(False, name, tp_ptr)
   577          else:
   578              tp_ptr = model.PointerType(tp)
   579              self._generate_gen_const(False, name, tp_ptr, category='var')
   580  
   581      _loading_gen_variable = _loaded_noop
   582  
   583      def _loaded_gen_variable(self, tp, name, module, library):
   584          if isinstance(tp, model.ArrayType):   # int a[5] is "constant" in the
   585                                                # sense that "a=..." is forbidden
   586              if tp.length == '...':
   587                  funcname = '_cffi_sizeof_%s' % (name,)
   588                  BFunc = self.ffi._typeof_locked('size_t(*)(void)')[0]
   589                  function = module.load_function(BFunc, funcname)
   590                  size = function()
   591                  BItemType = self.ffi._get_cached_btype(tp.item)
   592                  length, rest = divmod(size, self.ffi.sizeof(BItemType))
   593                  if rest != 0:
   594                      raise ffiplatform.VerificationError(
   595                          "bad size: %r does not seem to be an array of %s" %
   596                          (name, tp.item))
   597                  tp = tp.resolve_length(length)
   598              tp_ptr = model.PointerType(tp.item)
   599              value = self._load_constant(False, tp_ptr, name, module)
   600              # 'value' is a <cdata 'type *'> which we have to replace with
   601              # a <cdata 'type[N]'> if the N is actually known
   602              if tp.length is not None:
   603                  BArray = self.ffi._get_cached_btype(tp)
   604                  value = self.ffi.cast(BArray, value)
   605              setattr(library, name, value)
   606              type(library)._cffi_dir.append(name)
   607              return
   608          # remove ptr=<cdata 'int *'> from the library instance, and replace
   609          # it by a property on the class, which reads/writes into ptr[0].
   610          funcname = '_cffi_var_%s' % name
   611          BFunc = self.ffi._typeof_locked(tp.get_c_name('*(*)(void)', name))[0]
   612          function = module.load_function(BFunc, funcname)
   613          ptr = function()
   614          def getter(library):
   615              return ptr[0]
   616          def setter(library, value):
   617              ptr[0] = value
   618          setattr(type(library), name, property(getter, setter))
   619          type(library)._cffi_dir.append(name)
   620  
   621  cffimod_header = r'''
   622  #include <stdio.h>
   623  #include <stddef.h>
   624  #include <stdarg.h>
   625  #include <errno.h>
   626  #include <sys/types.h>   /* XXX for ssize_t on some platforms */
   627  
   628  /* this block of #ifs should be kept exactly identical between
   629     c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py */
   630  #if defined(_MSC_VER)
   631  # include <malloc.h>   /* for alloca() */
   632  # if _MSC_VER < 1600   /* MSVC < 2010 */
   633     typedef __int8 int8_t;
   634     typedef __int16 int16_t;
   635     typedef __int32 int32_t;
   636     typedef __int64 int64_t;
   637     typedef unsigned __int8 uint8_t;
   638     typedef unsigned __int16 uint16_t;
   639     typedef unsigned __int32 uint32_t;
   640     typedef unsigned __int64 uint64_t;
   641     typedef __int8 int_least8_t;
   642     typedef __int16 int_least16_t;
   643     typedef __int32 int_least32_t;
   644     typedef __int64 int_least64_t;
   645     typedef unsigned __int8 uint_least8_t;
   646     typedef unsigned __int16 uint_least16_t;
   647     typedef unsigned __int32 uint_least32_t;
   648     typedef unsigned __int64 uint_least64_t;
   649     typedef __int8 int_fast8_t;
   650     typedef __int16 int_fast16_t;
   651     typedef __int32 int_fast32_t;
   652     typedef __int64 int_fast64_t;
   653     typedef unsigned __int8 uint_fast8_t;
   654     typedef unsigned __int16 uint_fast16_t;
   655     typedef unsigned __int32 uint_fast32_t;
   656     typedef unsigned __int64 uint_fast64_t;
   657     typedef __int64 intmax_t;
   658     typedef unsigned __int64 uintmax_t;
   659  # else
   660  #  include <stdint.h>
   661  # endif
   662  # if _MSC_VER < 1800   /* MSVC < 2013 */
   663     typedef unsigned char _Bool;
   664  # endif
   665  #else
   666  # include <stdint.h>
   667  # if (defined (__SVR4) && defined (__sun)) || defined(_AIX)
   668  #  include <alloca.h>
   669  # endif
   670  #endif
   671  '''