diff options
-rw-r--r-- | scripts/qapi/common.py | 69 |
1 files 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 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 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 __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): |