OLD | NEW |
| (Empty) |
1 #! /usr/bin/python | |
2 # -*- coding: utf-8 -*- | |
3 # | |
4 # Copyright (C) 2011-2014, International Business Machines | |
5 # Corporation and others. All Rights Reserved. | |
6 # | |
7 # file name: dependencies.py | |
8 # | |
9 # created on: 2011may26 | |
10 | |
11 """Reader module for dependency data for the ICU dependency tester. | |
12 | |
13 Reads dependencies.txt and makes the data available. | |
14 | |
15 Attributes: | |
16 files: Set of "library/filename.o" files mentioned in the dependencies file. | |
17 items: Map from library or group names to item maps. | |
18 Each item has a "type" ("library" or "group" or "system_symbols"). | |
19 A library or group item can have an optional set of "files" (as in the files
attribute). | |
20 Each item can have an optional set of "deps" (libraries & groups). | |
21 A group item also has a "library" name unless it is a group of system symbol
s. | |
22 The one "system_symbols" item and its groups have sets of "system_symbols" | |
23 with standard-library system symbol names. | |
24 libraries: Set of library names mentioned in the dependencies file. | |
25 file_to_item: Map from a symbol (ushoe.o) to library or group (shoesize) | |
26 """ | |
27 __author__ = "Markus W. Scherer" | |
28 | |
29 # TODO: Support binary items. | |
30 # .txt syntax: binary: tools/genrb | |
31 # item contents: {"type": "binary"} with optional files & deps | |
32 # A binary must not be used as a dependency for anything else. | |
33 | |
34 import sys | |
35 | |
36 files = set() | |
37 items = {} | |
38 libraries = set() | |
39 file_to_item = {} | |
40 | |
41 _line_number = 0 | |
42 _groups_to_be_defined = set() | |
43 | |
44 def _CheckLibraryName(name): | |
45 global _line_number | |
46 if not name: | |
47 sys.exit("Error:%d: \"library: \" without name" % _line_number) | |
48 if name.endswith(".o"): | |
49 sys.exit("Error:%d: invalid library name %s" % (_line_number, name)) | |
50 | |
51 def _CheckGroupName(name): | |
52 global _line_number | |
53 if not name: | |
54 sys.exit("Error:%d: \"group: \" without name" % _line_number) | |
55 if "/" in name or name.endswith(".o"): | |
56 sys.exit("Error:%d: invalid group name %s" % (_line_number, name)) | |
57 | |
58 def _CheckFileName(name): | |
59 global _line_number | |
60 if "/" in name or not name.endswith(".o"): | |
61 sys.exit("Error:%d: invalid file name %s" % (_line_number, name)) | |
62 | |
63 def _RemoveComment(line): | |
64 global _line_number | |
65 _line_number = _line_number + 1 | |
66 index = line.find("#") # Remove trailing comment. | |
67 if index >= 0: line = line[:index] | |
68 return line.rstrip() # Remove trailing newlines etc. | |
69 | |
70 def _ReadLine(f): | |
71 while True: | |
72 line = _RemoveComment(f.next()) | |
73 if line: return line | |
74 | |
75 def _ReadFiles(deps_file, item, library_name): | |
76 global files | |
77 item_files = item.get("files") | |
78 while True: | |
79 line = _ReadLine(deps_file) | |
80 if not line: continue | |
81 if not line.startswith(" "): return line | |
82 if item_files == None: item_files = item["files"] = set() | |
83 for file_name in line.split(): | |
84 _CheckFileName(file_name) | |
85 file_name = library_name + "/" + file_name | |
86 if file_name in files: | |
87 sys.exit("Error:%d: file %s listed in multiple groups" % (_line_number,
file_name)) | |
88 files.add(file_name) | |
89 item_files.add(file_name) | |
90 file_to_item[file_name] = item["name"] | |
91 | |
92 def _IsLibrary(item): return item and item["type"] == "library" | |
93 | |
94 def _IsLibraryGroup(item): return item and "library" in item | |
95 | |
96 def _ReadDeps(deps_file, item, library_name): | |
97 global items, _line_number, _groups_to_be_defined | |
98 item_deps = item.get("deps") | |
99 while True: | |
100 line = _ReadLine(deps_file) | |
101 if not line: continue | |
102 if not line.startswith(" "): return line | |
103 if item_deps == None: item_deps = item["deps"] = set() | |
104 for dep in line.split(): | |
105 _CheckGroupName(dep) | |
106 dep_item = items.get(dep) | |
107 if item["type"] == "system_symbols" and (_IsLibraryGroup(dep_item) or _IsL
ibrary(dep_item)): | |
108 sys.exit(("Error:%d: system_symbols depend on previously defined " + | |
109 "library or library group %s") % (_line_number, dep)) | |
110 if dep_item == None: | |
111 # Add this dependency as a new group. | |
112 items[dep] = {"type": "group"} | |
113 if library_name: items[dep]["library"] = library_name | |
114 _groups_to_be_defined.add(dep) | |
115 item_deps.add(dep) | |
116 | |
117 def _AddSystemSymbol(item, symbol): | |
118 exports = item.get("system_symbols") | |
119 if exports == None: exports = item["system_symbols"] = set() | |
120 exports.add(symbol) | |
121 | |
122 def _ReadSystemSymbols(deps_file, item): | |
123 global _line_number | |
124 while True: | |
125 line = _ReadLine(deps_file) | |
126 if not line: continue | |
127 if not line.startswith(" "): return line | |
128 line = line.lstrip() | |
129 if '"' in line: | |
130 # One double-quote-enclosed symbol on the line, allows spaces in a symbol
name. | |
131 symbol = line[1:-1] | |
132 if line.startswith('"') and line.endswith('"') and '"' not in symbol: | |
133 _AddSystemSymbol(item, symbol) | |
134 else: | |
135 sys.exit("Error:%d: invalid quoted symbol name %s" % (_line_number, line
)) | |
136 else: | |
137 # One or more space-separate symbols. | |
138 for symbol in line.split(): _AddSystemSymbol(item, symbol) | |
139 | |
140 def Load(): | |
141 """Reads "dependencies.txt" and populates the module attributes.""" | |
142 global items, libraries, _line_number, _groups_to_be_defined | |
143 deps_file = open("dependencies.txt") | |
144 try: | |
145 line = None | |
146 current_type = None | |
147 while True: | |
148 while not line: line = _RemoveComment(deps_file.next()) | |
149 | |
150 if line.startswith("library: "): | |
151 current_type = "library" | |
152 name = line[9:].lstrip() | |
153 _CheckLibraryName(name) | |
154 if name in items: | |
155 sys.exit("Error:%d: library definition using duplicate name %s" % (_li
ne_number, name)) | |
156 libraries.add(name) | |
157 item = items[name] = {"type": "library", "name": name} | |
158 line = _ReadFiles(deps_file, item, name) | |
159 elif line.startswith("group: "): | |
160 current_type = "group" | |
161 name = line[7:].lstrip() | |
162 _CheckGroupName(name) | |
163 if name not in items: | |
164 sys.exit("Error:%d: group %s defined before mentioned as a dependency"
% | |
165 (_line_number, name)) | |
166 if name not in _groups_to_be_defined: | |
167 sys.exit("Error:%d: group definition using duplicate name %s" % (_line
_number, name)) | |
168 _groups_to_be_defined.remove(name) | |
169 item = items[name] | |
170 item["name"] = name | |
171 library_name = item.get("library") | |
172 if library_name: | |
173 line = _ReadFiles(deps_file, item, library_name) | |
174 else: | |
175 line = _ReadSystemSymbols(deps_file, item) | |
176 elif line == " deps": | |
177 if current_type == "library": | |
178 line = _ReadDeps(deps_file, items[name], name) | |
179 elif current_type == "group": | |
180 item = items[name] | |
181 line = _ReadDeps(deps_file, item, item.get("library")) | |
182 elif current_type == "system_symbols": | |
183 item = items[current_type] | |
184 line = _ReadDeps(deps_file, item, None) | |
185 else: | |
186 sys.exit("Error:%d: deps before any library or group" % _line_number) | |
187 elif line == "system_symbols:": | |
188 current_type = "system_symbols" | |
189 if current_type in items: | |
190 sys.exit("Error:%d: duplicate entry for system_symbols" % _line_number
) | |
191 item = items[current_type] = {"type": current_type, "name": current_type
} | |
192 line = _ReadSystemSymbols(deps_file, item) | |
193 else: | |
194 sys.exit("Syntax error:%d: %s" % (_line_number, line)) | |
195 except StopIteration: | |
196 pass | |
197 if _groups_to_be_defined: | |
198 sys.exit("Error: some groups mentioned in dependencies are undefined: %s" %
_groups_to_be_defined) | |
OLD | NEW |