mirror of
https://github.com/mumble-voip/mumble.git
synced 2024-12-04 04:27:20 +00:00
330c356e71
Keeping these up-to-date is just super tedious and they don't really fulfill any purpose these days.
203 lines
8.2 KiB
Python
Executable File
203 lines
8.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
# Copyright The Mumble Developers. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license
|
|
# that can be found in the LICENSE file at the root of the
|
|
# Mumble source tree or at <https://www.mumble.info/LICENSE>.
|
|
|
|
|
|
import argparse
|
|
import re
|
|
from datetime import datetime
|
|
import os
|
|
|
|
def comment_remover(text):
|
|
def replacer(match):
|
|
s = match.group(0)
|
|
if s.startswith('/'):
|
|
return ""
|
|
else:
|
|
return s
|
|
pattern = re.compile(
|
|
r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
|
|
re.DOTALL | re.MULTILINE
|
|
)
|
|
return re.sub(pattern, replacer, text)
|
|
|
|
def fix_lineEnding(text):
|
|
# Convert from Windows to Unix
|
|
text = text.replace("\r\n", "\n")
|
|
# Convert from old Mac to Unix
|
|
text = text.replace("\r", "\n")
|
|
|
|
return text
|
|
|
|
def create_disclaimerComment():
|
|
return "// This file was auto-generated by scripts/generateIceWrapper.py on " + datetime.now().strftime("%Y-%m-%d") + " -- DO NOT EDIT MANUALLY!\n"
|
|
|
|
def generateFunction(className, functionName, wrapArgs, callArgs):
|
|
function = "void ::MumbleServer::" + className + "I::" + functionName + "_async(" + (", ".join(wrapArgs)) + ") {\n"
|
|
function += "\t// qWarning() << \"" + functionName + "\" << meta->mp.qsIceSecretRead.isNull() << meta->mp.qsIceSecretRead.isEmpty();\n"
|
|
function += "#ifndef ACCESS_" + className + "_" + functionName + "_ALL\n"
|
|
function += "#\tifdef ACCESS_" + className + "_" + functionName + "_READ\n"
|
|
function += "\tif (!meta->mp.qsIceSecretRead.isNull()) {\n"
|
|
function += "\t\tbool ok = !meta->mp.qsIceSecretRead.isEmpty();\n"
|
|
function += "#\telse\n"
|
|
function += "\tif (!meta->mp.qsIceSecretRead.isNull() || !meta->mp.qsIceSecretWrite.isNull()) {\n"
|
|
function += "\t\tbool ok = !meta->mp.qsIceSecretWrite.isEmpty();\n"
|
|
function += "#\tendif // ACCESS_" + className + "_" + functionName + "_READ\n"
|
|
function += "\t\t::Ice::Context::const_iterator i = current.ctx.find(\"secret\");\n"
|
|
function += "\t\tok = ok && (i != current.ctx.end());\n"
|
|
function += "\t\tif (ok) {\n"
|
|
function += "\t\t\tconst QString &secret = u8((*i).second);\n"
|
|
function += "#\tifdef ACCESS_" + className + "_" + functionName + "_READ\n"
|
|
function += "\t\t\tok = ((secret == meta->mp.qsIceSecretRead) || (secret == meta->mp.qsIceSecretWrite));\n"
|
|
function += "#\telse\n"
|
|
function += "\t\t\tok = (secret == meta->mp.qsIceSecretWrite);\n"
|
|
function += "#\tendif // ACCESS_" + className + "_" + functionName + "_READ\n"
|
|
function += "\t\t}\n"
|
|
function += "\n"
|
|
function += "\t\tif (!ok) {\n"
|
|
function += "\t\t\tcb->ice_exception(InvalidSecretException());\n"
|
|
function += "\t\t\treturn;\n"
|
|
function += "\t\t}\n"
|
|
function += "\t}\n"
|
|
function += "#endif // ACCESS_" + className + "_" + functionName + "_ALL\n"
|
|
function += "\n"
|
|
function += "\tExecEvent *ie = new ExecEvent(boost::bind(&impl_" + className + "_" + functionName + ", " + ", ".join(callArgs) + "));\n"
|
|
function += "\tQCoreApplication::instance()->postEvent(mi, ie);\n"
|
|
function += "}\n"
|
|
|
|
return function
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Generates the wrapper files needed for the ICE server-interface")
|
|
parser.add_argument("-i", "--ice-file", help="Path to the ICE specification file (*.ice)", metavar="PATH")
|
|
parser.add_argument("-g", "--generated-ice-header", help="Path to the header file that was generated by ICE", metavar="PATH")
|
|
parser.add_argument("-o", "--out-file", help="Path to the file to write the generated output to. If omitted, the content will be written to std::out", metavar="PATH")
|
|
parser.add_argument("-q", "--quiet", action="store_true", help="Don't display used file paths")
|
|
|
|
args = parser.parse_args()
|
|
|
|
scriptPath = os.path.realpath(__file__)
|
|
rootDir = os.path.dirname(os.path.dirname(scriptPath))
|
|
|
|
if args.ice_file is None:
|
|
# Try to figure out the path to the ice-file (MumbleServer.ice)
|
|
args.ice_file = os.path.join(rootDir, "src", "murmur", "MumbleServer.ice")
|
|
if args.generated_ice_header is None:
|
|
# Try to figure out path to the generated header file (in the build dir)
|
|
args.generated_ice_header = os.path.join(rootDir, "build", "src", "murmur", "MumbleServer.h")
|
|
|
|
if not args.quiet:
|
|
print("Using ICE-file at \"%s\"" % args.ice_file)
|
|
print("Using ICE-generated header file at \"%s\"" % args.generated_ice_header)
|
|
|
|
|
|
iceSpec = fix_lineEnding(open(args.ice_file, "r").read())
|
|
generatedIceHeader = fix_lineEnding(open(args.generated_ice_header, "r").read())
|
|
|
|
# remove comments from the iceSpec
|
|
iceSpec = comment_remover(iceSpec)
|
|
# Remove all tabs from iceSpec
|
|
iceSpec = iceSpec.replace("\t", "")
|
|
# Remove empty lines form iceSpec
|
|
iceSpec = iceSpec.replace("\n\n", "\n")
|
|
|
|
# Escape all special characters so that iceSpec can be used in a std::string ctor
|
|
iceSpec = iceSpec.replace("\"", "\\\"") # quotes
|
|
iceSpec = iceSpec.replace("\n", "\\n") # newlines
|
|
|
|
wrapperContent = create_disclaimerComment()
|
|
|
|
# Include boost-bind as we'll need it later
|
|
wrapperContent += "\n#include <boost/bind/bind.hpp>\n\n"
|
|
|
|
|
|
className = ""
|
|
for currentLine in generatedIceHeader.split("\n"):
|
|
currentLine = currentLine.strip()
|
|
|
|
if not currentLine:
|
|
# Skip empty lines
|
|
continue
|
|
|
|
# find class name
|
|
match = re.match(r"^class\s+AMD_(.+)\s+:\s+(?:public\svirtual|virtual\s+public)\s+::Ice(?:::AMDCallback|Util::Shared)", currentLine)
|
|
if match:
|
|
className = "AMD_" + match.group(1)
|
|
|
|
match = re.match(r"virtual\s+void\s+ice_response\\((.*)\\)\s+=\s+0;", currentLine)
|
|
if match:
|
|
if not className:
|
|
raise RuntimeError("Expected a className to be found at this time")
|
|
match = re.match(r"virtual\s+void\s+(.+)_async\(const\s+(.+?)&\s*\w*,(.*)\s+const\s+::Ice::Current&", currentLine)
|
|
if match:
|
|
functionName = match.group(1)
|
|
objectName = match.group(2)
|
|
arguments = match.group(3)
|
|
|
|
if functionName == "getSlice":
|
|
# getSlice is handled separately
|
|
continue
|
|
|
|
targetClass = "Server" if "AMD_Server" in objectName else "Meta"
|
|
|
|
wrapArgs = []
|
|
callArgs = []
|
|
argIndex = 0
|
|
|
|
wrapArgs.append("const %s &cb" % objectName)
|
|
callArgs.append("cb")
|
|
|
|
if targetClass == "Server":
|
|
callArgs.append("QString::fromStdString(current.id.name).toInt()")
|
|
else:
|
|
callArgs.append("current.adapter")
|
|
|
|
for currentArg in arguments.split(","):
|
|
if not currentArg:
|
|
# skip empty entries
|
|
continue
|
|
|
|
parts = currentArg.split()
|
|
if len(parts) > 1:
|
|
lastPart = parts[len(parts) - 1]
|
|
|
|
if not ":" in lastPart and not "&" in lastPart:
|
|
# Omit the last part as it is only a parameter name. We however want the parameters
|
|
# to be named p1, p2, ... which we'll do below
|
|
currentArg = " ".join(parts[:len(parts) - 1])
|
|
|
|
if len(currentArg.split()) == 1 and currentArg == "const":
|
|
# Failsafe in order for us to not only leave const as the type
|
|
# We have to include lastPart after all
|
|
currentArg += " " + lastPart
|
|
|
|
argIndex += 1
|
|
wrapArgs.append("%s p%d" % (currentArg, argIndex))
|
|
callArgs.append("p%d" % argIndex)
|
|
|
|
wrapArgs.append("const ::Ice::Current ¤t")
|
|
|
|
wrapperContent += generateFunction(targetClass, functionName, wrapArgs, callArgs) + "\n"
|
|
|
|
|
|
wrapperContent += "void ::MumbleServer::MetaI::getSlice_async(const ::MumbleServer::AMD_Meta_getSlicePtr &cb, const Ice::Current&) {\n"
|
|
wrapperContent += "\tcb->ice_response(std::string(\"" + iceSpec + "\"));\n"
|
|
wrapperContent += "}\n"
|
|
|
|
|
|
if args.out_file is None:
|
|
# Write to std::out
|
|
print(wrapperContent)
|
|
else:
|
|
# Write to file
|
|
outFile = open(args.out_file, "w")
|
|
outFile.write(wrapperContent)
|
|
|
|
|
|
|
|
main()
|