from __future__ import with_statement from cStringIO 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 def set_option(self, opt, value = True): self.options[opt] = value def has_option(self, opt): return self.options.has_key(opt) def set_is_generated(self, kind, name): if not self.generated.has_key(kind): v = {} self.generated[kind] = v else: v = self.generated[kind] v[name] = 1 def is_generated(self, kind, name): if not self.generated.has_key(kind): return False v = self.generated[kind] return v.has_key(name) def getvalue(self): strs = map(lambda writer: writer.getvalue(), 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.generated = self.generated writer.options = self.options writer.public_prefix = self.public_prefix return writer; def write(self, s): # Ensure its a string s = str(s) if len(s) == 0: return if self.at_line_start: for i in range(self.indentation): self.out.write(" ") self.at_line_start = False self.out.write(s) return self def newline(self): self.out.write("\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.indenttation = 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 add_function_variable(self, ctype, name): if self.function_variables.has_key(name): 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("uint32_t", index) return index def push_index(self): 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)