diff options
author | Marc-André Lureau <marcandre.lureau@gmail.com> | 2016-03-10 15:18:06 +0100 |
---|---|---|
committer | Marc-André Lureau <marcandre.lureau@redhat.com> | 2016-03-10 16:01:36 +0100 |
commit | 1cd26b87c10870ea9bfb65b4640d2e318b45aafb (patch) | |
tree | d6488289140a7082bea97ea12ab2eaa551f401e1 /python_modules/codegen.py | |
parent | f06f699d7817354a532f091f46044720f9045887 (diff) |
Revert "Remove files moved to spice-protocol"
This reverts commit 7665dcf1bb2fa0b16b3d0015b28d7f5912664c3f.
Also revert the related build-sys changes to fix the build.
codegen generated code depends on spice-common code (marshaller,
messages etc), it makes more sense to keep the generator along
this. Otherwise a newer protocol release will fail to build older
projects.
*.proto files are required as well, since it generates code that parent
modules depend on unconditionnaly.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Diffstat (limited to 'python_modules/codegen.py')
-rw-r--r-- | python_modules/codegen.py | 380 |
1 files changed, 380 insertions, 0 deletions
diff --git a/python_modules/codegen.py b/python_modules/codegen.py new file mode 100644 index 0000000..f7a2048 --- /dev/null +++ b/python_modules/codegen.py @@ -0,0 +1,380 @@ + +import six +from io import StringIO + +def camel_to_underscores(s, upper = False): + res = "" + for i in range(len(s)): + c = s[i] + if i > 0 and c.isupper(): + res = res + "_" + if upper: + res = res + c.upper() + else: + res = res + c.lower() + return res + +def underscores_to_camel(s): + res = "" + do_upper = True + for i in range(len(s)): + c = s[i] + if c == "_": + do_upper = True + else: + if do_upper: + res = res + c.upper() + else: + res = res + c + do_upper = False + return res + +proto_prefix = "Temp" + +def set_prefix(prefix): + global proto_prefix + global proto_prefix_upper + global proto_prefix_lower + proto_prefix = prefix + proto_prefix_upper = prefix.upper() + proto_prefix_lower = prefix.lower() + +def prefix_underscore_upper(*args): + s = proto_prefix_upper + for arg in args: + s = s + "_" + arg + return s + +def prefix_underscore_lower(*args): + s = proto_prefix_lower + for arg in args: + s = s + "_" + arg + return s + +def prefix_camel(*args): + s = proto_prefix + for arg in args: + s = s + underscores_to_camel(arg) + return s + +def increment_identifier(idf): + v = idf[-1:] + if v.isdigit(): + return idf[:-1] + str(int(v) + 1) + return idf + "2" + +def sum_array(array): + if len(array) == 0: + return 0 + return " + ".join(array) + +class CodeWriter: + def __init__(self): + self.out = StringIO() + self.contents = [self.out] + self.indentation = 0 + self.at_line_start = True + self.indexes = ["i", "j", "k", "ii", "jj", "kk"] + self.current_index = 0 + self.generated = {} + self.vars = [] + self.has_error_check = False + self.options = {} + self.function_helper_writer = None + self.index_type = 'uint32_t' + + def set_option(self, opt, value = True): + self.options[opt] = value + + def has_option(self, opt): + return opt in self.options + + def set_is_generated(self, kind, name): + if kind not in self.generated: + v = {} + self.generated[kind] = v + else: + v = self.generated[kind] + v[name] = 1 + + def is_generated(self, kind, name): + if kind not in self.generated: + return False + v = self.generated[kind] + return name in v + + def getvalue(self): + strs = [writer.getvalue() for writer in self.contents] + return "".join(strs) + + def get_subwriter(self): + writer = CodeWriter() + self.contents.append(writer) + self.out = StringIO() + self.contents.append(self.out) + writer.indentation = self.indentation + writer.at_line_start = self.at_line_start + writer.index_type = self.index_type + writer.generated = self.generated + writer.options = self.options + writer.public_prefix = self.public_prefix + + return writer + + def write(self, s): + # Ensure its a unicode string + if six.PY3: + s = str(s) + else: + s = unicode(s) + + if len(s) == 0: + return + + if self.at_line_start: + self.out.write(u" " * self.indentation) + self.at_line_start = False + self.out.write(s) + return self + + def newline(self): + self.out.write(u"\n") + self.at_line_start = True + return self + + def writeln(self, s): + self.write(s) + self.newline() + return self + + def label(self, s): + self.indentation = self.indentation - 1 + self.write(s + ":") + self.indentation = self.indentation + 1 + self.newline() + + def statement(self, s): + self.write(s) + self.write(";") + self.newline() + return self + + def assign(self, var, val): + self.write("%s = %s" % (var, val)) + self.write(";") + self.newline() + return self + + def increment(self, var, val): + self.write("%s += %s" % (var, val)) + self.write(";") + self.newline() + return self + + def comment(self, str): + self.write("/* " + str + " */") + return self + + def todo(self, str): + self.comment("TODO: *** %s ***" % str).newline() + return self + + def error_check(self, check, label = "error"): + self.has_error_check = True + with self.block("if (SPICE_UNLIKELY(%s))" % check): + if self.has_option("print_error"): + self.statement('printf("%%s: Caught error - %s", __PRETTY_FUNCTION__)' % check) + if self.has_option("assert_on_error"): + self.statement("assert(0)") + self.statement("goto %s" % label) + + def indent(self): + self.indentation += 4 + + def unindent(self): + self.indentation -= 4 + if self.indentation < 0: + self.indentation = 0 + + def begin_block(self, prefix= "", comment = ""): + if len(prefix) > 0: + self.write(prefix) + if self.at_line_start: + self.write("{") + else: + self.write(" {") + if len(comment) > 0: + self.write(" ") + self.comment(comment) + self.newline() + self.indent() + + def end_block(self, semicolon=False, newline=True): + self.unindent() + if self.at_line_start: + self.write("}") + else: + self.write(" }") + if semicolon: + self.write(";") + if newline: + self.newline() + + class Block: + def __init__(self, writer, semicolon, newline): + self.writer = writer + self.semicolon = semicolon + self.newline = newline + + def __enter__(self): + return self.writer.get_subwriter() + + def __exit__(self, exc_type, exc_value, traceback): + self.writer.end_block(self.semicolon, self.newline) + + class PartialBlock: + def __init__(self, writer, scope, semicolon, newline): + self.writer = writer + self.scope = scope + self.semicolon = semicolon + self.newline = newline + + def __enter__(self): + return self.scope + + def __exit__(self, exc_type, exc_value, traceback): + self.writer.end_block(self.semicolon, self.newline) + + class NoBlock: + def __init__(self, scope): + self.scope = scope + + def __enter__(self): + return self.scope + + def __exit__(self, exc_type, exc_value, traceback): + pass + + def block(self, prefix= "", comment = "", semicolon=False, newline=True): + self.begin_block(prefix, comment) + return self.Block(self, semicolon, newline) + + def partial_block(self, scope, semicolon=False, newline=True): + return self.PartialBlock(self, scope, semicolon, newline) + + def no_block(self, scope): + return self.NoBlock(scope) + + def optional_block(self, scope): + if scope != None: + return self.NoBlock(scope) + return self.block() + + def for_loop(self, index, limit): + return self.block("for (%s = 0; %s < %s; %s++)" % (index, index, limit, index)) + + def while_loop(self, expr): + return self.block("while (%s)" % (expr)) + + def if_block(self, check, elseif=False, newline=True): + s = "if (%s)" % (check) + if elseif: + s = " else " + s + self.begin_block(s, "") + return self.Block(self, False, newline) + + def variable_defined(self, name): + for n in self.vars: + if n == name: + return True + return False + + def variable_def(self, ctype, *names): + for n in names: + # Strip away initialization + i = n.find("=") + if i != -1: + n = n[0:i] + self.vars.append(n.strip()) + # only add space for non-pointer types + if ctype[-1] == "*": + ctype = ctype[:-1].rstrip() + self.writeln("%s *%s;"%(ctype, ", *".join(names))) + else: + self.writeln("%s %s;"%(ctype, ", ".join(names))) + return self + + def function_helper(self): + if self.function_helper_writer != None: + writer = self.function_helper_writer.get_subwriter() + self.function_helper_writer.newline() + else: + writer = self.get_subwriter() + return writer + + def function(self, name, return_type, args, static = False): + self.has_error_check = False + self.function_helper_writer = self.get_subwriter() + if static: + self.write("static ") + self.write(return_type) + self.write(" %s(%s)"% (name, args)).newline() + self.begin_block() + self.function_variables_writer = self.get_subwriter() + self.function_variables = {} + return self.function_variables_writer + + def macro(self, name, args, define): + self.write("#define %s(%s) %s" % (name, args, define)).newline() + + def ifdef(self, name): + indentation = self.indentation + self.indentation = 0; + self.write("#ifdef %s" % (name)).newline() + self.indentation = indentation + + def ifdef_else(self, name): + indentation = self.indentation + self.indentation = 0; + self.write("#else /* %s */" % (name)).newline() + self.indentation = indentation + + def endif(self, name): + indentation = self.indentation + self.indentation = 0; + self.write("#endif /* %s */" % (name)).newline() + self.indentation = indentation + + def add_function_variable(self, ctype, name): + if name in self.function_variables: + assert(self.function_variables[name] == ctype) + else: + self.function_variables[name] = ctype + self.function_variables_writer.variable_def(ctype, name) + + def pop_index(self): + index = self.indexes[self.current_index] + self.current_index = self.current_index + 1 + self.add_function_variable(self.index_type, index) + return index + + def push_index(self): + assert self.current_index > 0 + self.current_index = self.current_index - 1 + + class Index: + def __init__(self, writer, val): + self.writer = writer + self.val = val + + def __enter__(self): + return self.val + + def __exit__(self, exc_type, exc_value, traceback): + self.writer.push_index() + + def index(self, no_block = False): + if no_block: + return self.no_block(None) + val = self.pop_index() + return self.Index(self, val) |