OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 '''Item formatters for RC headers. | 6 '''Item formatters for RC headers. |
7 ''' | 7 ''' |
8 | 8 |
9 from grit import exception | 9 from grit import exception |
10 from grit import util | 10 from grit import util |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 with item: | 72 with item: |
73 for tid in item.GetTextualIds(): | 73 for tid in item.GetTextualIds(): |
74 if tid in tids and tid not in seen: | 74 if tid in tids and tid not in seen: |
75 seen.add(tid) | 75 seen.add(tid) |
76 yield rc_header_format.format(textual_id=tid,numeric_id=tids[tid]) | 76 yield rc_header_format.format(textual_id=tid,numeric_id=tids[tid]) |
77 | 77 |
78 | 78 |
79 _cached_ids = {} | 79 _cached_ids = {} |
80 | 80 |
81 | 81 |
| 82 _predetermined_tids = {} |
| 83 |
| 84 |
| 85 def SetPredeterminedIdsFile(predetermined_ids_file): |
| 86 global _predetermined_tids |
| 87 if predetermined_ids_file: |
| 88 _predetermined_tids = _ReadIdsFromFile(predetermined_ids_file) |
| 89 else: |
| 90 _predetermined_tids = {} |
| 91 |
| 92 |
| 93 def _ReadIdsFromFile(path): |
| 94 with open(path, "r") as f: |
| 95 content = f.readlines() |
| 96 tids = {} # Maps textual id to numeric id |
| 97 for line in content: |
| 98 tid, id = line.split() |
| 99 tids[tid] = int(id) |
| 100 return tids |
| 101 |
| 102 |
82 def GetIds(root): | 103 def GetIds(root): |
83 '''Return a dictionary mapping textual ids to numeric ids for the given tree. | 104 '''Return a dictionary mapping textual ids to numeric ids for the given tree. |
84 | 105 |
85 Args: | 106 Args: |
86 root: A GritNode. | 107 root: A GritNode. |
87 ''' | 108 ''' |
| 109 global _cached_ids |
| 110 global _predetermined_tids |
88 # TODO(benrg): Since other formatters use this, it might make sense to move it | 111 # TODO(benrg): Since other formatters use this, it might make sense to move it |
89 # and _ComputeIds to GritNode and store the cached ids as an attribute. On the | 112 # and _ComputeIds to GritNode and store the cached ids as an attribute. On the |
90 # other hand, GritNode has too much random stuff already. | 113 # other hand, GritNode has too much random stuff already. |
91 if root not in _cached_ids: | 114 if root not in _cached_ids: |
92 _cached_ids[root] = _ComputeIds(root) | 115 _cached_ids[root] = _ComputeIds(root, _predetermined_tids) |
93 return _cached_ids[root] | 116 return _cached_ids[root] |
94 | 117 |
95 | 118 |
96 def _ComputeIds(root): | 119 def _ComputeIds(root, predetermined_tids): |
97 from grit.node import empty, include, message, misc, structure | 120 from grit.node import empty, include, message, misc, structure |
98 | 121 |
99 ids = {} # Maps numeric id to textual id | 122 ids = {} # Maps numeric id to textual id |
100 tids = {} # Maps textual id to numeric id | 123 tids = {} # Maps textual id to numeric id |
101 id_reasons = {} # Maps numeric id to text id and a human-readable explanation | 124 id_reasons = {} # Maps numeric id to text id and a human-readable explanation |
102 group = None | 125 group = None |
103 last_id = None | 126 last_id = None |
| 127 predetermined_ids = {value: key |
| 128 for key, value in predetermined_tids.iteritems()} |
104 | 129 |
105 for item in root: | 130 for item in root: |
106 if isinstance(item, empty.GroupingNode): | 131 if isinstance(item, empty.GroupingNode): |
107 # Note: this won't work if any GroupingNode can be contained inside | 132 # Note: this won't work if any GroupingNode can be contained inside |
108 # another. | 133 # another. |
109 group = item | 134 group = item |
110 last_id = None | 135 last_id = None |
111 continue | 136 continue |
112 | 137 |
113 assert not item.GetTextualIds() or isinstance(item, | 138 assert not item.GetTextualIds() or isinstance(item, |
114 (include.IncludeNode, message.MessageNode, | 139 (include.IncludeNode, message.MessageNode, |
115 misc.IdentifierNode, structure.StructureNode)) | 140 misc.IdentifierNode, structure.StructureNode)) |
116 | 141 |
117 # Resources that use the RES protocol don't need | 142 # Resources that use the RES protocol don't need |
118 # any numerical ids generated, so we skip them altogether. | 143 # any numerical ids generated, so we skip them altogether. |
119 # This is accomplished by setting the flag 'generateid' to false | 144 # This is accomplished by setting the flag 'generateid' to false |
120 # in the GRD file. | 145 # in the GRD file. |
121 if item.attrs.get('generateid', 'true') == 'false': | 146 if item.attrs.get('generateid', 'true') == 'false': |
122 continue | 147 continue |
123 | 148 |
124 for tid in item.GetTextualIds(): | 149 for tid in item.GetTextualIds(): |
125 if util.SYSTEM_IDENTIFIERS.match(tid): | 150 if util.SYSTEM_IDENTIFIERS.match(tid): |
126 # Don't emit a new ID for predefined IDs | 151 # Don't emit a new ID for predefined IDs |
127 continue | 152 continue |
128 | 153 |
129 if tid in tids: | 154 if tid in tids: |
130 continue | 155 continue |
131 | 156 |
| 157 if predetermined_tids and tid in predetermined_tids: |
| 158 id = predetermined_tids[tid] |
| 159 reason = "from predetermined_tids map" |
| 160 |
132 # Some identifier nodes can provide their own id, | 161 # Some identifier nodes can provide their own id, |
133 # and we use that id in the generated header in that case. | 162 # and we use that id in the generated header in that case. |
134 if hasattr(item, 'GetId') and item.GetId(): | 163 elif hasattr(item, 'GetId') and item.GetId(): |
135 id = long(item.GetId()) | 164 id = long(item.GetId()) |
136 reason = 'returned by GetId() method' | 165 reason = 'returned by GetId() method' |
137 | 166 |
138 elif ('offset' in item.attrs and group and | 167 elif ('offset' in item.attrs and group and |
139 group.attrs.get('first_id', '') != ''): | 168 group.attrs.get('first_id', '') != ''): |
140 offset_text = item.attrs['offset'] | 169 offset_text = item.attrs['offset'] |
141 parent_text = group.attrs['first_id'] | 170 parent_text = group.attrs['first_id'] |
142 | 171 |
143 try: | 172 try: |
144 offset_id = long(offset_text) | 173 offset_id = long(offset_text) |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 # Don't fail when 'offset' is specified, as the base and the 0th | 219 # Don't fail when 'offset' is specified, as the base and the 0th |
191 # offset will have the same ID. | 220 # offset will have the same ID. |
192 if id in id_reasons and not 'offset' in item.attrs: | 221 if id in id_reasons and not 'offset' in item.attrs: |
193 raise exception.IdRangeOverlap('ID %d was assigned to both %s and %s.' | 222 raise exception.IdRangeOverlap('ID %d was assigned to both %s and %s.' |
194 % (id, id_reasons[id], reason)) | 223 % (id, id_reasons[id], reason)) |
195 | 224 |
196 if id < 101: | 225 if id < 101: |
197 print ('WARNING: Numeric resource IDs should be greater than 100 to\n' | 226 print ('WARNING: Numeric resource IDs should be greater than 100 to\n' |
198 'avoid conflicts with system-defined resource IDs.') | 227 'avoid conflicts with system-defined resource IDs.') |
199 | 228 |
| 229 if tid not in predetermined_tids and id in predetermined_ids: |
| 230 raise exception.IdRangeOverlap('ID %d overlaps between %s and %s' |
| 231 % (id, tid, predetermined_ids[tid])) |
| 232 |
200 ids[id] = tid | 233 ids[id] = tid |
201 tids[tid] = id | 234 tids[tid] = id |
202 id_reasons[id] = reason | 235 id_reasons[id] = reason |
203 | 236 |
204 return tids | 237 return tids |
OLD | NEW |