def CheckTypedefs(filenode, releases):
    """Checks that typedefs don't specify callbacks that take some structs.

  See http://crbug.com/233439 for details.
  """
    cgen = CGen()
    # TODO(teravest): Fix the following callback to pass PP_Var by pointer
    # instead of by value.
    node_whitelist = ['PP_Ext_Alarms_OnAlarm_Func_Dev_0_1']
    for node in filenode.GetListOf('Typedef'):
        if node.GetName() in node_whitelist:
            continue
        build_list = node.GetUniqueReleases(releases)
        callnode = node.GetOneOf('Callspec')
        if callnode:
            for param in callnode.GetListOf('Param'):
                if param.GetListOf('Array'):
                    continue
                if cgen.GetParamMode(param) != 'in':
                    continue
                t = param.GetType(build_list[0])
                while t.IsA('Typedef'):
                    t = t.GetType(build_list[0])
                if t.IsA('Struct'):
                    raise Exception('%s is a struct in callback %s. '
                                    'See http://crbug.com/233439' %
                                    (t.GetName(), node.GetName()))
Beispiel #2
0
def CheckTypedefs(filenode, releases):
    """Checks that typedefs don't specify callbacks that take some structs.

  See http://crbug.com/233439 for details.
  """
    cgen = CGen()
    for node in filenode.GetListOf('Typedef'):
        build_list = node.GetUniqueReleases(releases)
        callnode = node.GetOneOf('Callspec')
        if callnode:
            for param in callnode.GetListOf('Param'):
                if param.GetListOf('Array'):
                    continue
                if cgen.GetParamMode(param) != 'in':
                    continue
                t = param.GetType(build_list[0])
                while t.IsA('Typedef'):
                    t = t.GetType(build_list[0])
                if t.IsA('Struct') and t.GetProperty('passByValue'):
                    raise Exception('%s is a struct in callback %s. '
                                    'See http://crbug.com/233439' %
                                    (t.GetName(), node.GetName()))
Beispiel #3
0
def _GetOutputParams(member, release):
    """Returns output parameters (and their types) for a member function.

  Args:
    member - IDLNode for the member function
    release - Release to get output parameters for
  Returns:
    A list of name strings for all output parameters of the member
    function.
  """
    out_params = []
    callnode = member.GetOneOf('Callspec')
    if callnode:
        cgen = CGen()
        for param in callnode.GetListOf('Param'):
            mode = cgen.GetParamMode(param)
            if mode == 'out':
                # We use the 'store' mode when getting the parameter type, since we
                # need to call sizeof() for memset().
                _, pname, _, _ = cgen.GetComponents(param, release, 'store')
                out_params.append(pname)
    return out_params
