qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Markus Armbruster <armbru@redhat.com>
To: qemu-devel@nongnu.org
Cc: marcandre.lureau@redhat.com, mdroth@linux.vnet.ibm.com
Subject: [PATCH 03/25] qapi: New QAPISourceInfo, replacing dict
Date: Tue, 24 Sep 2019 15:28:08 +0200	[thread overview]
Message-ID: <20190924132830.15835-4-armbru@redhat.com> (raw)
In-Reply-To: <20190924132830.15835-1-armbru@redhat.com>

We track source locations with a dict of the form

    {'file': FNAME, 'line': LINENO, parent': PARENT}

where PARENT is None for the main file, and the include directive's
source location for included files.

This is servicable enough, but the next commit will add information,
and that's going to come out cleaner if we turn this into a class.  So
do that.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 scripts/qapi/common.py | 69 +++++++++++++++++++++++++-----------------
 1 file changed, 41 insertions(+), 28 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index bfb3e8a493..5843f3eeb2 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -13,6 +13,7 @@
 
 from __future__ import print_function
 from contextlib import contextmanager
+import copy
 import errno
 import os
 import re
@@ -53,34 +54,50 @@ struct_types = {}
 union_types = {}
 all_names = {}
 
+
 #
 # Parsing the schema into expressions
 #
 
+class QAPISourceInfo(object):
+    def __init__(self, fname, line, parent):
+        self.fname = fname
+        self.line = line
+        self.parent = parent
 
-def error_path(parent):
-    res = ''
-    while parent:
-        res = ('In file included from %s:%d:\n' % (parent['file'],
-                                                   parent['line'])) + res
-        parent = parent['parent']
-    return res
+    def next_line(self):
+        info = copy.copy(self)
+        info.line += 1
+        return info
+
+    def loc(self):
+        return '%s:%d' % (self.fname, self.line)
+
+    def include_path(self):
+        ret = ''
+        parent = self.parent
+        while parent:
+            ret = 'In file included from %s:\n' % parent.loc() + ret
+            parent = parent.parent
+        return ret
+
+    def __str__(self):
+        return self.include_path() + self.loc()
 
 
 class QAPIError(Exception):
-    def __init__(self, fname, line, col, incl_info, msg):
+    def __init__(self, info, col, msg):
         Exception.__init__(self)
-        self.fname = fname
-        self.line = line
+        self.info = info
         self.col = col
-        self.info = incl_info
         self.msg = msg
 
     def __str__(self):
-        loc = '%s:%d' % (self.fname, self.line)
+        loc = str(self.info)
         if self.col is not None:
+            assert self.info.line is not None
             loc += ':%s' % self.col
-        return error_path(self.info) + '%s: %s' % (loc, self.msg)
+        return loc + ': ' + self.msg
 
 
 class QAPIParseError(QAPIError):
@@ -91,14 +108,12 @@ class QAPIParseError(QAPIError):
                 col = (col + 7) % 8 + 1
             else:
                 col += 1
-        QAPIError.__init__(self, parser.fname, parser.line, col,
-                           parser.incl_info, msg)
+        QAPIError.__init__(self, parser.info, col, msg)
 
 
 class QAPISemError(QAPIError):
     def __init__(self, info, msg):
-        QAPIError.__init__(self, info['file'], info['line'], None,
-                           info['parent'], msg)
+        QAPIError.__init__(self, info, None, msg)
 
 
 class QAPIDoc(object):
@@ -382,12 +397,11 @@ class QAPISchemaParser(object):
     def __init__(self, fp, previously_included=[], incl_info=None):
         self.fname = fp.name
         previously_included.append(os.path.abspath(fp.name))
-        self.incl_info = incl_info
         self.src = fp.read()
         if self.src == '' or self.src[-1] != '\n':
             self.src += '\n'
         self.cursor = 0
-        self.line = 1
+        self.info = QAPISourceInfo(self.fname, 1, incl_info)
         self.line_pos = 0
         self.exprs = []
         self.docs = []
@@ -395,8 +409,7 @@ class QAPISchemaParser(object):
         cur_doc = None
 
         while self.tok is not None:
-            info = {'file': self.fname, 'line': self.line,
-                    'parent': self.incl_info}
+            info = self.info
             if self.tok == '#':
                 self.reject_expr_doc(cur_doc)
                 cur_doc = self.get_doc(info)
@@ -456,9 +469,9 @@ class QAPISchemaParser(object):
         # catch inclusion cycle
         inf = info
         while inf:
-            if incl_abs_fname == os.path.abspath(inf['file']):
+            if incl_abs_fname == os.path.abspath(inf.fname):
                 raise QAPISemError(info, "Inclusion loop for %s" % include)
-            inf = inf['parent']
+            inf = inf.parent
 
         # skip multiple include of the same file
         if incl_abs_fname in previously_included:
@@ -552,7 +565,7 @@ class QAPISchemaParser(object):
                 if self.cursor == len(self.src):
                     self.tok = None
                     return
-                self.line += 1
+                self.info = self.info.next_line()
                 self.line_pos = self.cursor
             elif not self.tok.isspace():
                 # Show up to next structural, whitespace or quote
@@ -1172,7 +1185,7 @@ class QAPISchemaEntity(object):
     def check(self, schema):
         assert not self._checked
         if self.info:
-            self._module = os.path.relpath(self.info['file'],
+            self._module = os.path.relpath(self.info.fname,
                                            os.path.dirname(schema.fname))
         self._checked = True
 
@@ -1781,9 +1794,9 @@ class QAPISchema(object):
         include = expr['include']
         assert doc is None
         main_info = info
-        while main_info['parent']:
-            main_info = main_info['parent']
-        fname = os.path.relpath(include, os.path.dirname(main_info['file']))
+        while main_info.parent:
+            main_info = main_info.parent
+        fname = os.path.relpath(include, os.path.dirname(main_info.fname))
         self._def_entity(QAPISchemaInclude(fname, info))
 
     def _def_builtin_type(self, name, json_type, c_type):
-- 
2.21.0



  parent reply	other threads:[~2019-09-24 14:38 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-24 13:28 [PATCH 00/25] qapi: Pay back some frontend technical debt Markus Armbruster
2019-09-24 13:28 ` [PATCH 01/25] qapi: Tighten QAPISchemaFOO.check() assertions Markus Armbruster
2019-09-24 14:39   ` Eric Blake
2019-09-24 20:18     ` Markus Armbruster
2019-09-24 13:28 ` [PATCH 02/25] qapi: Rename .owner to .defined_in Markus Armbruster
2019-09-24 14:41   ` Eric Blake
2019-09-24 13:28 ` Markus Armbruster [this message]
2019-09-24 14:51   ` [PATCH 03/25] qapi: New QAPISourceInfo, replacing dict Eric Blake
2019-09-24 20:18     ` Markus Armbruster
2019-09-24 19:12   ` Eric Blake
2019-09-25  6:40     ` Markus Armbruster
2019-09-24 13:28 ` [PATCH 04/25] qapi: Prefix frontend errors with an "in definition" line Markus Armbruster
2019-09-24 14:58   ` Eric Blake
2019-09-24 13:28 ` [PATCH 05/25] qapi: Clean up member name case checking Markus Armbruster
2019-09-24 15:07   ` Eric Blake
2019-09-24 20:20     ` Markus Armbruster
2019-09-24 13:28 ` [PATCH 06/25] qapi: Change frontend error messages to start with lower case Markus Armbruster
2019-09-24 15:17   ` Eric Blake
2019-09-24 20:35     ` Markus Armbruster
2019-09-24 13:28 ` [PATCH 07/25] qapi: Improve reporting of member name clashes Markus Armbruster
2019-09-24 15:38   ` Eric Blake
2019-09-24 13:28 ` [PATCH 08/25] qapi: Reorder check_FOO() parameters for consistency Markus Armbruster
2019-09-24 15:41   ` Eric Blake
2019-09-24 13:28 ` [PATCH 09/25] qapi: Improve reporting of invalid name errors Markus Armbruster
2019-09-24 15:48   ` Eric Blake
2019-09-24 13:28 ` [PATCH 10/25] qapi: Use check_name_str() where it suffices Markus Armbruster
2019-09-24 15:50   ` Eric Blake
2019-09-24 13:28 ` [PATCH 11/25] qapi: Report invalid '*' prefix like any other invalid name Markus Armbruster
2019-09-24 15:52   ` Eric Blake
2019-09-24 13:28 ` [PATCH 12/25] qapi: Move check for reserved names out of add_name() Markus Armbruster
2019-09-24 15:56   ` Eric Blake
2019-09-24 13:28 ` [PATCH 13/25] qapi: Make check_type()'s array case a bit more obvious Markus Armbruster
2019-09-24 15:57   ` Eric Blake
2019-09-24 13:28 ` [PATCH 14/25] qapi: Plumb info to the QAPISchemaMember Markus Armbruster
2019-09-24 16:01   ` Eric Blake
2019-09-24 13:28 ` [PATCH 15/25] qapi: Inline check_name() into check_union() Markus Armbruster
2019-09-24 16:39   ` Eric Blake
2019-09-24 13:28 ` [PATCH 16/25] qapi: Move context-sensitive checking to the proper place Markus Armbruster
2019-09-24 17:49   ` Eric Blake
2019-09-24 20:41     ` Markus Armbruster
2019-09-24 13:28 ` [PATCH 17/25] qapi: Move context-free " Markus Armbruster
2019-09-24 17:59   ` Eric Blake
2019-09-24 13:28 ` [PATCH 18/25] qapi: Improve reporting of invalid 'if' errors Markus Armbruster
2019-09-24 18:01   ` Eric Blake
2019-09-24 13:28 ` [PATCH 19/25] qapi: Improve reporting of invalid flags Markus Armbruster
2019-09-24 18:07   ` Eric Blake
2019-09-24 20:43     ` Markus Armbruster
2019-09-25  6:13       ` Markus Armbruster
2019-09-24 13:28 ` [PATCH 20/25] qapi: Improve reporting of missing / unknown definition keys Markus Armbruster
2019-09-24 18:13   ` Eric Blake
2019-09-24 20:46     ` Markus Armbruster
2019-09-24 13:28 ` [PATCH 21/25] qapi: Avoid redundant definition references in error messages Markus Armbruster
2019-09-24 18:46   ` Eric Blake
2019-09-24 20:59     ` Markus Armbruster
2019-09-24 13:28 ` [PATCH 22/25] qapi: Eliminate check_keys(), rename check_known_keys() Markus Armbruster
2019-09-24 18:49   ` Eric Blake
2019-09-24 13:28 ` [PATCH 23/25] qapi: Improve reporting of missing documentation comment Markus Armbruster
2019-09-24 19:44   ` Eric Blake
2019-09-24 13:28 ` [PATCH 24/25] qapi: Improve reporting of redefinition Markus Armbruster
2019-09-24 19:53   ` Eric Blake
2019-09-24 13:28 ` [PATCH 25/25] qapi: Improve source file read error handling Markus Armbruster
2019-09-24 19:57   ` Eric Blake
2019-09-24 20:59     ` Markus Armbruster

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190924132830.15835-4-armbru@redhat.com \
    --to=armbru@redhat.com \
    --cc=marcandre.lureau@redhat.com \
    --cc=mdroth@linux.vnet.ibm.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).