From a84007f911f00b93deb13d2b55c108d88f1a9198 Mon Sep 17 00:00:00 2001 From: sebaszm <45654185+sebaszm@users.noreply.github.com> Date: Tue, 21 Nov 2023 14:04:07 +0100 Subject: [PATCH] [StubGen/JsonGen] Support mulitple namespace scanning (#58) --- JsonGenerator/source/config.py | 23 +-- JsonGenerator/source/header_loader.py | 33 +++-- JsonGenerator/source/rpc_emitter.py | 38 ++--- LuaGenerator/GenerateLua.sh | 2 +- ProxyStubGenerator/StubGenerator.py | 193 +++++++++++++------------- cmake/FindJsonGenerator.cmake.in | 4 +- cmake/FindProxyStubGenerator.cmake.in | 4 +- 7 files changed, 160 insertions(+), 137 deletions(-) diff --git a/JsonGenerator/source/config.py b/JsonGenerator/source/config.py index a81a5e0..668ff83 100644 --- a/JsonGenerator/source/config.py +++ b/JsonGenerator/source/config.py @@ -37,7 +37,7 @@ DOC_ISSUES = True DEFAULT_DEFINITIONS_FILE = "../../ProxyStubGenerator/default.h" FRAMEWORK_NAMESPACE = "WPEFramework" -INTERFACE_NAMESPACE = "::" + FRAMEWORK_NAMESPACE + "::Exchange" +INTERFACE_NAMESPACES = ["::WPEFramework::Exchange"] INTERFACES_SECTION = True INTERFACE_SOURCE_LOCATION = None INTERFACE_SOURCE_REVISION = None @@ -66,7 +66,7 @@ class RpcFormat(Enum): def Parse(cmdline): global DEFAULT_DEFINITIONS_FILE - global INTERFACE_NAMESPACE + global INTERFACE_NAMESPACES global JSON_INTERFACE_PATH global NO_INCLUDES global NO_VERSIONING @@ -169,12 +169,11 @@ def Parse(cmdline): default=DEFAULT_DEFINITIONS_FILE, help="include a C++ header file with common types (default: include '%s')" % DEFAULT_DEFINITIONS_FILE) cpp_group.add_argument("--namespace", - dest="if_namespace", + dest="if_namespaces", metavar="NS", - type=str, - action="store", - default=INTERFACE_NAMESPACE, - help="set namespace to look for interfaces in (default: %s)" % INTERFACE_NAMESPACE) + action="append", + default=[], + help="set namespace to look for interfaces in (default: %s)" % [INTERFACE_NAMESPACES]) cpp_group.add_argument("--format", dest="format", type=str, @@ -286,13 +285,17 @@ def Parse(cmdline): DUMP_JSON = args.dump_json FORCE = args.force DEFAULT_DEFINITIONS_FILE = args.extra_include - INTERFACE_NAMESPACE = args.if_namespace - if not INTERFACE_NAMESPACE.startswith("::"): - INTERFACE_NAMESPACE = "::" + INTERFACE_NAMESPACE INTERFACES_SECTION = not args.no_interfaces_section INTERFACE_SOURCE_LOCATION = args.source_location INTERFACE_SOURCE_REVISION = args.source_revision + if args.if_namespaces: + INTERFACE_NAMESPACES = args.if_namespaces + + for i, ns in enumerate(INTERFACE_NAMESPACES): + if not ns.startswith("::"): + INTERFACE_NAMESPACES[i] = "::" + ns + if RpcFormat.EXTENDED.value in args.format: RPC_FORMAT = RpcFormat.EXTENDED elif RpcFormat.COLLAPSED.value in args.format: diff --git a/JsonGenerator/source/header_loader.py b/JsonGenerator/source/header_loader.py index 1ca8bd1..555e372 100644 --- a/JsonGenerator/source/header_loader.py +++ b/JsonGenerator/source/header_loader.py @@ -42,18 +42,15 @@ def __init__(self, obj, msg): super(CppParseError, self).__init__(msg) -def LoadInterfaceInternal(file, log, all = False, includePaths = []): +def LoadInterfaceInternal(file, tree, ns, log, all = False, includePaths = []): def StripFrameworkNamespace(identifier): return str(identifier).replace("::" + config.FRAMEWORK_NAMESPACE + "::", "") def StripInterfaceNamespace(identifier): - return str(identifier).replace(config.INTERFACE_NAMESPACE + "::", "") + return str(identifier).replace(ns + "::", "") - tree = CppParser.ParseFiles([os.path.join(os.path.dirname(os.path.realpath(__file__)), - posixpath.normpath(config.DEFAULT_DEFINITIONS_FILE)), file], includePaths, log) - - interfaces = [i for i in CppInterface.FindInterfaceClasses(tree, config.INTERFACE_NAMESPACE, file) if (i.obj.is_json or (all and not i.obj.is_event))] + interfaces = [i for i in CppInterface.FindInterfaceClasses(tree, ns, file) if (i.obj.is_json or (all and not i.obj.is_event))] def Build(face): def _EvaluateRpcFormat(obj): @@ -77,6 +74,7 @@ def _EvaluateRpcFormat(obj): schema["$schema"] = "interface.json.schema" schema["jsonrpc"] = "2.0" schema["@generated"] = True + schema["namespace"] = ns if face.obj.is_json: schema["mode"] = "auto" @@ -92,7 +90,7 @@ def _EvaluateRpcFormat(obj): info = dict() info["format"] = rpc_format.value - if not face.obj.parent.full_name.endswith(config.INTERFACE_NAMESPACE): + if not face.obj.parent.full_name.endswith(ns): info["namespace"] = face.obj.parent.name[1:] if (face.obj.parent.name[0] == "I" and face.obj.parent.name[1].isupper()) else face.obj.parent.name info["class"] = face.obj.name[1:] if face.obj.name[0] == "I" else face.obj.name @@ -417,7 +415,7 @@ def BuildResult(vars, is_property=False): if face.obj.json_prefix: prefix = (face.obj.json_prefix + "::") - elif face.obj.parent.full_name != config.INTERFACE_NAMESPACE: + elif face.obj.parent.full_name != ns: prefix = (face.obj.parent.name.lower() + "_") else: prefix = "" @@ -760,13 +758,26 @@ def BuildResult(vars, is_property=False): schema = Build(face) if schema: schemas.append(schema) - else: - log.Info("No interfaces found") return schemas, [] def LoadInterface(file, log, all = False, includePaths = []): try: - return LoadInterfaceInternal(file, log, all, includePaths) + schemas = [] + includes = [] + + tree = CppParser.ParseFiles([os.path.join(os.path.dirname(os.path.realpath(__file__)), + posixpath.normpath(config.DEFAULT_DEFINITIONS_FILE)), file], includePaths, log) + + for ns in config.INTERFACE_NAMESPACES: + s, i = LoadInterfaceInternal(file, tree, ns, log, all, includePaths) + schemas.extend(s) + includes.extend(i) + + if not schemas: + log.Info("No interfaces found") + + return schemas, includes + except CppParser.ParserError as ex: raise CppParseError(None, str(ex)) diff --git a/JsonGenerator/source/rpc_emitter.py b/JsonGenerator/source/rpc_emitter.py index b9fdc1a..3ccaa83 100644 --- a/JsonGenerator/source/rpc_emitter.py +++ b/JsonGenerator/source/rpc_emitter.py @@ -185,7 +185,7 @@ def Emit(parameters): emit.Line() -def _EmitRpcPrologue(root, emit, header_file, source_file, data_emitted, prototypes = []): +def _EmitRpcPrologue(root, emit, header_file, source_file, ns, data_emitted, prototypes = []): json_source = source_file.endswith(".json") emit.Line() @@ -221,9 +221,9 @@ def _EmitRpcPrologue(root, emit, header_file, source_file, data_emitted, prototy emit.Line() - for i, ns in enumerate(config.INTERFACE_NAMESPACE.split("::")): - if ns: - emit.Line("namespace %s {" % ns) + for i, ns_ in enumerate(ns.split("::")): + if ns_: + emit.Line("namespace %s {" % ns_) if i >= 2: emit.Indent() emit.Line() @@ -241,7 +241,7 @@ def _EmitRpcPrologue(root, emit, header_file, source_file, data_emitted, prototy emit.Indent() emit.Line() -def _EmitRpcEpilogue(root, emit): +def _EmitRpcEpilogue(root, emit, ns): emit.Unindent() emit.Line("} // namespace %s" % ("J" + root.json_name)) emit.Line() @@ -251,11 +251,11 @@ def _EmitRpcEpilogue(root, emit): emit.Line("} // namespace %s" % root.schema["info"]["namespace"]) emit.Line() - for i, ns in reversed(list(enumerate(config.INTERFACE_NAMESPACE.split("::")))): - if ns: + for i, ns_ in reversed(list(enumerate(ns.split("::")))): + if ns_: if i >= 2: emit.Unindent() - emit.Line("} // namespace %s" % ns) + emit.Line("} // namespace %s" % ns_) emit.Line() emit.Line() @@ -271,11 +271,11 @@ def _EmitVersionCode(emit, version): emit.Unindent() emit.Line("} // namespace Version") -def _EmitRpcCode(root, emit, header_file, source_file, data_emitted): +def _EmitRpcCode(root, emit, ns, header_file, source_file, data_emitted): json_source = source_file.endswith(".json") - for i, ns in enumerate(config.INTERFACE_NAMESPACE.split("::")): - if ns and i >= 2: + for i, ns_ in enumerate(ns.split("::")): + if ns_ and i >= 2: emit.Indent() if "info" in root.schema and "namespace" in root.schema["info"]: @@ -836,15 +836,21 @@ def _Invoke(params, response, use_prefix = True, const_cast = False, parent = "" return prototypes def EmitRpcCode(root, emit, header_file, source_file, data_emitted): - prototypes = _EmitRpcCode(root, emit, header_file, source_file, data_emitted) + + ns = root.schema["namespace"] if "namespace" in root.schema else "::WPEFramework::Exchange" + + prototypes = _EmitRpcCode(root, emit, ns, header_file, source_file, data_emitted) with emitter.Emitter(None, config.INDENT_SIZE) as prototypes_emitter: - _EmitRpcPrologue(root, prototypes_emitter, header_file, source_file, data_emitted, prototypes) + _EmitRpcPrologue(root, prototypes_emitter, header_file, source_file, ns, data_emitted, prototypes) emit.Prepend(prototypes_emitter) - _EmitRpcEpilogue(root, emit) + _EmitRpcEpilogue(root, emit, ns) def EmitRpcVersionCode(root, emit, header_file, source_file, data_emitted): - _EmitRpcPrologue(root, emit, header_file, source_file, data_emitted) + + ns = root.schema["namespace"] if "namespace" in root.schema else "::WPEFramework::Exchange" + + _EmitRpcPrologue(root, emit, header_file, source_file, ns, data_emitted) _EmitVersionCode(emit, rpc_version.GetVersion(root.schema["info"] if "info" in root.schema else dict())) - _EmitRpcEpilogue(root, emit) + _EmitRpcEpilogue(root, emit, ns) diff --git a/LuaGenerator/GenerateLua.sh b/LuaGenerator/GenerateLua.sh index 08661e5..5f80694 100755 --- a/LuaGenerator/GenerateLua.sh +++ b/LuaGenerator/GenerateLua.sh @@ -33,7 +33,7 @@ THUNDER_DIR="${1:-../../Thunder}" INTERFACES_DIR="${2:-../../ThunderInterfaces}" files="$THUNDER_DIR/Source/com/ICOM.h" -files="$files $THUNDER_DIR/Source/plugins/IController.h $THUNDER_DIR/Source/plugins/IPlugin.h $THUNDER_DIR/Source/plugins/IShell.h $THUNDER_DIR/Source/plugins/IStateControl.h $THUNDER_DIR/Source/plugins/ISubSystem.h $THUNDER_DIR/Source/plugins/IDispatcher.h" +files="$files $THUNDER_DIR/Source/plugins/IController.h $THUNDER_DIR/Source/plugins/IControllerDeprecated.h $THUNDER_DIR/Source/plugins/IPlugin.h $THUNDER_DIR/Source/plugins/IShell.h $THUNDER_DIR/Source/plugins/IStateControl.h $THUNDER_DIR/Source/plugins/ISubSystem.h $THUNDER_DIR/Source/plugins/IDispatcher.h" files="$files $INTERFACES_DIR/interfaces/I*.h" # add more interface files if needed.. diff --git a/ProxyStubGenerator/StubGenerator.py b/ProxyStubGenerator/StubGenerator.py index 4cc4550..471c34b 100755 --- a/ProxyStubGenerator/StubGenerator.py +++ b/ProxyStubGenerator/StubGenerator.py @@ -44,7 +44,7 @@ EMIT_COMMENT_WITH_PROTOTYPE = True EMIT_COMMENT_WITH_STUB_ORDER = True STUB_NAMESPACE = "::WPEFramework::ProxyStubs" -INTERFACE_NAMESPACE = "::WPEFramework" +INTERFACE_NAMESPACES = ["::WPEFramework"] CLASS_IUNKNOWN = "::WPEFramework::Core::IUnknown" PROXYSTUB_CPP_NAME = "ProxyStubs_%s.cpp" @@ -123,14 +123,14 @@ def __init__(self, obj, iid, file): # Looks for interface classes (ie. classes inheriting from Core::Unknown and specifying ID enum). -def FindInterfaceClasses(tree): +def FindInterfaceClasses(tree, namespace): interfaces = [] - def __Traverse(tree, faces): + def __Traverse(tree, interface_namespace, faces): if isinstance(tree, CppParser.Namespace) or isinstance(tree, CppParser.Class): for c in tree.classes: if not isinstance(c, CppParser.TemplateClass): - if (c.full_name.startswith(INTERFACE_NAMESPACE + "::")): + if (c.full_name.startswith(interface_namespace + "::")): inherits_iunknown = False for a in c.ancestors: if CLASS_IUNKNOWN in str(a[0]): @@ -151,21 +151,19 @@ def __Traverse(tree, faces): if not has_id and not c.omit: log.Warn("class %s does not have an ID enumerator" % c.full_name, source_file) - elif not c.omit: - log.Info("class %s not in %s namespace" % (c.full_name, INTERFACE_NAMESPACE), source_file) - - __Traverse(c, faces) + __Traverse(c, interface_namespace, faces) if isinstance(tree, CppParser.Namespace): for n in tree.namespaces: - __Traverse(n, faces) + __Traverse(n, namespace, faces) + + __Traverse(tree, namespace, interfaces) - __Traverse(tree, interfaces) return interfaces # Cut out scope resolution operators from all identifiers found in a string -def Flatten(identifier, scope=INTERFACE_NAMESPACE): +def Flatten(identifier, scope): assert scope.startswith("::") split = scope.replace(" ", "").split("::") split[0] = ("::" + split[1]) @@ -189,12 +187,15 @@ def Flatten(identifier, scope=INTERFACE_NAMESPACE): # Generate interface information in lua -def GenerateLuaData(emit, interfaces_list, enums_list, source_file, includePaths = [], defaults = "", extra_includes = []): +def GenerateLuaData(emit, interfaces_list, enums_list, source_file=None, tree=None, ns=None): if not source_file: + assert(tree==None) + assert(ns==None) + emit.Line("-- enums") - for k,v in lua_enums.items(): + for k,v in enums_list.items(): emit.Line("ENUMS[\"%s\"] = {" % k) emit.IndentInc() text = [] @@ -211,22 +212,9 @@ def GenerateLuaData(emit, interfaces_list, enums_list, source_file, includePaths return - files = [] - - if defaults: - files.append(defaults) - - files.extend(extra_includes) - files.append(source_file) - - tree = CppParser.ParseFiles(files, includePaths, log) - - if not isinstance(tree, CppParser.Namespace): - raise SkipFileError(source_file) - - interfaces = FindInterfaceClasses(tree) + interfaces = FindInterfaceClasses(tree, ns) if not interfaces: - raise NoInterfaceError(source_file) + return [] if not interfaces_list: emit.Line("-- Interfaces definition data file") @@ -237,18 +225,18 @@ def GenerateLuaData(emit, interfaces_list, enums_list, source_file, includePaths emit.Line("-- %s" % os.path.basename(source_file)) - iface_namespace_l = INTERFACE_NAMESPACE.split("::") + iface_namespace_l = ns.split("::") iface_namespace = iface_namespace_l[-1] for iface in interfaces: - iface_name = Flatten(iface.obj.type) + iface_name = Flatten(iface.obj.type, ns) interfaces_var_name = "INTERFACES" methods_var_name = "METHODS" assume_hresult = iface.obj.is_json - if not iface.obj.full_name.startswith(INTERFACE_NAMESPACE): + if not iface.obj.full_name.startswith(ns): continue # interface in other namespace if iface.obj.omit: @@ -381,12 +369,12 @@ def Convert(paramtype, retval, vars, hresult=False): elif isinstance(p, CppParser.Class): if param.IsPointer(): - return ["type = Type.OBJECT", "class = \"%s\"" % Flatten(param.TypeName())] + return ["type = Type.OBJECT", "class = \"%s\"" % Flatten(param.TypeName(), ns)] else: - value = ["type = Type.POD", "class = \"%s\"" % Flatten(param.type.full_name)] + value = ["type = Type.POD", "class = \"%s\"" % Flatten(param.type.full_name, ns)] pod_params = [] - kind = p.vars.Merge() + kind = p.Merge() for v in kind.vars: param_info = Convert(v, None, kind.vars) @@ -415,7 +403,7 @@ def Convert(paramtype, retval, vars, hresult=False): if p.type.Type().signed: signed = "" - name = Flatten(param.type.full_name) + name = Flatten(param.type.full_name, ns) if name not in enums_list: data = dict() @@ -507,12 +495,9 @@ def Convert(paramtype, retval, vars, hresult=False): emit.Line("}") emit.Line() +def Parse(source_file, includePaths = [], defaults = "", extra_includes = []): -def GenerateStubs2(output_file, source_file, includePaths = [], defaults = "", extra_includes = [], scan_only=False): - log.Info("Parsing '%s'..." % source_file) - - if not FORCE and (os.path.exists(output_file) and (os.path.getmtime(source_file) < os.path.getmtime(output_file))): - raise NotModifiedException(output_file) + log.Info("Parsing %s..." % source_file) files = [] @@ -526,16 +511,24 @@ def GenerateStubs2(output_file, source_file, includePaths = [], defaults = "", e if not isinstance(tree, CppParser.Namespace): raise SkipFileError(source_file) - interfaces = FindInterfaceClasses(tree) + return tree + +def GenerateStubs2(output_file, source_file, tree, ns, scan_only=False): + log.Info("Scanning '%s' (in %s)..." % (source_file, ns)) + + if not FORCE and (os.path.exists(output_file) and (os.path.getmtime(source_file) < os.path.getmtime(output_file))): + raise NotModifiedException(output_file) + + interfaces = FindInterfaceClasses(tree, ns) if not interfaces: - raise NoInterfaceError(source_file) + return [] if scan_only: return interfaces interface_header_name = os.path.basename(source_file) - interface_namespace = INTERFACE_NAMESPACE.split("::")[-1] + interface_namespace = ns.split("::")[-1] with open(output_file, "w") as file: emit = Emitter(file, INDENT_SIZE) @@ -547,7 +540,7 @@ def GenerateStubs2(output_file, source_file, includePaths = [], defaults = "", e for face in interfaces: if not face.obj.omit: - emit.Line("// - %s" % Flatten(str(face.obj))) + emit.Line("// - %s" % Flatten(str(face.obj), ns)) emit.Line("//") @@ -667,7 +660,7 @@ def _FindLength(length_name, variable_name): if not isinstance(identifier.type, CppParser.Type): undefined = CppParser.Type(CppParser.Undefined(identifier.type)) if not identifier.parent.stub and not identifier.parent.omit: - raise TypenameError(identifier, "'%s': undefined type" % Flatten(str(" ".join(identifier.type)))) + raise TypenameError(identifier, "'%s': undefined type" % Flatten(str(" ".join(identifier.type)), ns)) else: type_ = undefined else: @@ -690,7 +683,7 @@ def _FindLength(length_name, variable_name): self.is_const = not identifier.meta.output # Yields identifier name as in the soruce code, meaningful for a human - self.trace_proto = Flatten(self.identifier.Signature()) + self.trace_proto = Flatten(self.identifier.Signature(), ns) if not self.identifier.name.startswith("__unnamed") and \ (self.identifier.name.startswith("_") or self.identifier.name.endswith("_")): @@ -761,8 +754,8 @@ def _FindLength(length_name, variable_name): if (self.is_buffer and self.is_output and not self.max_length): raise TypenameError(self.identifier, "'%s': can't deduce maximum length of the buffer, use @maxlength" % self.trace_proto) - if (self.is_buffer and self.max_length and not self.length): - log.WarnLine(self.identifier, "'%s': length of returned buffer is not specified" % self.trace_proto) + #if (self.is_buffer and self.max_length and not self.length): + # log.WarnLine(self.identifier, "'%s': length of returned buffer is not specified" % self.trace_proto) # Is it a hresult? self.is_hresult = self.identifier_type.TypeName().endswith("Core::hresult") \ @@ -785,13 +778,13 @@ def _FindLength(length_name, variable_name): if has_proxy: # Have to use instance_id instead of the class name - self.type_name = Flatten(self.identifier_type.TypeName()) + self.type_name = Flatten(self.identifier_type.TypeName(), ns) self.proto = (("const " if self.is_const else "") + INSTANCE_ID).strip() self.proto_no_cv = INSTANCE_ID else: - self.type_name = Flatten(self.identifier_type.TypeName()) - self.proto = Flatten(self.identifier_type.Proto("noref")) - self.proto_no_cv = Flatten(self.identifier_type.Proto("nocv|noref")) + self.type_name = Flatten(self.identifier_type.TypeName(), ns) + self.proto = Flatten(self.identifier_type.Proto("noref"), ns) + self.proto_no_cv = Flatten(self.identifier_type.Proto("nocv|noref"), ns) if has_proxy: self.name = ("%sImplementation" % name[1:]) @@ -1087,7 +1080,7 @@ def EmitFunctionOrder(methods): emit.Line("// Methods:") for index, method in enumerate(methods): - emit.Line("// (%i) %s" % (index, Flatten(method.Proto()))) + emit.Line("// (%i) %s" % (index, Flatten(method.Proto(), ns))) emit.Line("//") @@ -1146,12 +1139,12 @@ def PrepareParams(method, interface): # Build the announce list upfront for interface in interfaces: obj = interface.obj - interface_name = Flatten(obj.full_name) + interface_name = Flatten(obj.full_name, ns) - log.Info("Processing '%s' interface data..." % Flatten(obj.type)) + log.Info("Processing '%s' interface data..." % Flatten(obj.type, ns)) - if not obj.full_name.startswith(INTERFACE_NAMESPACE + "::"): - log.Info("class %s not in requested namespace (%s)" % (obj.full_name, INTERFACE_NAMESPACE)) + if not obj.full_name.startswith(ns + "::"): + log.Info("class %s not in requested namespace (%s)" % (obj.full_name, ns)) elif obj.omit: log.Info("omitting class %s" % interface_name) else: @@ -1407,10 +1400,10 @@ def CallImplementation(retval, params): if interface.obj.is_iterator: face_name = vars["interface"] - emit.Line("using %s = %s;" % (vars["interface"], Flatten(interface.obj.type))) + emit.Line("using %s = %s;" % (vars["interface"], Flatten(interface.obj.type, ns))) emit.Line() else: - face_name = Flatten(interface.obj.type) + face_name = Flatten(interface.obj.type, ns) if ENABLE_INTEGRITY_VERIFICATION: emit.Line("if (%s->Parameters().Length() < (sizeof(%s) + sizeof(uint32_t) + 1)) { return (COM_ERROR | Core::ERROR_READ_ERROR); }" % (vars["message"], INSTANCE_ID)) @@ -1497,7 +1490,7 @@ def CallImplementation(retval, params): emit.Line("%s.Number(%s);" % (vars["writer"], hresult.as_rvalue)) emit.Line("fprintf(stderr, \"COM-RPC stub 0x%%08x(%%u) failed: 0x%%08x\\n\", %s, %s, %s);" \ - % (Flatten(interface.obj.type) + "::ID", index, hresult.as_rvalue)) + % (Flatten(interface.obj.type, ns) + "::ID", index, hresult.as_rvalue)) if not has_hresult: emit.Line("TRACE_L1(\"Warning: This COM-RPC failure will not propagate!\");") @@ -1513,7 +1506,7 @@ def EmitStubMethod(index, last, method, interface_name, interface, prepared_para channel = "/* channel */" if method.stub or (not proxy_params and not return_proxy_params and not ENABLE_INSTANCE_VERIFICATION) else vars["channel"] message = "/* message */" if method.stub else vars["message"] - emit.Line("// (%i) %s" % (index, Flatten(method.Proto()))) + emit.Line("// (%i) %s" % (index, Flatten(method.Proto(), ns))) emit.Line("//") emit.Line("[](Core::ProxyType& %s, Core::ProxyType& %s) {" % (channel, message)) emit.IndentInc() @@ -1537,7 +1530,7 @@ def EmitStubMethod(index, last, method, interface_name, interface, prepared_para def EmitStub(interface_name, methods, stub_methods_name, interface, prepared_params): if BE_VERBOSE: - log.Print("Emitting stub code for interface %s..." % Flatten(interface.obj.type)) + log.Print("Emitting stub code for interface %s..." % Flatten(interface.obj.type, ns)) # Emit class summary emit.Line("//") @@ -1751,7 +1744,7 @@ def ReadParameter(p): emit.Line("if ((%s & COM_ERROR) != 0) {" % hresult.as_rvalue) emit.IndentInc() emit.Line("fprintf(stderr, \"COM-RPC call 0x%%08x(%%u) failed: 0x%%08x\\n\", %s, %s, %s);" \ - % (Flatten(interface.obj.type) + "::ID", index, hresult.as_rvalue)) + % (Flatten(interface.obj.type, ns) + "::ID", index, hresult.as_rvalue)) if not reuse_hresult: emit.Line("TRACE_L1(\"Warning: This COM-RPC failure will not propagate!\");") @@ -1775,9 +1768,9 @@ def ReadParameter(p): def EmitProxyMethod(index, method, interface_name, interface, prepared_params): retval, params, input_params, output_params, proxy_params, return_proxy_params = prepared_params - method_type = ((Flatten(retval.identifier.Proto()) + " ") if retval else "void ") + method_type = ((Flatten(retval.identifier.Proto(), ns) + " ") if retval else "void ") method_qualifiers = ((" const" if "const" in method.qualifiers else "") + " override") - params_list = [(Flatten(p.identifier.Proto()) + ((" " + p.as_in_prototype) if not method.stub else "")) for p in params] + params_list = [(Flatten(p.identifier.Proto(), ns) + ((" " + p.as_in_prototype) if not method.stub else "")) for p in params] emit.Line("%s%s(%s)%s" % (method_type, method.name, ", ".join(params_list), method_qualifiers)) emit.Line("{") emit.IndentInc() @@ -1805,7 +1798,7 @@ def EmitProxyMethod(index, method, interface_name, interface, prepared_params): def EmitProxy(interface_name, methods, proxy_name, interface, prepared_params): if BE_VERBOSE: - log.Print("Emitting proxy code for interface %s..." % Flatten(interface.obj.type)) + log.Print("Emitting proxy code for interface %s..." % Flatten(interface.obj.type, ns)) # Emit class summary emit.Line("//") @@ -1815,7 +1808,7 @@ def EmitProxy(interface_name, methods, proxy_name, interface, prepared_params): emit.Line() # Emit proxy class definition - emit.Line("class %s final : public ProxyStub::UnknownProxyType<%s> {" % (proxy_name, Flatten(interface.obj.type))) + emit.Line("class %s final : public ProxyStub::UnknownProxyType<%s> {" % (proxy_name, Flatten(interface.obj.type, ns))) emit.Line("public:") emit.IndentInc() @@ -1859,7 +1852,7 @@ def EmitProxy(interface_name, methods, proxy_name, interface, prepared_params): emit.Line() for _, [_, methods, stub, _, interface, _ ] in announce_list.items(): - emit.Line("typedef ProxyStub::UnknownStubType<%s, %s> %s;" % (Flatten(interface.obj.type), methods, stub)) + emit.Line("typedef ProxyStub::UnknownStubType<%s, %s> %s;" % (Flatten(interface.obj.type, ns), methods, stub)) emit.Line() @@ -1871,13 +1864,13 @@ def EmitProxy(interface_name, methods, proxy_name, interface, prepared_params): emit.IndentInc() if EMIT_TRACES: - emit.Line("fprintf(stderr, \"*** Announcing %s interface methods...\\n\");" % Flatten(interface.obj.type)) + emit.Line("fprintf(stderr, \"*** Announcing %s interface methods...\\n\");" % Flatten(interface.obj.type, ns)) for _, [_, _, stub, proxy, interface, _ ] in announce_list.items(): - emit.Line("RPC::Administrator::Instance().Announce<%s, %s, %s>();" % (Flatten(interface.obj.type), proxy, stub)) + emit.Line("RPC::Administrator::Instance().Announce<%s, %s, %s>();" % (Flatten(interface.obj.type, ns), proxy, stub)) if EMIT_TRACES: - emit.Line("fprintf(stderr, \"*** Announcing %s interface methods... done\\n\");" % Flatten(interface.obj.type)) + emit.Line("fprintf(stderr, \"*** Announcing %s interface methods... done\\n\");" % Flatten(interface.obj.type, ns)) emit.IndentDec() emit.Line("}") @@ -1887,13 +1880,13 @@ def EmitProxy(interface_name, methods, proxy_name, interface, prepared_params): emit.IndentInc() if EMIT_TRACES: - emit.Line("fprintf(stderr, \"*** Recalling %s interface methods...\\n\");" % Flatten(interface.obj.type)) + emit.Line("fprintf(stderr, \"*** Recalling %s interface methods...\\n\");" % Flatten(interface.obj.type, ns)) for _, [_, _, _, _, interface, _ ] in announce_list.items(): - emit.Line("RPC::Administrator::Instance().Recall<%s>();" % (Flatten(interface.obj.type))) + emit.Line("RPC::Administrator::Instance().Recall<%s>();" % (Flatten(interface.obj.type, ns))) if EMIT_TRACES: - emit.Line("fprintf(stderr, \"*** Announcing %s interface methods... done\\n\");" % Flatten(interface.obj.type)) + emit.Line("fprintf(stderr, \"*** Announcing %s interface methods... done\\n\");" % Flatten(interface.obj.type, ns)) emit.IndentDec() emit.Line("}") @@ -1995,12 +1988,11 @@ def GenerateIdentification(name): default=False, help="emit additional debug traces (default: no extra traces)") argparser.add_argument("--namespace", - dest="if_namespace", + dest="if_namespaces", metavar="NS", - type=str, - action="store", - default=INTERFACE_NAMESPACE, - help="set the namespace to look for interfaces in (default: %s)" % INTERFACE_NAMESPACE) + action="append", + default=[], + help="set a namespace to look for interfaces in (default: %s)" % INTERFACE_NAMESPACES[0]) argparser.add_argument("--outdir", dest="outdir", metavar="DIR", @@ -2046,14 +2038,17 @@ def GenerateIdentification(name): ENABLE_SECURE = ENABLE_INSTANCE_VERIFICATION or ENABLE_RANGE_VERIFICATION or ENABLE_INTEGRITY_VERIFICATION log.show_infos = BE_VERBOSE log.show_warnings = SHOW_WARNINGS - INTERFACE_NAMESPACE = args.if_namespace OUTDIR = args.outdir EMIT_TRACES = args.traces scan_only = False keep_incomplete = args.keep_incomplete - if INTERFACE_NAMESPACE[0:2] != "::": - INTERFACE_NAMESPACE = "::" + INTERFACE_NAMESPACE + if args.if_namespaces: + INTERFACE_NAMESPACES = args.if_namespaces + + for i, ns in enumerate(INTERFACE_NAMESPACES): + if not ns.startswith("::"): + INTERFACE_NAMESPACES[i] = "::" + ns if args.help_tags: print("The following special tags are supported:") @@ -2161,6 +2156,10 @@ def GenerateIdentification(name): _extra_includes = [ os.path.join("@" + os.path.dirname(source_file), IDS_DEFINITIONS_FILE) ] _extra_includes.extend(args.extra_includes) + tree = Parse(source_file, args.includePaths, + os.path.join("@" + os.path.dirname(os.path.realpath(__file__)), DEFAULT_DEFINITIONS_FILE), + _extra_includes) + if args.code: log.Header(source_file) @@ -2171,14 +2170,17 @@ def GenerateIdentification(name): if not os.path.exists(out_dir): os.makedirs(out_dir) - output = GenerateStubs2( - output_file, source_file, - args.includePaths, - os.path.join("@" + os.path.dirname(os.path.realpath(__file__)), DEFAULT_DEFINITIONS_FILE), - _extra_includes, - scan_only) + new_faces = [] - faces += output + for ns in INTERFACE_NAMESPACES: + output = GenerateStubs2(output_file, source_file, tree, ns, scan_only) + + new_faces += output + + if not new_faces: + raise NoInterfaceError + + faces += new_faces log.Print("created file %s" % os.path.basename(output_file)) @@ -2189,9 +2191,9 @@ def GenerateIdentification(name): if args.lua_code: log.Print("(lua generator) Scanning %s..." % os.path.basename(source_file)) - GenerateLuaData(Emitter(lua_file, INDENT_SIZE), lua_interfaces, lua_enums, source_file, args.includePaths, - os.path.join("@" + os.path.dirname(os.path.realpath(__file__)), DEFAULT_DEFINITIONS_FILE), - _extra_includes) + + for ns in INTERFACE_NAMESPACES: + GenerateLuaData(Emitter(lua_file, INDENT_SIZE), lua_interfaces, lua_enums, source_file, tree, ns) except NotModifiedException as err: log.Print("skipped file %s, up-to-date" % os.path.basename(output_file)) @@ -2200,7 +2202,7 @@ def GenerateIdentification(name): log.Print("skipped file %s" % os.path.basename(output_file)) skipped.append(source_file) except NoInterfaceError as err: - log.Warn("no interface classes found in %s" % (INTERFACE_NAMESPACE), os.path.basename(source_file)) + log.Warn("no interface classes found") except TypenameError as err: log.Error(err) if not keep_incomplete and os.path.isfile(output_file): @@ -2241,8 +2243,9 @@ def GenerateIdentification(name): if args.lua_code: # Epilogue - GenerateLuaData(Emitter(lua_file, INDENT_SIZE), lua_interfaces, lua_enums, None) - log.Print("Created %s (%s interfaces, %s enums)" % (lua_file.name, len(lua_interfaces), len(lua_enums))) + for ns in INTERFACE_NAMESPACES: + GenerateLuaData(Emitter(lua_file, INDENT_SIZE), lua_interfaces, lua_enums) + log.Print("Created %s (%s interfaces, %s enums)" % (lua_file.name, len(lua_interfaces), len(lua_enums))) else: log.Print("Nothing to do") diff --git a/cmake/FindJsonGenerator.cmake.in b/cmake/FindJsonGenerator.cmake.in index 926d8c2..c52be6c 100644 --- a/cmake/FindJsonGenerator.cmake.in +++ b/cmake/FindJsonGenerator.cmake.in @@ -31,8 +31,8 @@ function(JsonGenerator) endif() set(optionsArgs CODE STUBS DOCS NO_INCLUDES NO_STYLE_WARNINGS COPY_CTOR NO_REF_NAMES NO_INTERFACES_SECTION VERBOSE FORCE_GENERATE) - set(oneValueArgs OUTPUT IFDIR CPPIFDIR INDENT DEF_STRING DEF_INT_SIZE PATH FORMAT NAMESPACE) - set(multiValueArgs INPUT INCLUDE_PATH) + set(oneValueArgs OUTPUT IFDIR CPPIFDIR INDENT DEF_STRING DEF_INT_SIZE PATH FORMAT) + set(multiValueArgs INPUT INCLUDE_PATH NAMESPACE) cmake_parse_arguments(Argument "${optionsArgs}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) diff --git a/cmake/FindProxyStubGenerator.cmake.in b/cmake/FindProxyStubGenerator.cmake.in index 00f988d..e6e2709 100644 --- a/cmake/FindProxyStubGenerator.cmake.in +++ b/cmake/FindProxyStubGenerator.cmake.in @@ -31,8 +31,8 @@ function(ProxyStubGenerator) endif() set(optionsArgs SECURE COHERENT TRACES VERBOSE NO_WARNINGS KEEP FORCE_GENERATE) - set(oneValueArgs NAMESPACE OUTDIR) - set(multiValueArgs INPUT INCLUDE INCLUDE_PATH) + set(oneValueArgs OUTDIR) + set(multiValueArgs INPUT INCLUDE INCLUDE_PATH NAMESPACE) cmake_parse_arguments(Argument "${optionsArgs}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )