From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:43347) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bhFbO-0001gv-N2 for qemu-devel@nongnu.org; Tue, 06 Sep 2016 08:35:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bhFbK-0002rm-OX for qemu-devel@nongnu.org; Tue, 06 Sep 2016 08:35:46 -0400 Received: from mx1.redhat.com ([209.132.183.28]:60244) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bhFbK-0002rS-B4 for qemu-devel@nongnu.org; Tue, 06 Sep 2016 08:35:42 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2B92B8553C for ; Tue, 6 Sep 2016 12:35:40 +0000 (UTC) From: Markus Armbruster References: <20160817165757.23486-1-marcandre.lureau@redhat.com> <20160817165757.23486-3-marcandre.lureau@redhat.com> Date: Tue, 06 Sep 2016 14:35:37 +0200 In-Reply-To: <20160817165757.23486-3-marcandre.lureau@redhat.com> (=?utf-8?Q?=22Marc-Andr=C3=A9?= Lureau"'s message of "Wed, 17 Aug 2016 20:57:39 +0400") Message-ID: <87fupd5hpi.fsf@dusky.pond.sub.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH v5 02/20] qapi.py: add a simple #ifdef conditional List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: =?utf-8?Q?Marc-Andr=C3=A9?= Lureau Cc: qemu-devel@nongnu.org Marc-Andr=C3=A9 Lureau writes: > Learn to parse #define files provided with -f option, and skip > undefined #ifdef blocks in the schema. > > This is a very simple pre-processing, without stacking support or > evaluation (it could be implemented if needed). > > Signed-off-by: Marc-Andr=C3=A9 Lureau > --- > scripts/qapi.py | 43 ++++++++++++++++++++++++++++++++++++++++--- Missing: update of docs/qapi-code-gen.txt. > 1 file changed, 40 insertions(+), 3 deletions(-) > > diff --git a/scripts/qapi.py b/scripts/qapi.py > index 21bc32f..d0b8a66 100644 > --- a/scripts/qapi.py > +++ b/scripts/qapi.py > @@ -76,6 +76,7 @@ struct_types =3D [] > union_types =3D [] > events =3D [] > all_names =3D {} > +defs =3D [] >=20=20 > # > # Parsing the schema into expressions > @@ -177,6 +178,7 @@ class QAPISchemaParser(object): > self.exprs.append(expr_elem) >=20=20 > def accept(self): > + ok =3D True > while True: > self.tok =3D self.src[self.cursor] > self.pos =3D self.cursor > @@ -184,7 +186,19 @@ class QAPISchemaParser(object): > self.val =3D None >=20=20 > if self.tok =3D=3D '#': > - self.cursor =3D self.src.find('\n', self.cursor) > + end =3D self.src.find('\n', self.cursor) > + line =3D self.src[self.cursor:end+1] > + self.cursor =3D end > + sline =3D line.split() > + if len(defs) and len(sline) >=3D 1 \ > + and sline[0] in ['ifdef', 'endif']: > + if sline[0] =3D=3D 'ifdef': > + ok =3D sline[1] in defs > + elif sline[0] =3D=3D 'endif': > + ok =3D True > + continue > + elif not ok: > + continue > elif self.tok in "{}:,[]": > return > elif self.tok =3D=3D "'": Oww, you're abusing comments! That's horrible :) Can we make this real syntax, like everything else, including 'include'? Unfortunately, the natural { 'ifdef': 'CONFIG_FOO' 'then': ... # ignored unless CONFIG_FOO 'else': ... # ignored if CONFIG_FOO (optional) } is awkward, because the ... have to be a single JSON value, but a QAPI schema isn't a single JSON value, it's a *sequence* of JSON values. A top-level stanza JSON-value1 JSON-value2 ... would become [ JSON-value1, JSON-value2, ... ] within a conditional. Blech. Could sacrifice the nesting and do { 'ifdef': 'CONFIG_FOO' } ... { 'endif' } Widens the gap between syntax and semantics. Editors can no longer easily jump over the conditional (e.g. Emacs forward-sexp). Nested conditionals becomes as confusing as in C. Not exactly elegant, either. Yet another option is to add 'ifdef' keys to the definitions themselves, i.e. { 'command': 'query-gic-capabilities', 'returns': ['GICCapability'], 'ifdef': 'TARGET_ARM' } > @@ -1707,15 +1721,36 @@ def gen_params(arg_type, boxed, extra): > # > # Common command line parsing > # > +def defile(filename): >>From The Collaborative International Dictionary of English v.0.48 [gcide]: Defile \De*file"\ (d[-e]*f[imac]l"), v. t. [OE. defoulen, -foilen, to tread down, OF. defouler; de- + fouler to trample (see Full, v. t.), and OE. defoulen to foul (influenced in form by the older verb defoilen). See File to defile, Foul, Defoul.] 1. To make foul or impure; to make filthy; to dirty; to befoul; to pollute. [1913 Webster] They that touch pitch will be defiled. --Shak. [1913 Webster] 2. To soil or sully; to tarnish, as reputation; to taint. [1913 Webster] He is . . . among the greatest prelates of this age, however his character may be defiled by . . . dirty hands. --Swift. [1913 Webster] 3. To injure in purity of character; to corrupt. [1913 Webster] Defile not yourselves with the idols of Egypt. --Ezek. xx. 7. [1913 Webster] 4. To corrupt the chastity of; to debauch; to violate; to rape. [1913 Webster] The husband murder'd and the wife defiled. --Prior. [1913 Webster] 5. To make ceremonially unclean; to pollute. [1913 Webster] That which dieth of itself, or is torn with beasts, he shall not eat to defile therewith. --Lev. xxii. 8. [1913 Webster] Fitting in a way; you're defiling the poor, innocent comment syntax ;) > + f =3D open(filename, 'r') > + while 1: while True: > + line =3D f.readline() > + if not line: > + break > + while line[-2:] =3D=3D '\\\n': > + nextline =3D f.readline() > + if not nextline: > + break > + line =3D line + nextline > + tmp =3D line.strip() > + if tmp[:1] !=3D '#': > + continue > + tmp =3D tmp[1:] > + words =3D tmp.split() > + if words[0] !=3D "define": > + continue > + defs.append(words[1]) > + f.close() This parses Yet Another Language. Worse, Yet Another Undocumented Language. Why not JSON? Hmm, peeking ahead to PATCH 04... aha! This is for reading config-host.h and config-target.h. So, this actually doesn't parse YAUL, it parses C. Sloppily, of course. I guess we could instead parse config-host.mak and config-target.mak sloppily. Not sure which idea is more disgusting :) Could we punt evaluating conditionals to the C compiler? Instead of emitting TEXT when CONFIG_FOO is defined, emit #ifdef CONFIG_FOO TEXT #endif >=20=20 >=20=20 > def parse_command_line(extra_options=3D"", extra_long_options=3D[]): >=20=20 > try: > opts, args =3D getopt.gnu_getopt(sys.argv[1:], > - "chp:o:" + extra_options, > + "chp:o:f:" + extra_options, > ["source", "header", "prefix=3D", > - "output-dir=3D"] + extra_long_op= tions) > + "output-dir=3D", "--defile=3D"] + https://docs.python.org/3/library/getopt.html on the third argument: "The leading '--' characters should not be included in the option name." > + extra_long_options) > except getopt.GetoptError as err: > print >>sys.stderr, "%s: %s" % (sys.argv[0], str(err)) > sys.exit(1) > @@ -1742,6 +1777,8 @@ def parse_command_line(extra_options=3D"", extra_lo= ng_options=3D[]): > do_c =3D True > elif o in ("-h", "--header"): > do_h =3D True > + elif o in ("-f", "--defile"): > + defile(a) > else: > extra_opts.append(oa)