Beispiel #4
0
class RPCGen(object):
    def __init__(self):
        self.cgen = CGen()
        self.interfaceStructs = []
        self.pppInterfaceGetters = []

    def AddProp(self,
                release,
                s,
                prefix,
                member,
                isOutParam=False,
                callnode=None,
                derefSizeIs=True):
        out = ''
        key = member.GetName()
        if not member.InReleases([release]):
            out += '/* skipping %s */\n' % key
            return
        type = member.GetType(release).GetName()
        array = member.GetOneOf('Array')
        interfaceMember = member.parent
        interface = interfaceMember.parent.parent
        customSerializer = getCustom(interface.GetName(),
                                     interfaceMember.GetName(),
                                     member.GetName())
        array = customSerializer.get('array', array)
        isOutParam = customSerializer.get('isOutParam', isOutParam)
        if isOutParam:
            out += '  AddProp(' + s + ', "' + key + '", PointerToString(' + prefix + key + '));\n'
        elif array:
            if customSerializer:
                type = customSerializer.get('arrayType', type)
            count = array.GetProperty('FIXED') if isinstance(array,
                                                             IDLNode) else None
            if not count:
                size_is = member.GetProperty('size_is()')
                if size_is:
                    size_is = size_is[0]
                    count = prefix + size_is
                    if callnode:
                        for param in callnode.GetListOf('Param'):
                            if param.GetName() == size_is:
                                if self.cgen.GetParamMode(
                                        param) == 'out' and derefSizeIs:
                                    count = '*' + count
                                break
                else:
                    size_as = member.GetProperty('size_as')
                    count = size_as
            if customSerializer:
                count = customSerializer.get('arraySize', count)
            out += '  {\n'
            out += '    BeginProp(' + s + ', "' + key + '");\n'
            out += '    BeginElements(' + s + ');\n'
            out += '    for (uint32_t _n = 0; '
            if count:
                out += '_n < ' + count
            else:
                sentinel = customSerializer.get('arraySentinel', '0')
                out += prefix + key + '[_n] != ' + sentinel
            out += '; ++_n) {\n'
            out += '      AddElement(' + s + ', ToString_' + type + '(' + prefix + key + '[_n]));\n'
            out += '    }\n'
            out += '    EndElements(' + s + ');\n'
            out += '  }\n'
        else:
            out += '  AddProp(' + s + ', "' + key + '", ToString_' + type + '(' + prefix + key + '));\n'
        return out

    def FromJSON(self, release, prefix, outvalue, node, create, callnode=None):
        out = ''
        type = node.GetType(release).GetName()
        array = node.GetOneOf('Array')
        interfaceMember = node.parent
        interface = interfaceMember.parent.parent
        customParser = getCustom(interface.GetName(),
                                 interfaceMember.GetName(), node.GetName())
        array = customParser.get('array', array)
        create = customParser.get('create', create)
        name = node.GetName()
        outvalue = prefix + outvalue
        if array:
            if customParser:
                type = customParser.get('arrayType', type)
            fixed = array.GetProperty('FIXED') if isinstance(array,
                                                             IDLNode) else None
            count = fixed
            if type == 'char':
                assert count > 0
                out += '  FromJSON_charArray(iterator, ' + outvalue + ', ' + str(
                    count) + ');\n'
            else:
                if not count:
                    size_is = node.GetProperty('size_is()')
                    if size_is:
                        size_is = size_is[0]
                        count = prefix + size_is
                        if callnode:
                            for param in callnode.GetListOf('Param'):
                                if param.GetName() == size_is:
                                    if self.cgen.GetParamMode(param) == 'out':
                                        count = '*' + count
                                    break
                    else:
                        size_as = node.GetProperty('size_as')
                        count = size_as
                if customParser:
                    count = customParser.get('arraySize', count)
                out += '\n'
                out += '  {\n'
                out += '    size_t children = iterator.expectArrayAndGotoFirstItem();\n'
                if count:
                    out += '    if (children > ' + count + ') {\n'
                    out += '      Fail("Too many items in array\\n", "");\n'
                    out += '    }\n'
                if create and not fixed:
                    if not count:
                        count = 'children'
                    out += '    ' + outvalue + ' = new ' + self.cgen.GetTypeByMode(
                        node, release, 'store') + '[' + count + '];\n'
                out += '    for (uint32_t _n = 0; _n < children; ++_n) {\n'
                out += '      FromJSON_' + type + '(iterator, (' + outvalue + ')[_n]);\n'
                out += '    }\n'
                out += '    // FIXME Null out remaining items?\n'
                out += '  }\n'
        else:
            out += '  FromJSON_' + type + '(iterator, ' + outvalue + ');\n'
        return out

    def MemberFromJSON(self, release, prefix, member, create):
        key = member.GetName()
        if not member.InReleases([release]):
            return '/* skipping %s */\n' % key
        return self.FromJSON(release, prefix, key, member, create)

    DerefOutType = {
        'Array': {
            'out': '*'
        },
        'Enum': '*',
        'Struct': '*',
        'cstr_t': '*',
        'TypeValue': '*',
    }

    def DefineInterfaceMethodSerializer(self, iface, releases, node, release):
        customSerializer = getCustom(iface.GetName(), node.GetName(), None)
        if not node.InReleases([release]):
            return '/* skipping %s */\n' % node.GetName()
        if customSerializer and customSerializer.get('skip', False):
            return self.cgen.GetSignature(node,
                                          release,
                                          'ref',
                                          '',
                                          func_as_ptr=False,
                                          include_version=True) + ";\n"
        out = ''
        out += 'static '
        out += self.cgen.GetSignature(node,
                                      release,
                                      'ref',
                                      '',
                                      func_as_ptr=False,
                                      include_version=True)
        out += ' {\n'
        out += '  stringstream ss;\n'
        out += '  BeginProps(ss);\n'
        out += '  AddProp(ss, "__interface", "\\"' + iface.GetName(
        ) + '\\"");\n'
        out += '  AddProp(ss, "__version", "\\"' + iface.GetVersion(
            release) + '\\"");\n'
        out += '  AddProp(ss, "__method", "\\"' + node.GetName() + '\\"");\n'
        callnode = node.GetOneOf('Callspec')
        hasOutParams = False
        if callnode:
            for param in callnode.GetListOf('Param'):
                mode = self.cgen.GetParamMode(param)
                ntype, mode = self.cgen.GetRootTypeMode(param, release, mode)
                mode = getCustom(param.parent.parent.parent.GetName(),
                                 param.parent.GetName(),
                                 param.GetName()).get('mode', mode)
                if mode == "out" or mode == "inout":
                    hasOutParams = hasOutParams or not (ntype == 'mem_t'
                                                        and mode == "inout")
                out += self.AddProp(release, 'ss', '', param, mode == "out",
                                    callnode)
        out += '  EndProps(ss);\n'
        if node.GetProperty('ref'):
            mode = 'ref'
        else:
            mode = 'store'
        rtype = self.cgen.GetTypeByMode(node.GetType(release), release,
                                        'store')
        out += '#ifndef INTERPOSE\n'
        out += '  '
        if rtype != 'void' or hasOutParams:
            out += 'string json = RPCWithResult'
        else:
            out += 'RPC'
        if customSerializer and customSerializer.get('maybeNonMainThread',
                                                     False):
            out += '<MaybeNonMainThread>'
        else:
            out += '<MainThreadOnly>'
        out += '(ss);\n'
        if rtype != 'void' or hasOutParams:
            if rtype != 'void':
                out += '  ' + rtype + ' rval;\n'
            out += '  JSONIterator iterator(json);\n'
            out += '  iterator.expectArrayAndGotoFirstItem();\n'
            if hasOutParams:
                out += '  iterator.expectArrayAndGotoFirstItem();\n'
            if rtype != 'void':
                customRval = getCustom(iface.GetName(), node.GetName(),
                                       "rval").get('convert')
                if customRval:
                    out += customRval
                else:
                    out += '  FromJSON_' + node.GetType(
                        release).GetName() + '(iterator, rval);\n'
            if hasOutParams:
                out += '  iterator.expectObjectAndGotoFirstProperty();\n'
                for param in callnode.GetListOf('Param'):
                    mode = self.cgen.GetParamMode(param)
                    ntype, mode = self.cgen.GetRootTypeMode(
                        param, release, mode)
                    mode = getCustom(param.parent.parent.parent.GetName(),
                                     param.parent.GetName(),
                                     param.GetName()).get('mode', mode)
                    if mode == "out" or mode == "inout":
                        if ntype == 'mem_t' and mode == "inout":
                            continue
                        if ntype == 'Struct' and mode == 'out':
                            out += '  if (!!' + param.GetName() + ') {\n'
                        to_indent = '  iterator.skip();\n'
                        deref = self.DerefOutType.get(ntype, '')
                        if isinstance(deref, dict):
                            deref = deref.get(mode, '')
                        to_indent += self.FromJSON(release, '',
                                                   deref + param.GetName(),
                                                   param, mode == 'out',
                                                   callnode)
                        if ntype == 'Struct' and mode == 'out':
                            out += re.sub(r"(^|\n)(?!(\n|$))",
                                          r'\1' + (2 * ' '), to_indent)
                            out += '  }\n'
                        else:
                            out += to_indent
            if rtype != 'void':
                out += '  return rval;\n'
        out += '#else // !INTERPOSE\n'
        out += '  printf("%s\\n", ss.str().c_str());\n'
        #out += '  printf("Calling: %p\\n", RealGetInterface("' + self.cgen.GetInterfaceString(iface, iface.GetVersion(release)) + '"));\n'
        #out += '  printf("  -> %p\\n", ((' + self.cgen.GetStructName(iface, release, include_version=True) + '*)RealGetInterface("' + self.cgen.GetInterfaceString(iface, iface.GetVersion(release)) + '"))->' + node.GetName() + ');\n'
        out += '  '
        rtype = self.cgen.GetTypeByMode(node.GetType(release), release,
                                        'return')
        params = []
        for param in callnode.GetListOf('Param'):
            mode = self.cgen.GetParamMode(param)
            ntype, mode = self.cgen.GetRootTypeMode(param, release, mode)
            if mode == "in" and param.GetType(
                    release).GetName() == 'PP_CompletionCallback':
                out += 'PP_CompletionCallback logging_' + param.GetName(
                ) + ';\n'
                out += '  logging_' + param.GetName(
                ) + '.func = &Logging_PP_CompletionCallback;\n'
                out += '  logging_' + param.GetName(
                ) + '.user_data = new PP_CompletionCallback(' + param.GetName(
                ) + ');\n'
                out += '  logging_' + param.GetName(
                ) + '.flags = ' + param.GetName() + '.flags;\n'
                out += '  '
                params.append('logging_' + param.GetName())
            elif mode == "in" and param.GetType(
                    release).GetName() == 'PPP_Class_Deprecated':
                out += 'Logging_PPP_Class_Deprecated_holder* logging_' + param.GetName(
                ) + ' = new Logging_PPP_Class_Deprecated_holder();\n'
                out += '  logging_' + param.GetName(
                ) + '->_real_PPP_Class_Deprecated = ' + param.GetName() + ';\n'
                out += '  logging_' + param.GetName(
                ) + '->object = object_data;\n'
                out += '  object_data = logging_' + param.GetName() + ';\n'
                out += '  '
                params.append('&_interpose_PPP_Class_Deprecated_1_0')
            elif mode == "return" and param.GetType(release).GetName(
            ) == 'PPB_Audio_Callback' and param.GetVersion(release) == "1.0":
                out += 'Logging_PPB_Audio_Callback_1_0_holder* ' + param.GetName(
                ) + '_holder = new Logging_PPB_Audio_Callback_1_0_holder();\n'
                out += '  ' + param.GetName(
                ) + '_holder->func = ' + param.GetName() + ';\n'
                out += '  ' + param.GetName(
                ) + '_holder->user_data = user_data;\n'
                out += '  user_data = ' + param.GetName() + '_holder;\n'
                out += '  '
                params.append('Logging_PPB_Audio_Callback_1_0')
            else:
                params.append(param.GetName())
        if rtype != 'void':
            out += rtype + ' rval = '
        out += '((' + self.cgen.GetStructName(
            iface, release, include_version=True
        ) + '*)RealGetInterface("' + self.cgen.GetInterfaceString(
            iface, iface.GetVersion(release)) + '"))->' + node.GetName(
            ) + '(' + ', '.join(params) + ');\n'
        if rtype != 'void' or hasOutParams:
            out += '  printf("RPC response: [");\n'
            if hasOutParams:
                out += '  printf("[");\n'
            if rtype != 'void':
                out += '  printf("%s", ToString_' + node.GetType(
                    release).GetName() + '(rval).c_str());\n'
            if hasOutParams:
                if rtype != 'void':
                    out += '  printf(",");\n'
                out += '  std::stringstream os;\n'
                out += '  BeginProps(os);\n'
                for param in callnode.GetListOf('Param'):
                    mode = self.cgen.GetParamMode(param)
                    ntype, mode = self.cgen.GetRootTypeMode(
                        param, release, mode)
                    if mode == "out" or mode == "inout":
                        if mode == "out" and (ntype == 'Struct'
                                              or ntype == 'TypeValue'):
                            out += '  if (!!' + param.GetName() + ') {\n'
                        out += self.AddProp(release, 'os', '', param, False,
                                            callnode)
                        if mode == "out" and (ntype == 'Struct'
                                              or ntype == 'TypeValue'):
                            out += '  }\n'
                out += '  EndProps(os);\n'
                out += '  printf("%s]", os.str().c_str());\n'
            out += '  printf("]\\n");\n'
            if rtype != 'void':
                out += '  return rval;\n'
        out += '#endif // !INTERPOSE\n'
        out += '}\n'
        return out

    def DefineInterfaceMethodParser(self, iface, releases, node, release):
        if not node.InReleases([release]):
            return '/* skipping %s */\n' % node.GetName()
        version = self.GetNodeName(iface, release, releases)
        out = ''
        out += 'char* Call_%s_%s(const %s* _interface, JSONIterator& iterator) {\n' % (
            iface.GetName(), node.GetName(), version)
        callnode = node.GetOneOf('Callspec')
        params = []
        hasOutParams = False
        for param in callnode.GetListOf('Param'):
            mode = self.cgen.GetParamMode(param)
            ptype, pname, parray, pspec = self.cgen.GetComponents(
                param, release, "store")
            out += '  ' + self.cgen.Compose(ptype,
                                            pname,
                                            parray,
                                            pspec,
                                            '',
                                            func_as_ptr=True,
                                            include_name=True,
                                            unsized_as_ptr=True) + ';\n'
            if mode == 'out':
                if len(parray) > 0:
                    out += '  iterator.skip();\n'
                    out += '  PointerValueFromJSON(iterator, ' + pname + ');\n'
            else:
                out += '  iterator.skip();\n'
                out += self.FromJSON(release, '', pname, param, True, callnode)
            hasOutParams = hasOutParams or mode == "out" or mode == "inout"
        if node.GetProperty('ref'):
            mode = 'ref'
        else:
            mode = 'store'
        rtype = self.cgen.GetTypeByMode(node.GetType(release), release,
                                        'store')
        out += '  '
        if rtype != 'void':
            out += rtype + ' rval;\n'
            out += '  rval = '
        params = []
        for param in callnode.GetListOf('Param'):
            mode = self.cgen.GetParamMode(param)
            ntype, mode = self.cgen.GetRootTypeMode(param, release, mode)
            ptype, pname, parray, pspec = self.cgen.GetComponents(
                param, release, mode)
            if mode == 'out' or ntype == 'Struct' or (mode == 'constptr_in' and
                                                      ntype == 'TypeValue'):
                pname = '&' + pname
            pname = '(' + self.cgen.Compose(ptype,
                                            pname,
                                            parray,
                                            pspec,
                                            '',
                                            func_as_ptr=True,
                                            include_name=False,
                                            unsized_as_ptr=True) + ')' + pname
            params.append(pname)
        out += '_interface->' + node.GetName() + '(' + ", ".join(
            params) + ');\n'
        if rtype != 'void' or hasOutParams:
            typeref = node.GetType(release)
            if hasOutParams:
                out += '  stringstream os;\n'
                out += '  BeginElements(os);\n'
                if rtype != 'void':
                    out += '  AddElement(os, ToString_' + typeref.GetName(
                    ) + '(rval).c_str());\n'
                    out += '  BeginElement(os);\n'
                out += '  BeginProps(os);\n'
                for param in callnode.GetListOf('Param'):
                    mode = self.cgen.GetParamMode(param)
                    ntype, mode = self.cgen.GetRootTypeMode(
                        param, release, mode)
                    ptype, pname, parray, pspec = self.cgen.GetComponents(
                        param, release, mode)
                    if mode == 'out' or mode == 'inout':
                        out += self.AddProp(release,
                                            'os',
                                            '',
                                            param,
                                            False,
                                            callnode,
                                            derefSizeIs=False)
                out += '  EndProps(os);\n'
                out += '  EndElements(os);\n'
                out += '  return strdup(os.str().c_str());\n'
            else:
                out += '  return strdup(ToString_' + typeref.GetName(
                ) + '(rval).c_str());\n'
        else:
            out += '  return nullptr;\n'
        out += '}\n'
        return out

    def DefineInterface(self, node, releases, declareOnly):
        out = ''
        if node.GetName() == "PPB_NaCl_Private":
            # skip
            return out
        isPPP = node.GetName()[0:4] == "PPP_"
        build_list = node.GetUniqueReleases(releases)
        for release in build_list:
            name = self.cgen.GetStructName(node, release, include_version=True)
            if declareOnly:
                out += '#ifdef INTERPOSE\n'
                out += 'static ' + name + ' *_real_' + name + ';\n'
                out += '#endif // INTERPOSE\n'
            if isPPP:
                version = self.GetNodeName(node, release, build_list)
                if declareOnly:
                    out += 'static char* Call_%s(void* _interface, JSONIterator& iterator);\n' % (
                        version)
                    continue
                members = node.GetListOf('Member')
                for member in members:
                    out += self.DefineInterfaceMethodParser(
                        node, build_list, member, release)
                out += 'char* Call_%s(const void* _interface, JSONIterator& iterator) {\n' % (
                    version)
                out += '  iterator.skip();\n'
                out += '  const Token& member = iterator.getCurrentStringAndGotoNext();\n'
                out += '  string memberName = member.value();\n'
                for member in members:
                    if not member.InReleases([release]):
                        out += '/* skipping %s */\n' % member.GetName()
                        continue
                    out += '  if (!memberName.compare("' + member.GetName(
                    ) + '")) {\n'
                    out += '    return Call_' + node.GetName(
                    ) + '_' + member.GetName(
                    ) + '((const ' + version + '*)_interface, iterator);\n'
                    out += '  }\n'
                out += '  return nullptr;\n'
                out += '}\n'
                self.pppInterfaceGetters.append(
                    (self.cgen.GetInterfaceString(node,
                                                  node.GetVersion(release)),
                     'Call_' + version))
                continue
            version = self.cgen.GetStructName(node,
                                              release,
                                              include_version=True)
            if declareOnly:
                out += 'const string ToString_%s(const %s *v);\n' % (
                    node.GetName(), version)
                continue
            ns = 'ns_' + version
            out += 'namespace ' + ns + ' {\n'
            members = node.GetListOf('Member')
            for member in members:
                out += self.DefineInterfaceMethodSerializer(
                    node, releases, member, release)
            out += '}\n'
            self.interfaceStructs.append(
                (self.cgen.GetInterfaceString(node, node.GetVersion(release)),
                 '_' + name))
            out += 'static ' + name + ' _' + name + ' = {\n'
            for member in members:
                if not member.InReleases([release]):
                    continue
                memberName = self.cgen.GetStructName(member, release, True)
                out += '  ' + ns + '::' + memberName + ',\n'
            out += '};\n'
            out += 'const string ToString_%s(const %s *v) {\n' % (
                node.GetName(), version)
            out += '  stringstream s;\n'
            out += '  s << v;\n'
            out += '  return s.str();\n'
            out += '}\n'
        return out

    def GetNodeName(self, node, release, build_list):
        return self.cgen.GetStructName(
            node, release, include_version=(release != build_list[-1]))

    @staticmethod
    def SerializerAndParserSignatures(typename, type):
        s = ('const string ToString_%s(const %s *v)',
             'const string ToString_%s(const %s &v)',
             'void FromJSON_%s(JSONIterator& iterator, %s &value)')
        return (sig % (typename, type) for sig in s)

    def DefineTypedefSerializerAndParser(self, node, releases, declareOnly):
        out = ''
        build_list = node.GetUniqueReleases(releases)
        for release in build_list:
            type = self.GetNodeName(node, release, build_list)
            typeref = node.GetType(release)
            (toStringFromPointer, toStringFromRef,
             fromJSONToRef) = self.SerializerAndParserSignatures(
                 node.GetName(), type)
            isFuncPtr = node.GetOneOf('Callspec')
            if declareOnly:
                if not isFuncPtr:
                    out += toStringFromPointer + ";\n"
                out += toStringFromRef + ";\n"
                out += fromJSONToRef + ";\n"
                continue
            if not isFuncPtr:
                out += toStringFromPointer + ' {\n'
                out += '  return ToString_%s(v);\n' % (typeref.GetName())
                out += '}\n'
            out += toStringFromRef + ' {\n'
            if isFuncPtr:
                out += '  return PointerToString(v);\n'
            else:
                out += '  return ToString_%s(&v);\n' % (node.GetName())
            out += '}\n'
            out += fromJSONToRef + ' {\n'
            if isFuncPtr:
                out += '  PointerValueFromJSON(iterator, value);\n'
            else:
                out += '  FromJSON_%s(iterator, value);\n' % (
                    typeref.GetName())
            out += '}\n'
        return out

    def DefineStructSerializerAndParser(self, node, releases, declareOnly):
        out = ''
        build_list = node.GetUniqueReleases(releases)
        for release in build_list:
            name = node.GetName()
            version = self.GetNodeName(node, release, build_list)
            (toStringFromPointer, toStringFromRef,
             fromJSONToRef) = self.SerializerAndParserSignatures(
                 name, version)
            if declareOnly:
                out += toStringFromPointer + ";\n"
                out += toStringFromRef + ";\n"
                out += fromJSONToRef + ";\n"
                continue
            out += toStringFromPointer + ' {\n'
            out += '  if (!v) {\n'
            out += '    return "null";\n'
            out += '  }\n'
            out += '  return ToString_%s(*v);\n' % (name)
            out += '}\n'
            out += toStringFromRef + ' {\n'
            out += '  stringstream x;\n'
            out += '  BeginProps(x);\n'
            members = node.GetListOf('Member')
            for member in members:
                out += self.AddProp(release, 'x', 'v.', member)
            out += '  EndProps(x);\n'
            out += '  return x.str();\n'
            out += '}\n'
            out += fromJSONToRef + ' {\n'
            out += '  const JSON::Token& current = iterator.getCurrentAndGotoNext();\n'
            # FIXME Should we warn here somehow? It might be ok to return null in
            #       error conditions, so maybe not.
            out += '  if (current.isPrimitive() && !current.value().compare("null")) {\n'
            out += '    return;\n'
            out += '  }\n'
            out += '  if (!current.isObject()) {\n'
            out += '    Fail("Expected object!", "");\n'
            out += '  }\n'
            if node.GetProperty('union'):
                out += '  string name = iterator.getCurrentStringAndGotoNext().value();\n'
                out += " else ".join(
                    map(
                        lambda m: '  if (!name.compare(\"' + m.GetName(
                        ) + '\")) {\n  ' + self.MemberFromJSON(
                            release, 'value.', m, False) + '  }',
                        members)) + "\n"
            else:
                for member in members:
                    typeref = member.GetType(release)
                    out += '  iterator.skip();\n'
                    out += self.MemberFromJSON(release, 'value.', member,
                                               False)
            out += '}\n'
        return out

    def DefineEnumSerializerAndParser(self, node, releases, declareOnly):
        if node.GetProperty('unnamed'):
            return ''
        out = ''
        name = node.GetName()
        (toStringFromPointer, toStringFromRef,
         fromJSONToRef) = self.SerializerAndParserSignatures(name, name)
        if declareOnly:
            out += toStringFromPointer + ";\n"
            out += toStringFromRef + ";\n"
            out += fromJSONToRef + ";\n"
            return out
        out += toStringFromPointer + ' {\n'
        out += '  switch (*v) {\n'
        next = 0
        emitted = set()
        for child in node.GetListOf('EnumItem'):
            value = child.GetName()
            label = child.GetProperty('VALUE')
            if not label:
                label = str(next)
                next = next + 1
            if label in emitted:
                continue
            emitted.add(label)
            emitted.add(value)
            out += '    case ' + label + ':\n'
            out += '      return "\\"' + value + '\\"";\n'
        out += '    default:\n'
        out += '      return "\\"???\\"";\n'
        out += '  }\n'
        out += '}\n'
        out += toStringFromRef + ' {\n'
        out += '  return ToString_%s(&v);\n' % (name)
        out += '}\n'
        out += fromJSONToRef + ' {\n'
        out += '  long int v;\n'
        out += '  FromJSON_int(iterator, v);\n'
        out += '  value = %s(v);\n' % (name)
        out += '}\n'
        return out

    def Define(self, node, releases, declareOnly):
        # Skip if this node is not in this release
        if not node.InReleases(releases):
            return "/* skipping %s */\n" % node
        if node.IsA('Typedef'):
            return self.DefineTypedefSerializerAndParser(
                node, releases, declareOnly)
        if node.IsA('Struct'):
            return self.DefineStructSerializerAndParser(
                node, releases, declareOnly)
        if node.IsA('Enum'):
            return self.DefineEnumSerializerAndParser(node, releases,
                                                      declareOnly)
        if node.IsA('Interface'):
            return self.DefineInterface(node, releases, declareOnly)
        return ''
