2 # -*- coding: utf-8 -*-
4 # Copyright (C) 2011-2014, International Business Machines
5 # Corporation and others. All Rights Reserved.
7 # file name: dependencies.py
9 # created on: 2011may26
11 """Reader module for dependency data for the ICU dependency tester.
13 Reads dependencies.txt and makes the data available.
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 symbols.
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)
27 __author__
= "Markus W. Scherer"
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.
42 _groups_to_be_defined
= set()
44 def _CheckLibraryName(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
))
51 def _CheckGroupName(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
))
58 def _CheckFileName(name
):
60 if "/" in name
or not name
.endswith(".o"):
61 sys
.exit("Error:%d: invalid file name %s" % (_line_number
, name
))
63 def _RemoveComment(line
):
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.
72 line
= _RemoveComment(f
.next())
75 def _ReadFiles(deps_file
, item
, library_name
):
77 item_files
= item
.get("files")
79 line
= _ReadLine(deps_file
)
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
))
89 item_files
.add(file_name
)
90 file_to_item
[file_name
] = item
["name"]
92 def _IsLibrary(item
): return item
and item
["type"] == "library"
94 def _IsLibraryGroup(item
): return item
and "library" in item
96 def _ReadDeps(deps_file
, item
, library_name
):
97 global items
, _line_number
, _groups_to_be_defined
98 item_deps
= item
.get("deps")
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():
106 dep_item
= items
.get(dep
)
107 if item
["type"] == "system_symbols" and (_IsLibraryGroup(dep_item
) or _IsLibrary(dep_item
)):
108 sys
.exit(("Error:%d: system_symbols depend on previously defined " +
109 "library or library group %s") % (_line_number
, dep
))
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
)
117 def _AddSystemSymbol(item
, symbol
):
118 exports
= item
.get("system_symbols")
119 if exports
== None: exports
= item
["system_symbols"] = set()
122 def _ReadSystemSymbols(deps_file
, item
):
125 line
= _ReadLine(deps_file
)
126 if not line
: continue
127 if not line
.startswith(" "): return line
130 # One double-quote-enclosed symbol on the line, allows spaces in a symbol name.
132 if line
.startswith('"') and line
.endswith('"') and '"' not in symbol
:
133 _AddSystemSymbol(item
, symbol
)
135 sys
.exit("Error:%d: invalid quoted symbol name %s" % (_line_number
, line
))
137 # One or more space-separate symbols.
138 for symbol
in line
.split(): _AddSystemSymbol(item
, symbol
)
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")
148 while not line
: line
= _RemoveComment(deps_file
.next())
150 if line
.startswith("library: "):
151 current_type
= "library"
152 name
= line
[9:].lstrip()
153 _CheckLibraryName(name
)
155 sys
.exit("Error:%d: library definition using duplicate name %s" % (_line_number
, 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
)
171 library_name
= item
.get("library")
173 line
= _ReadFiles(deps_file
, item
, library_name
)
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":
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)
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
)
194 sys
.exit("Syntax error:%d: %s" % (_line_number
, line
))
195 except StopIteration:
197 if _groups_to_be_defined
:
198 sys
.exit("Error: some groups mentioned in dependencies are undefined: %s" % _groups_to_be_defined
)