Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Side by Side Diff: grit/format/rc_header.py

Issue 1442863002: Remove contents of grit's SVN repository. (Closed) Base URL: http://grit-i18n.googlecode.com/svn/trunk/
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « grit/format/rc.py ('k') | grit/format/rc_header_unittest.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
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
4 # found in the LICENSE file.
5
6 '''Item formatters for RC headers.
7 '''
8
9 from grit import exception
10 from grit import util
11 from grit.extern import FP
12
13
14 def Format(root, lang='en', output_dir='.'):
15 yield '''\
16 // This file is automatically generated by GRIT. Do not edit.
17
18 #pragma once
19 '''
20 # Check for emit nodes under the rc_header. If any emit node
21 # is present, we assume it means the GRD file wants to override
22 # the default header, with no includes.
23 default_includes = ['#include <atlres.h>', '']
24 emit_lines = []
25 for output_node in root.GetOutputFiles():
26 if output_node.GetType() == 'rc_header':
27 for child in output_node.children:
28 if child.name == 'emit' and child.attrs['emit_type'] == 'prepend':
29 emit_lines.append(child.GetCdata())
30 for line in emit_lines or default_includes:
31 yield line + '\n'
32
33 for line in FormatDefines(root, root.ShouldOutputAllResourceDefines(),
34 root.GetRcHeaderFormat()):
35 yield line
36
37
38 def FormatDefines(root, output_all_resource_defines=True,
39 rc_header_format=None):
40 '''Yields #define SYMBOL 1234 lines.
41
42 Args:
43 root: A GritNode.
44 output_all_resource_defines: If False, output only the symbols used in the
45 current output configuration.
46 '''
47 from grit.node import message
48 tids = GetIds(root)
49
50 if output_all_resource_defines:
51 items = root.Preorder()
52 else:
53 items = root.ActiveDescendants()
54
55 if not rc_header_format:
56 rc_header_format = "#define {textual_id} {numeric_id}"
57 rc_header_format += "\n"
58 seen = set()
59 for item in items:
60 if not isinstance(item, message.MessageNode):
61 with item:
62 for tid in item.GetTextualIds():
63 if tid in tids and tid not in seen:
64 seen.add(tid)
65 yield rc_header_format.format(textual_id=tid,numeric_id=tids[tid])
66
67 # Temporarily mimic old behavior: MessageNodes were only output if active,
68 # even with output_all_resource_defines set. TODO(benrg): Remove this after
69 # fixing problems in the Chrome tree.
70 for item in root.ActiveDescendants():
71 if isinstance(item, message.MessageNode):
72 with item:
73 for tid in item.GetTextualIds():
74 if tid in tids and tid not in seen:
75 seen.add(tid)
76 yield rc_header_format.format(textual_id=tid,numeric_id=tids[tid])
77
78
79 _cached_ids = {}
80
81
82 def GetIds(root):
83 '''Return a dictionary mapping textual ids to numeric ids for the given tree.
84
85 Args:
86 root: A GritNode.
87 '''
88 # 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
90 # other hand, GritNode has too much random stuff already.
91 if root not in _cached_ids:
92 _cached_ids[root] = _ComputeIds(root)
93 return _cached_ids[root]
94
95
96 def _ComputeIds(root):
97 from grit.node import empty, include, message, misc, structure
98
99 ids = {} # Maps numeric id to textual id
100 tids = {} # Maps textual id to numeric id
101 id_reasons = {} # Maps numeric id to text id and a human-readable explanation
102 group = None
103 last_id = None
104
105 for item in root:
106 if isinstance(item, empty.GroupingNode):
107 # Note: this won't work if any GroupingNode can be contained inside
108 # another.
109 group = item
110 last_id = None
111 continue
112
113 assert not item.GetTextualIds() or isinstance(item,
114 (include.IncludeNode, message.MessageNode,
115 misc.IdentifierNode, structure.StructureNode))
116
117 # Resources that use the RES protocol don't need
118 # any numerical ids generated, so we skip them altogether.
119 # This is accomplished by setting the flag 'generateid' to false
120 # in the GRD file.
121 if item.attrs.get('generateid', 'true') == 'false':
122 continue
123
124 for tid in item.GetTextualIds():
125 if util.SYSTEM_IDENTIFIERS.match(tid):
126 # Don't emit a new ID for predefined IDs
127 continue
128
129 if tid in tids:
130 continue
131
132 # Some identifier nodes can provide their own id,
133 # and we use that id in the generated header in that case.
134 if hasattr(item, 'GetId') and item.GetId():
135 id = long(item.GetId())
136 reason = 'returned by GetId() method'
137
138 elif ('offset' in item.attrs and group and
139 group.attrs.get('first_id', '') != ''):
140 offset_text = item.attrs['offset']
141 parent_text = group.attrs['first_id']
142
143 try:
144 offset_id = long(offset_text)
145 except ValueError:
146 offset_id = tids[offset_text]
147
148 try:
149 parent_id = long(parent_text)
150 except ValueError:
151 parent_id = tids[parent_text]
152
153 id = parent_id + offset_id
154 reason = 'first_id %d + offset %d' % (parent_id, offset_id)
155
156 # We try to allocate IDs sequentially for blocks of items that might
157 # be related, for instance strings in a stringtable (as their IDs might be
158 # used e.g. as IDs for some radio buttons, in which case the IDs must
159 # be sequential).
160 #
161 # We do this by having the first item in a section store its computed ID
162 # (computed from a fingerprint) in its parent object. Subsequent children
163 # of the same parent will then try to get IDs that sequentially follow
164 # the currently stored ID (on the parent) and increment it.
165 elif last_id is None:
166 # First check if the starting ID is explicitly specified by the parent.
167 if group and group.attrs.get('first_id', '') != '':
168 id = long(group.attrs['first_id'])
169 reason = "from parent's first_id attribute"
170 else:
171 # Automatically generate the ID based on the first clique from the
172 # first child of the first child node of our parent (i.e. when we
173 # first get to this location in the code).
174
175 # According to
176 # http://msdn.microsoft.com/en-us/library/t2zechd4(VS.71).aspx
177 # the safe usable range for resource IDs in Windows is from decimal
178 # 101 to 0x7FFF.
179
180 id = FP.UnsignedFingerPrint(tid)
181 id = id % (0x7FFF - 101) + 101
182 reason = 'chosen by random fingerprint -- use first_id to override'
183
184 last_id = id
185 else:
186 id = last_id = last_id + 1
187 reason = 'sequentially assigned'
188
189 reason = "%s (%s)" % (tid, reason)
190 # Don't fail when 'offset' is specified, as the base and the 0th
191 # offset will have the same ID.
192 if id in id_reasons and not 'offset' in item.attrs:
193 raise exception.IdRangeOverlap('ID %d was assigned to both %s and %s.'
194 % (id, id_reasons[id], reason))
195
196 if id < 101:
197 print ('WARNING: Numeric resource IDs should be greater than 100 to\n'
198 'avoid conflicts with system-defined resource IDs.')
199
200 ids[id] = tid
201 tids[tid] = id
202 id_reasons[id] = reason
203
204 return tids
OLDNEW
« no previous file with comments | « grit/format/rc.py ('k') | grit/format/rc_header_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698