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