| Index: ppapi/native_client/src/tools/srpcgen.py
|
| diff --git a/ppapi/native_client/src/tools/srpcgen.py b/ppapi/native_client/src/tools/srpcgen.py
|
| deleted file mode 100755
|
| index 91901c10e2b2e84ab53b33a17251f10a7b863a47..0000000000000000000000000000000000000000
|
| --- a/ppapi/native_client/src/tools/srpcgen.py
|
| +++ /dev/null
|
| @@ -1,466 +0,0 @@
|
| -#!/usr/bin/env python
|
| -# Copyright (c) 2012 The Native Client Authors. All rights reserved.
|
| -# Use of this source code is governed by a BSD-style license that can be
|
| -# found in the LICENSE file.
|
| -
|
| -"""Build "SRPC" interfaces from specifications.
|
| -
|
| -SRPC interfaces consist of one or more interface classes, typically defined
|
| -in a set of .srpc files. The specifications are Python dictionaries, with a
|
| -top level 'name' element and an 'rpcs' element. The rpcs element is a list
|
| -containing a number of rpc methods, each of which has a 'name', an 'inputs',
|
| -and an 'outputs' element. These elements are lists of input or output
|
| -parameters, which are lists pairs containing a name and type. The set of
|
| -types includes all the SRPC basic types.
|
| -
|
| -These SRPC specifications are used to generate a header file and either a
|
| -server or client stub file, as determined by the command line flag -s or -c.
|
| -"""
|
| -
|
| -import getopt
|
| -import sys
|
| -import os
|
| -
|
| -COPYRIGHT_AND_AUTOGEN_COMMENT = """\
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -//
|
| -// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
|
| -//
|
| -// Automatically generated code. See srpcgen.py
|
| -//
|
| -// NaCl Simple Remote Procedure Call interface abstractions.
|
| -"""
|
| -
|
| -HEADER_INCLUDE_GUARD_START = """\
|
| -#ifndef %(include_guard)s
|
| -#define %(include_guard)s
|
| -"""
|
| -
|
| -HEADER_INCLUDE_GUARD_END = """\
|
| -\n\n#endif // %(include_guard)s
|
| -"""
|
| -
|
| -HEADER_FILE_INCLUDES = """\
|
| -#ifndef __native_client__
|
| -#include "native_client/src/include/portability.h"
|
| -#endif // __native_client__
|
| -%(EXTRA_INCLUDES)s
|
| -"""
|
| -
|
| -SOURCE_FILE_INCLUDES = """\
|
| -#include "%(srpcgen_h)s"
|
| -#ifdef __native_client__
|
| -#ifndef UNREFERENCED_PARAMETER
|
| -#define UNREFERENCED_PARAMETER(P) do { (void) P; } while (0)
|
| -#endif // UNREFERENCED_PARAMETER
|
| -#else
|
| -#include "native_client/src/include/portability.h"
|
| -#endif // __native_client__
|
| -%(EXTRA_INCLUDES)s
|
| -"""
|
| -
|
| -# For both .cc and .h files.
|
| -EXTRA_INCLUDES = [
|
| - '#include "native_client/src/shared/srpc/nacl_srpc.h"',
|
| -]
|
| -
|
| -types = {'bool': ['b', 'bool', 'u.bval', ''],
|
| - 'char[]': ['C', 'char*', 'arrays.carr', 'u.count'],
|
| - 'double': ['d', 'double', 'u.dval', ''],
|
| - 'double[]': ['D', 'double*', 'arrays.darr', 'u.count'],
|
| - 'handle': ['h', 'NaClSrpcImcDescType', 'u.hval', ''],
|
| - 'int32_t': ['i', 'int32_t', 'u.ival', ''],
|
| - 'int32_t[]': ['I', 'int32_t*', 'arrays.iarr', 'u.count'],
|
| - 'int64_t': ['l', 'int64_t', 'u.lval', ''],
|
| - 'int64_t[]': ['L', 'int64_t', 'arrays.larr', 'u.count'],
|
| - 'PP_Instance': ['i', 'PP_Instance', 'u.ival', ''],
|
| - 'PP_Module': ['i', 'PP_Module', 'u.ival', ''],
|
| - 'PP_Resource': ['i', 'PP_Resource', 'u.ival', ''],
|
| - 'string': ['s', 'const char*', 'arrays.str', ''],
|
| - }
|
| -
|
| -def AddInclude(name):
|
| - """Adds an include to the include section of both .cc and .h files."""
|
| - EXTRA_INCLUDES.append('#include "%s"' % name)
|
| -
|
| -
|
| -def HeaderFileIncludes():
|
| - """Includes are sorted alphabetically."""
|
| - EXTRA_INCLUDES.sort()
|
| - return HEADER_FILE_INCLUDES % {
|
| - 'EXTRA_INCLUDES': '\n'.join(EXTRA_INCLUDES),
|
| - }
|
| -
|
| -
|
| -def SourceFileIncludes(srpcgen_h_file):
|
| - """Includes are sorted alphabetically."""
|
| - EXTRA_INCLUDES.sort()
|
| - return SOURCE_FILE_INCLUDES % {
|
| - 'EXTRA_INCLUDES': '\n'.join(EXTRA_INCLUDES),
|
| - 'srpcgen_h': srpcgen_h_file
|
| - }
|
| -
|
| -
|
| -def PrintHeaderFileTop(output, include_guard):
|
| - """Prints the header of the .h file including copyright,
|
| - header comment, include guard and includes."""
|
| - print >>output, COPYRIGHT_AND_AUTOGEN_COMMENT
|
| - print >>output, HEADER_INCLUDE_GUARD_START % {'include_guard': include_guard}
|
| - print >>output, HeaderFileIncludes()
|
| -
|
| -
|
| -def PrintHeaderFileBottom(output, include_guard):
|
| - """Prints the footer of the .h file including copyright,
|
| - header comment, include guard and includes."""
|
| - print >>output, HEADER_INCLUDE_GUARD_END % {'include_guard': include_guard}
|
| -
|
| -
|
| -def PrintSourceFileTop(output, srpcgen_h_file):
|
| - """Prints the header of the .cc file including copyright,
|
| - header comment and includes."""
|
| - print >>output, COPYRIGHT_AND_AUTOGEN_COMMENT
|
| - print >>output, SourceFileIncludes(srpcgen_h_file)
|
| -
|
| -
|
| -def CountName(name):
|
| - """Returns the name of the auxiliary count member used for array typed."""
|
| - return '%s_bytes' % name
|
| -
|
| -
|
| -def FormatRpcPrototype(is_server, class_name, indent, rpc):
|
| - """Returns a string for the prototype of an individual RPC."""
|
| -
|
| - def FormatArgs(is_output, args):
|
| - """Returns a string containing the formatted arguments for an RPC."""
|
| -
|
| - def FormatArg(is_output, arg):
|
| - """Returns a string containing a formatted argument to an RPC."""
|
| - if is_output:
|
| - suffix = '* '
|
| - else:
|
| - suffix = ' '
|
| - s = ''
|
| - type_info = types[arg[1]]
|
| - if type_info[3]:
|
| - s += 'nacl_abi_size_t%s%s, %s %s' % (suffix,
|
| - CountName(arg[0]),
|
| - type_info[1],
|
| - arg[0])
|
| - else:
|
| - s += '%s%s%s' % (type_info[1], suffix, arg[0])
|
| - return s
|
| - s = ''
|
| - for arg in args:
|
| - s += ',\n %s%s' % (indent, FormatArg(is_output, arg))
|
| - return s
|
| - if is_server:
|
| - ret_type = 'void'
|
| - else:
|
| - ret_type = 'NaClSrpcError'
|
| - s = '%s %s%s(\n' % (ret_type, class_name, rpc['name'])
|
| - # Until SRPC uses RPC/Closure on the client side, these must be different.
|
| - if is_server:
|
| - s += ' %sNaClSrpcRpc* rpc,\n' % indent
|
| - s += ' %sNaClSrpcClosure* done' % indent
|
| - else:
|
| - s += ' %sNaClSrpcChannel* channel' % indent
|
| - s += '%s' % FormatArgs(False, rpc['inputs'])
|
| - s += '%s' % FormatArgs(True, rpc['outputs'])
|
| - s += ')'
|
| - return s
|
| -
|
| -
|
| -def PrintHeaderFile(output, is_server, guard_name, interface_name, specs):
|
| - """Prints out the header file containing the prototypes for the RPCs."""
|
| - PrintHeaderFileTop(output, guard_name)
|
| - s = ''
|
| - # iterate over all the specified interfaces
|
| - if is_server:
|
| - suffix = 'Server'
|
| - else:
|
| - suffix = 'Client'
|
| - for spec in specs:
|
| - class_name = spec['name'] + suffix
|
| - rpcs = spec['rpcs']
|
| - s += 'class %s {\n public:\n' % class_name
|
| - for rpc in rpcs:
|
| - s += ' static %s;\n' % FormatRpcPrototype(is_server, '', ' ', rpc)
|
| - s += '\n private:\n %s();\n' % class_name
|
| - s += ' %s(const %s&);\n' % (class_name, class_name)
|
| - s += ' void operator=(const %s);\n' % class_name
|
| - s += '}; // class %s\n\n' % class_name
|
| - if is_server:
|
| - s += 'class %s {\n' % interface_name
|
| - s += ' public:\n'
|
| - s += ' static NaClSrpcHandlerDesc srpc_methods[];\n'
|
| - s += '}; // class %s' % interface_name
|
| - print >>output, s
|
| - PrintHeaderFileBottom(output, guard_name)
|
| -
|
| -
|
| -def PrintServerFile(output, header_name, interface_name, specs):
|
| - """Print the server (stub) .cc file."""
|
| -
|
| - def FormatDispatchPrototype(indent, rpc):
|
| - """Format the prototype of a dispatcher method."""
|
| - s = '%sstatic void %sDispatcher(\n' % (indent, rpc['name'])
|
| - s += '%s NaClSrpcRpc* rpc,\n' % indent
|
| - s += '%s NaClSrpcArg** inputs,\n' % indent
|
| - s += '%s NaClSrpcArg** outputs,\n' % indent
|
| - s += '%s NaClSrpcClosure* done\n' % indent
|
| - s += '%s)' % indent
|
| - return s
|
| -
|
| - def FormatMethodString(rpc):
|
| - """Format the SRPC text string for a single rpc method."""
|
| -
|
| - def FormatTypes(args):
|
| - s = ''
|
| - for arg in args:
|
| - s += types[arg[1]][0]
|
| - return s
|
| - s = ' { "%s:%s:%s", %sDispatcher },\n' % (rpc['name'],
|
| - FormatTypes(rpc['inputs']),
|
| - FormatTypes(rpc['outputs']),
|
| - rpc['name'])
|
| - return s
|
| -
|
| - def FormatCall(class_name, indent, rpc):
|
| - """Format a call from a dispatcher method to its stub."""
|
| -
|
| - def FormatArgs(is_output, args):
|
| - """Format the arguments passed to the stub."""
|
| -
|
| - def FormatArg(is_output, num, arg):
|
| - """Format an argument passed to a stub."""
|
| - if is_output:
|
| - prefix = 'outputs[' + str(num) + ']->'
|
| - addr_prefix = '&('
|
| - addr_suffix = ')'
|
| - else:
|
| - prefix = 'inputs[' + str(num) + ']->'
|
| - addr_prefix = ''
|
| - addr_suffix = ''
|
| - type_info = types[arg[1]]
|
| - if type_info[3]:
|
| - s = '%s%s%s%s, %s%s' % (addr_prefix,
|
| - prefix,
|
| - type_info[3],
|
| - addr_suffix,
|
| - prefix,
|
| - type_info[2])
|
| - else:
|
| - s = '%s%s%s%s' % (addr_prefix, prefix, type_info[2], addr_suffix)
|
| - return s
|
| - # end FormatArg
|
| - s = ''
|
| - num = 0
|
| - for arg in args:
|
| - s += ',\n%s %s' % (indent, FormatArg(is_output, num, arg))
|
| - num += 1
|
| - return s
|
| - # end FormatArgs
|
| - s = '%s::%s(\n%s rpc,\n' % (class_name, rpc['name'], indent)
|
| - s += '%s done' % indent
|
| - s += FormatArgs(False, rpc['inputs'])
|
| - s += FormatArgs(True, rpc['outputs'])
|
| - s += '\n%s)' % indent
|
| - return s
|
| - # end FormatCall
|
| -
|
| - PrintSourceFileTop(output, header_name)
|
| - s = 'namespace {\n\n'
|
| - for spec in specs:
|
| - class_name = spec['name'] + 'Server'
|
| - rpcs = spec['rpcs']
|
| - for rpc in rpcs:
|
| - s += '%s {\n' % FormatDispatchPrototype('', rpc)
|
| - if rpc['inputs'] == []:
|
| - s += ' UNREFERENCED_PARAMETER(inputs);\n'
|
| - if rpc['outputs'] == []:
|
| - s += ' UNREFERENCED_PARAMETER(outputs);\n'
|
| - s += ' %s;\n' % FormatCall(class_name, ' ', rpc)
|
| - s += '}\n\n'
|
| - s += '} // namespace\n\n'
|
| - s += 'NaClSrpcHandlerDesc %s::srpc_methods[] = {\n' % interface_name
|
| - for spec in specs:
|
| - class_name = spec['name'] + 'Server'
|
| - rpcs = spec['rpcs']
|
| - for rpc in rpcs:
|
| - s += FormatMethodString(rpc)
|
| - s += ' { NULL, NULL }\n};\n'
|
| - print >>output, s
|
| -
|
| -
|
| -def PrintClientFile(output, header_name, specs, thread_check):
|
| - """Prints the client (proxy) .cc file."""
|
| -
|
| - def InstanceInputArg(rpc):
|
| - """Returns the name of the PP_Instance arg or None if there is none."""
|
| - for arg in rpc['inputs']:
|
| - if arg[1] == 'PP_Instance':
|
| - return arg[0]
|
| - return None
|
| -
|
| - def DeadNexeHandling(rpc, retval):
|
| - """Generates the code necessary to handle death of a nexe during the rpc
|
| - call. This is only possible if PP_Instance arg is present, otherwise"""
|
| - instance = InstanceInputArg(rpc);
|
| - if instance is not None:
|
| - check = (' if (%s == NACL_SRPC_RESULT_INTERNAL)\n'
|
| - ' ppapi_proxy::CleanUpAfterDeadNexe(%s);\n')
|
| - return check % (retval, instance)
|
| - return '' # No handling
|
| -
|
| -
|
| - def FormatCall(rpc):
|
| - """Format a call to the generic dispatcher, NaClSrpcInvokeBySignature."""
|
| -
|
| - def FormatTypes(args):
|
| - """Format a the type signature string for either inputs or outputs."""
|
| - s = ''
|
| - for arg in args:
|
| - s += types[arg[1]][0]
|
| - return s
|
| - def FormatArgs(args):
|
| - """Format the arguments for the call to the generic dispatcher."""
|
| -
|
| - def FormatArg(arg):
|
| - """Format a single argument for the call to the generic dispatcher."""
|
| - s = ''
|
| - type_info = types[arg[1]]
|
| - if type_info[3]:
|
| - s += '%s, ' % CountName(arg[0])
|
| - s += arg[0]
|
| - return s
|
| - # end FormatArg
|
| - s = ''
|
| - for arg in args:
|
| - s += ',\n %s' % FormatArg(arg)
|
| - return s
|
| - #end FormatArgs
|
| - s = '(\n channel,\n "%s:%s:%s"' % (rpc['name'],
|
| - FormatTypes(rpc['inputs']),
|
| - FormatTypes(rpc['outputs']))
|
| - s += FormatArgs(rpc['inputs'])
|
| - s += FormatArgs(rpc['outputs']) + '\n )'
|
| - return s
|
| - # end FormatCall
|
| -
|
| - # We need this to handle dead nexes.
|
| - if header_name.startswith('trusted'):
|
| - AddInclude('native_client/src/shared/ppapi_proxy/browser_globals.h')
|
| - if thread_check:
|
| - AddInclude('native_client/src/shared/ppapi_proxy/plugin_globals.h')
|
| - AddInclude('ppapi/c/ppb_core.h')
|
| - AddInclude('native_client/src/shared/platform/nacl_check.h')
|
| - PrintSourceFileTop(output, header_name)
|
| - s = ''
|
| -
|
| - for spec in specs:
|
| - class_name = spec['name'] + 'Client'
|
| - rpcs = spec['rpcs']
|
| - for rpc in rpcs:
|
| - s += '%s {\n' % FormatRpcPrototype('', class_name + '::', '', rpc)
|
| - if thread_check and rpc['name'] not in ['PPB_GetInterface',
|
| - 'PPB_Core_CallOnMainThread']:
|
| - error = '"%s: PPAPI calls are not supported off the main thread\\n"'
|
| - s += ' VCHECK(ppapi_proxy::PPBCoreInterface()->IsMainThread(),\n'
|
| - s += ' (%s,\n' % error
|
| - s += ' __FUNCTION__));\n'
|
| - s += ' NaClSrpcError retval;\n'
|
| - s += ' retval = NaClSrpcInvokeBySignature%s;\n' % FormatCall(rpc)
|
| - if header_name.startswith('trusted'):
|
| - s += DeadNexeHandling(rpc, 'retval')
|
| - s += ' return retval;\n'
|
| - s += '}\n\n'
|
| - print >>output, s
|
| -
|
| -def MakePath(name):
|
| - paths = name.split(os.sep)
|
| - path = os.sep.join(paths[:-1])
|
| - try:
|
| - os.makedirs(path)
|
| - except OSError:
|
| - return
|
| -
|
| -
|
| -def main(argv):
|
| - usage = 'Usage: srpcgen.py <-c | -s> [--include=<name>] [--ppapi]'
|
| - usage = usage + ' <iname> <gname> <.h> <.cc> <specs>'
|
| -
|
| - mode = None
|
| - ppapi = False
|
| - thread_check = False
|
| - try:
|
| - long_opts = ['include=', 'ppapi', 'thread-check']
|
| - opts, pargs = getopt.getopt(argv[1:], 'cs', long_opts)
|
| - except getopt.error, e:
|
| - print >>sys.stderr, 'Illegal option:', str(e)
|
| - print >>sys.stderr, usage
|
| - return 1
|
| -
|
| - # Get the class name for the interface.
|
| - interface_name = pargs[0]
|
| - # Get the name for the token used as a multiple inclusion guard in the header.
|
| - include_guard_name = pargs[1]
|
| - # Get the name of the header file to be generated.
|
| - h_file_name = pargs[2]
|
| - MakePath(h_file_name)
|
| - # Note we open output files in binary mode so that on Windows the files
|
| - # will always get LF line-endings rather than CRLF.
|
| - h_file = open(h_file_name, 'wb')
|
| - # Get the name of the source file to be generated. Depending upon whether
|
| - # -c or -s is generated, this file contains either client or server methods.
|
| - cc_file_name = pargs[3]
|
| - MakePath(cc_file_name)
|
| - cc_file = open(cc_file_name, 'wb')
|
| - # The remaining arguments are the spec files to be compiled.
|
| - spec_files = pargs[4:]
|
| -
|
| - for opt, val in opts:
|
| - if opt == '-c':
|
| - mode = 'client'
|
| - elif opt == '-s':
|
| - mode = 'server'
|
| - elif opt == '--include':
|
| - h_file_name = val
|
| - elif opt == '--ppapi':
|
| - ppapi = True
|
| - elif opt == '--thread-check':
|
| - thread_check = True
|
| -
|
| - if ppapi:
|
| - AddInclude("ppapi/c/pp_instance.h")
|
| - AddInclude("ppapi/c/pp_module.h")
|
| - AddInclude("ppapi/c/pp_resource.h")
|
| -
|
| - # Convert to forward slash paths if needed
|
| - h_file_name = "/".join(h_file_name.split("\\"))
|
| -
|
| - # Verify we picked server or client mode
|
| - if not mode:
|
| - print >>sys.stderr, 'Neither -c nor -s specified'
|
| - usage()
|
| - return 1
|
| -
|
| - # Combine the rpc specs from spec_files into rpcs.
|
| - specs = []
|
| - for spec_file in spec_files:
|
| - code_obj = compile(open(spec_file, 'r').read(), 'file', 'eval')
|
| - specs.append(eval(code_obj))
|
| - # Print out the requested files.
|
| - if mode == 'client':
|
| - PrintHeaderFile(h_file, False, include_guard_name, interface_name, specs)
|
| - PrintClientFile(cc_file, h_file_name, specs, thread_check)
|
| - elif mode == 'server':
|
| - PrintHeaderFile(h_file, True, include_guard_name, interface_name, specs)
|
| - PrintServerFile(cc_file, h_file_name, interface_name, specs)
|
| -
|
| - return 0
|
| -
|
| -
|
| -if __name__ == '__main__':
|
| - sys.exit(main(sys.argv))
|
|
|