summaryrefslogtreecommitdiffstats
path: root/scripts/qapi
diff options
context:
space:
mode:
authorMarc-André Lureau2018-07-03 17:56:40 +0200
committerMarkus Armbruster2018-07-03 18:38:53 +0200
commitded9fc28b5a07213f3e5e8ac7ea0494b85813de1 (patch)
treeab324b1d74043c2481ffb5a7b3b3fb896d03c06e /scripts/qapi
parentqapi: mcgen() shouldn't indent # lines (diff)
downloadqemu-ded9fc28b5a07213f3e5e8ac7ea0494b85813de1.tar.gz
qemu-ded9fc28b5a07213f3e5e8ac7ea0494b85813de1.tar.xz
qemu-ded9fc28b5a07213f3e5e8ac7ea0494b85813de1.zip
qapi: add #if/#endif helpers
Add helpers to wrap generated code with #if/#endif lines. A later patch wants to use QAPIGen for generating C snippets rather than full C files with copyright headers etc. Splice in class QAPIGenCCode between QAPIGen and QAPIGenC. Add a 'with' statement context manager that will be used to wrap generator visitor methods. The manager will check if code was generated before adding #if/#endif lines on QAPIGenCSnippet objects. Used in the following patches. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-Id: <20180703155648.11933-7-marcandre.lureau@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
Diffstat (limited to 'scripts/qapi')
-rw-r--r--scripts/qapi/common.py98
1 files changed, 94 insertions, 4 deletions
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 1b56065a80..9230a2a3e8 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -12,6 +12,7 @@
# See the COPYING file in the top-level directory.
from __future__ import print_function
+from contextlib import contextmanager
import errno
import os
import re
@@ -1974,6 +1975,40 @@ def guardend(name):
name=guardname(name))
+def gen_if(ifcond):
+ ret = ''
+ for ifc in ifcond:
+ ret += mcgen('''
+#if %(cond)s
+''', cond=ifc)
+ return ret
+
+
+def gen_endif(ifcond):
+ ret = ''
+ for ifc in reversed(ifcond):
+ ret += mcgen('''
+#endif /* %(cond)s */
+''', cond=ifc)
+ return ret
+
+
+def _wrap_ifcond(ifcond, before, after):
+ if before == after:
+ return after # suppress empty #if ... #endif
+
+ assert after.startswith(before)
+ out = before
+ added = after[len(before):]
+ if added[0] == '\n':
+ out += '\n'
+ added = added[1:]
+ out += gen_if(ifcond)
+ out += added
+ out += gen_endif(ifcond)
+ return out
+
+
def gen_enum_lookup(name, values, prefix=None):
ret = mcgen('''
@@ -2071,6 +2106,10 @@ class QAPIGen(object):
def add(self, text):
self._body += text
+ def get_content(self, fname=None):
+ return (self._top(fname) + self._preamble + self._body
+ + self._bottom(fname))
+
def _top(self, fname):
return ''
@@ -2091,8 +2130,7 @@ class QAPIGen(object):
f = open(fd, 'r+', encoding='utf-8')
else:
f = os.fdopen(fd, 'r+')
- text = (self._top(fname) + self._preamble + self._body
- + self._bottom(fname))
+ text = self.get_content(fname)
oldtext = f.read(len(text) + 1)
if text != oldtext:
f.seek(0)
@@ -2101,10 +2139,62 @@ class QAPIGen(object):
f.close()
-class QAPIGenC(QAPIGen):
+@contextmanager
+def ifcontext(ifcond, *args):
+ """A 'with' statement context manager to wrap with start_if()/end_if()
- def __init__(self, blurb, pydoc):
+ *args: any number of QAPIGenCCode
+
+ Example::
+
+ with ifcontext(ifcond, self._genh, self._genc):
+ modify self._genh and self._genc ...
+
+ Is equivalent to calling::
+
+ self._genh.start_if(ifcond)
+ self._genc.start_if(ifcond)
+ modify self._genh and self._genc ...
+ self._genh.end_if()
+ self._genc.end_if()
+ """
+ for arg in args:
+ arg.start_if(ifcond)
+ yield
+ for arg in args:
+ arg.end_if()
+
+
+class QAPIGenCCode(QAPIGen):
+
+ def __init__(self):
QAPIGen.__init__(self)
+ self._start_if = None
+
+ def start_if(self, ifcond):
+ assert self._start_if is None
+ self._start_if = (ifcond, self._body, self._preamble)
+
+ def end_if(self):
+ assert self._start_if
+ self._wrap_ifcond()
+ self._start_if = None
+
+ def _wrap_ifcond(self):
+ self._body = _wrap_ifcond(self._start_if[0],
+ self._start_if[1], self._body)
+ self._preamble = _wrap_ifcond(self._start_if[0],
+ self._start_if[2], self._preamble)
+
+ def get_content(self, fname=None):
+ assert self._start_if is None
+ return QAPIGen.get_content(self, fname)
+
+
+class QAPIGenC(QAPIGenCCode):
+
+ def __init__(self, blurb, pydoc):
+ QAPIGenCCode.__init__(self)
self._blurb = blurb
self._copyright = '\n * '.join(re.findall(r'^Copyright .*', pydoc,
re.MULTILINE))