Beispiel #5
0
def _MakeNormalMemberBody(filenode, release, node, member, rtype, args,
                          include_version, meta):
  """Returns the body of a typical function.

  Args:
    filenode - IDLNode for the file
    release - release to generate body for
    node - IDLNode for the interface
    member - IDLNode for the member function
    rtype - Return type for the member function
    args - List of 4-tuple arguments for the member function
    include_version - whether to include the version in the invocation
    meta - ThunkBodyMetadata for header hints
  """
  is_callback_func = args[len(args) - 1][0] == 'struct PP_CompletionCallback'

  if is_callback_func:
    call_args = args[:-1] + [('', 'enter.callback()', '', '')]
    meta.AddInclude('ppapi/c/pp_completion_callback.h')
  else:
    call_args = args

  if args[0][0] == 'PP_Instance':
    call_arglist = ', '.join(a[1] for a in call_args)
    function_container = 'functions'
  else:
    call_arglist = ', '.join(a[1] for a in call_args[1:])
    function_container = 'object'

  function_name = member.GetName()
  if include_version:
    version = node.GetVersion(release).replace('.', '_')
    function_name += version

  invocation = 'enter.%s()->%s(%s)' % (function_container,
                                       function_name,
                                       call_arglist)

  handle_errors = not (member.GetProperty('report_errors') == 'False')
  if is_callback_func:
    body = '%s\n' % _MakeEnterLine(filenode, node, args[0], handle_errors,
                                   args[len(args) - 1][1], meta)
    body += 'if (enter.failed())\n'
    value = member.GetProperty('on_failure')
    if value is None:
      value = 'enter.retval()'
    body += '  return %s;\n' % value
    body += 'return enter.SetResult(%s);' % invocation
  elif rtype == 'void':
    # On failure, zero out all output parameters.
    out_params = []
    callnode = member.GetOneOf('Callspec')
    if callnode:
      cgen = CGen()
      for param in callnode.GetListOf('Param'):
        mode = cgen.GetParamMode(param)
        if mode == 'out':
          # We use the 'store' mode when getting the parameter type, since we
          # need to call sizeof() for memset().
          ptype, pname, _, _ = cgen.GetComponents(param, release, 'store')
          out_params.append((pname, ptype))

    body = '%s\n' % _MakeEnterLine(filenode, node, args[0], handle_errors,
                                   None, meta)
    if not out_params:
      body += 'if (enter.succeeded())\n'
      body += '  %s;' % invocation
    else:
      body += 'if (enter.succeeded()) {\n'
      body += '  %s;\n' % invocation
      body += '  return;\n'
      body += '}'
      for param in out_params:
        body += '\nmemset(%s, 0, sizeof(%s));' % param
      meta.AddBuiltinInclude('string.h')

  else:
    value = member.GetProperty('on_failure')
    if value is None:
      value = _GetDefaultFailureValue(rtype)
    if value is None:
      raise TGenError('No default value for rtype %s' % rtype)

    body = '%s\n' % _MakeEnterLine(filenode, node, args[0], handle_errors,
                                   None, meta)
    body += 'if (enter.failed())\n'
    body += '  return %s;\n' % value
    body += 'return %s;' % invocation
  return body