from __future__ import with_statement
from srcgen.base import BaseModule, BaseE, R
from contextlib import contextmanager
class CModule(BaseModule):
def comment(self, *lines, **kwargs):
box = kwargs.pop("box", False)
sep = kwargs.pop("sep", False)
if sep and box:
self._append("")
self._append("/* " + "*" * (self._line_width-2))
elif sep:
self._append("/*")
elif box:
self._append("/* " + "*" * (self._line_width-2))
self._curr.extend("/* %s" % (l.replace("*/", "* /"),) for l in "\n".join(lines).splitlines())
if sep and box:
self._append("*" * (self._line_width - 2) + " */")
self._append("")
elif sep:
self._append("*/")
elif box:
self._append("*" * (self._line_width - 2) + " */")
else:
self._curr[-1] += " */"
#
# Statements
#
def stmt(self, text, *args, **kwargs):
text = str(text)
semicolon = kwargs.pop("semicolon", True)
if kwargs:
raise TypeError("Invalid keyword argument %r" % (kwargs.keys(),))
if semicolon and text.strip()[0] != "#" and text[-1] not in ";:,{":
text += ";"
self._append(text.format(*args) if args else text)
def break_(self):
self.stmt("break")
def continue_(self):
self.stmt("continue")
def return_(self, expr, *args):
self.stmt("return %s" % (expr,), *args)
def goto(self, name):
self.stmt("goto %s" % (name,))
def label(self, name):
self.stmt("%s:" % (name,))
def include(self, filename):
filename = str(filename)
if filename.startswith("<"):
self.stmt("#include %s" % (filename,))
else:
self.stmt('#include "%s"' % (filename,))
def define(self, name, value = None):
if value:
value = value.replace("\n", "\\\n")
self.stmt("#define %s %s" % (name, value))
else:
self.stmt("#define %s" % (name,))
#
# Suites
#
@contextmanager
def suite(self, headline, *args, **kwargs):
headline = str(headline)
terminator = kwargs.pop("terminator", None)
if kwargs:
raise TypeError("Invalid keyword argument %r" % (kwargs.keys(),))
if headline[-1] not in "{:":
headline += " {"
self._append(headline.format(*args) if args else headline)
prev = self._curr
self._curr = []
prev.append(self._curr)
yield
self._curr = prev
if terminator is None:
self._append("}")
else:
if terminator:
self._append(terminator)
def if_(self, cond, *args):
return self.suite("if (%s)" % (cond,), *args)
def elif_(self, cond, *args):
return self.suite("else if (%s)" % (cond,), *args)
def else_(self):
return self.suite("else")
def for_(self, init, cond, next):
return self.suite("for (%s; %s; %s)" % (init, cond, next))
def while_(self, cond, *args):
return self.suite("while %s:" % (cond,), *args)
def do_while(self, cond, *args):
return self.suite("do", terminator = "} while(%s);" % (cond,), *args)
def switch(self, cond, *args):
return self.suite("switch (%s)" % (cond,), *args)
def case(self, val, *args):
return self.suite("case %s:" % (val,), terminator = "", *args)
def default(self):
return self.suite("default:", terminator = "")
@contextmanager
def func(self, type, name, *args):
with self.suite("%s %s(%s)" % (type, name, ", ".join(str(a) for a in args))): yield
self.sep()
@contextmanager
def struct(self, name, varname = None):
with self.suite("struct %s" % (name,), terminator = "} %s;" % (varname,) if varname else "};"): yield
self.sep()
@contextmanager
def union(self, name, varname = None):
with self.suite("union %s" % (name,), terminator = "} %s;" % (varname,) if varname else "};"): yield
self.sep()
@contextmanager
def enum(self, name, varname = None):
with self.suite("enum %s" % (name,), terminator = "} %s;" % (varname,) if varname else "};"):
yield
if self._curr[-1].endswith(","):
self._curr[-1] = self._curr[-1][:-1]
self.sep()
def enum_member(self, name, value = None):
self._append("%s = %s," % (name, value) if value is not None else "%s," % (name,))
@contextmanager
def typedef(self, type, name):
self.stmt("typedef %s %s" % (type, name))
@contextmanager
def typedef_struct(self, name):
with self.suite("typedef struct _%s" % (name,), terminator = "} %s;" % (name,)): yield
self.sep()
@contextmanager
def typedef_union(self, name):
with self.suite("typedef union _%s" % (name,), terminator = "} %s;" % (name,)): yield
self.sep()
@contextmanager
def typedef_enum(self, name):
with self.suite("typedef enum _%s" % (name,), terminator = "} %s;" % (name,)): yield
self.sep()
# preprocessor stuff
@contextmanager
def _if_suite(self, headline, merge_endif):
if merge_endif and self._curr and self._curr[-1].startswith("#endif"):
self._curr.pop(-1)
self._append(headline)
prev = self._curr
self._curr = []
prev.append(self._curr)
yield
self._curr = prev
self.stmt("#endif")
def IF(self, cond):
return self._if_suite("#if %s" % (cond,), False)
def ELIF(self, cond):
return self._if_suite("#elif %s" % (cond,), True)
def ELSE(self, cond):
return self._if_suite("#else %s" % (cond,), True)
def IFDEF(self, name):
return self._if_suite("#ifdef %s" % (name,), False)
def IFNDEF(self, name):
return self._if_suite("#ifndef %s" % (name,), False)
class HModule(CModule):
def __init__(self, guard_name):
CModule.__init__(self)
self._guard_name = guard_name
def render(self):
text = CModule.render(self)
text = "#ifndef %s\n#define %s\n\n" % (self._guard_name, self._guard_name) + text
text += "\n#endif /* %s */\n" % (self._guard_name,)
return text
[docs]def render_literal(obj):
"""
Render obj as a literal expression in C.
"""
if isinstance(obj, str):
return '"%s"' % obj
else:
return repr(obj)
class E(BaseE):
def __call__(self, *args):
return E("%r(%s)" % (self, ", ".join(render_literal(a) for a in args)))