• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (C) 2009 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""A module for reading and parsing event-log-tags files."""
16
17import re
18import sys
19
20class Tag(object):
21  __slots__ = ["tagnum", "tagname", "description", "filename", "linenum"]
22
23  def __init__(self, tagnum, tagname, description, filename, linenum):
24    self.tagnum = tagnum
25    self.tagname = tagname
26    self.description = description
27    self.filename = filename
28    self.linenum = linenum
29
30
31class TagFile(object):
32  """Read an input event-log-tags file."""
33  def AddError(self, msg, linenum=None):
34    if linenum is None:
35      linenum = self.linenum
36    self.errors.append((self.filename, linenum, msg))
37
38  def AddWarning(self, msg, linenum=None):
39    if linenum is None:
40      linenum = self.linenum
41    self.warnings.append((self.filename, linenum, msg))
42
43  def __init__(self, filename, file_object=None):
44    """'filename' is the name of the file (included in any error
45    messages).  If 'file_object' is None, 'filename' will be opened
46    for reading."""
47    self.errors = []
48    self.warnings = []
49    self.tags = []
50    self.options = {}
51
52    self.filename = filename
53    self.linenum = 0
54
55    if file_object is None:
56      try:
57        file_object = open(filename, "rb")
58      except (IOError, OSError), e:
59        self.AddError(str(e))
60        return
61
62    try:
63      for self.linenum, line in enumerate(file_object):
64        self.linenum += 1
65
66        line = line.strip()
67        if not line or line[0] == '#': continue
68        parts = re.split(r"\s+", line, 2)
69
70        if len(parts) < 2:
71          self.AddError("failed to parse \"%s\"" % (line,))
72          continue
73
74        if parts[0] == "option":
75          self.options[parts[1]] = parts[2:]
76          continue
77
78        if parts[0] == "?":
79          tag = None
80        else:
81          try:
82            tag = int(parts[0])
83          except ValueError:
84            self.AddError("\"%s\" isn't an integer tag or '?'" % (parts[0],))
85            continue
86
87        tagname = parts[1]
88        if len(parts) == 3:
89          description = parts[2]
90        else:
91          description = None
92
93        self.tags.append(Tag(tag, tagname, description,
94                             self.filename, self.linenum))
95    except (IOError, OSError), e:
96      self.AddError(str(e))
97
98
99def BooleanFromString(s):
100  """Interpret 's' as a boolean and return its value.  Raise
101  ValueError if it's not something we can interpret as true or
102  false."""
103  s = s.lower()
104  if s in ("true", "t", "1", "on", "yes", "y"):
105    return True
106  if s in ("false", "f", "0", "off", "no", "n"):
107    return False
108  raise ValueError("'%s' not a valid boolean" % (s,))
109
110
111def WriteOutput(output_file, data):
112  """Write 'data' to the given output filename (which may be None to
113  indicate stdout).  Emit an error message and die on any failure.
114  'data' may be a string or a StringIO object."""
115  if not isinstance(data, str):
116    data = data.getvalue()
117  try:
118    if output_file is None:
119      out = sys.stdout
120      output_file = "<stdout>"
121    else:
122      out = open(output_file, "wb")
123    out.write(data)
124    out.close()
125  except (IOError, OSError), e:
126    print >> sys.stderr, "failed to write %s: %s" % (output_file, e)
127    sys.exit(1)
128