~ubuntu-branches/ubuntu/oneiric/mozc/oneiric

« back to all changes in this revision

Viewing changes to third_party/gyp/tools/pretty_vcproj.py

  • Committer: Bazaar Package Importer
  • Author(s): Nobuhiro Iwamatsu
  • Date: 2010-07-14 03:26:47 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100714032647-13qjisj6m8cm8jdx
Tags: 0.12.410.102-1
* New upstream release (Closes: #588971).
  - Add mozc-server, mozc-utils-gui and scim-mozc packages.
* Update debian/rules.
  Add --gypdir option to build_mozc.py.
* Update debian/control.
  - Bumped standards-version to 3.9.0.
  - Update description.
* Add mozc icon (Closes: #588972).
* Add patch which revises issue 18.
  ibus_mozc_issue18.patch
* kFreeBSD build support.
  support_kfreebsd.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python2.5
 
2
 
 
3
# Copyright (c) 2009 Google Inc. All rights reserved.
 
4
# Use of this source code is governed by a BSD-style license that can be
 
5
# found in the LICENSE file.
 
6
 
 
7
"""Make the format of a vcproj really pretty.
 
8
 
 
9
   This script normalize and sort an xml. It also fetches all the properties
 
10
   inside linked vsprops and include them explicitly in the vcproj.
 
11
 
 
12
   It outputs the resulting xml to stdout.
 
13
"""
 
14
 
 
15
__author__ = 'nsylvain (Nicolas Sylvain)'
 
16
 
 
17
import os
 
18
import sys
 
19
 
 
20
from xml.dom.minidom import parse
 
21
from xml.dom.minidom import Node
 
22
 
 
23
REPLACEMENTS = dict()
 
24
ARGUMENTS = None
 
25
 
 
26
class CmpTuple:
 
27
  """Compare function between 2 tuple."""
 
28
  def __call__(self, x, y):
 
29
    (key1, value1) = x
 
30
    (key2, value2) = y
 
31
    return cmp(key1, key2)
 
32
 
 
33
class CmpNode:
 
34
  """Compare function between 2 xml nodes."""
 
35
 
 
36
  def get_string(self, node):
 
37
    node_string = "node"
 
38
    node_string += node.nodeName
 
39
    if node.nodeValue:
 
40
      node_string += node.nodeValue
 
41
 
 
42
    if node.attributes:
 
43
      # We first sort by name, if present.
 
44
      node_string += node.getAttribute("Name")
 
45
 
 
46
      all_nodes = []
 
47
      for (name, value) in node.attributes.items():
 
48
        all_nodes.append((name, value))
 
49
 
 
50
      all_nodes.sort(CmpTuple())
 
51
      for (name, value) in all_nodes:
 
52
        node_string += name
 
53
        node_string += value
 
54
 
 
55
    return node_string
 
56
 
 
57
  def __call__(self, x, y):
 
58
    return cmp(self.get_string(x), self.get_string(y))
 
59
 
 
60
def PrettyPrintNode(node, indent=0):
 
61
  if node.nodeType == Node.TEXT_NODE:
 
62
    if node.data.strip():
 
63
      print '%s%s' % (' '*indent, node.data.strip())
 
64
    return
 
65
 
 
66
  if node.childNodes:
 
67
    node.normalize()
 
68
  # Get the number of attributes
 
69
  attr_count = 0
 
70
  if node.attributes:
 
71
    attr_count = node.attributes.length
 
72
 
 
73
  # Print the main tag
 
74
  if attr_count == 0:
 
75
    print '%s<%s>' % (' '*indent, node.nodeName)
 
76
  else:
 
77
    print '%s<%s' % (' '*indent, node.nodeName)
 
78
 
 
79
    all_attributes = []
 
80
    for (name, value) in node.attributes.items():
 
81
      all_attributes.append((name, value))
 
82
      all_attributes.sort(CmpTuple())
 
83
    for (name, value) in all_attributes:
 
84
      print '%s  %s="%s"' % (' '*indent, name, value)
 
85
    print '%s>' % (' '*indent)
 
86
  if node.nodeValue:
 
87
    print '%s  %s' % (' '*indent, node.nodeValue)
 
88
 
 
89
  for sub_node in node.childNodes:
 
90
    PrettyPrintNode(sub_node, indent=indent+2)
 
91
  print '%s</%s>' % (' '*indent, node.nodeName)
 
92
 
 
93
def FlattenFilter(node):
 
94
  """Returns a list of all the node and sub nodes."""
 
95
  node_list = []
 
96
 
 
97
  if (node.attributes and
 
98
      node.getAttribute('Name') == '_excluded_files'):
 
99
      # We don't add the "_excluded_files" filter.
 
100
    return []
 
101
 
 
102
  for current in node.childNodes:
 
103
    if current.nodeName == 'Filter':
 
104
      node_list.extend(FlattenFilter(current))
 
105
    else:
 
106
      node_list.append(current)
 
107
 
 
108
  return node_list
 
109
 
 
110
def FixFilenames(filenames, current_directory):
 
111
  new_list = []
 
112
  for filename in filenames:
 
113
    if filename:
 
114
      for key in REPLACEMENTS:
 
115
        filename = filename.replace(key, REPLACEMENTS[key])
 
116
      os.chdir(current_directory)
 
117
      filename = filename.strip('"\' ')
 
118
      if filename.startswith('$'):
 
119
        new_list.append(filename)
 
120
      else:
 
121
        new_list.append(os.path.abspath(filename))
 
122
  return new_list
 
123
 
 
124
def AbsoluteNode(node):
 
125
  # Make all the properties we know about in this node absolute.
 
126
  if node.attributes:
 
127
    for (name, value) in node.attributes.items():
 
128
      if name in ['InheritedPropertySheets', 'RelativePath',
 
129
                  'AdditionalIncludeDirectories',
 
130
                  'IntermediateDirectory', 'OutputDirectory',
 
131
                  'AdditionalLibraryDirectories']:
 
132
        # We want to fix up these paths
 
133
        path_list = value.split(';')
 
134
        new_list = FixFilenames(path_list, os.path.dirname(ARGUMENTS[1]))
 
135
        node.setAttribute(name, ';'.join(new_list))
 
136
      if not value:
 
137
        node.removeAttribute(name)
 
138
 
 
139
def CleanupVcproj(node):
 
140
  # For each sub node, we call recursively this function.
 
141
  for sub_node in node.childNodes:
 
142
    AbsoluteNode(sub_node)
 
143
    CleanupVcproj(sub_node)
 
144
 
 
145
  # Normalize the node, and remove all extranous whitespaces.
 
146
  for sub_node in node.childNodes:
 
147
    if sub_node.nodeType == Node.TEXT_NODE:
 
148
        sub_node.data = sub_node.data.replace("\r", "")
 
149
        sub_node.data = sub_node.data.replace("\n", "")
 
150
        sub_node.data = sub_node.data.rstrip()
 
151
 
 
152
  # Fix all the semicolon separated attributes to be sorted, and we also
 
153
  # remove the dups.
 
154
  if node.attributes:
 
155
    for (name, value) in node.attributes.items():
 
156
      sorted_list = sorted(value.split(';'))
 
157
      unique_list = []
 
158
      [unique_list.append(i) for i in sorted_list if not unique_list.count(i)]
 
159
      node.setAttribute(name, ';'.join(unique_list))
 
160
      if not value:
 
161
        node.removeAttribute(name)
 
162
 
 
163
  if node.childNodes:
 
164
    node.normalize()
 
165
 
 
166
  # For each node, take a copy, and remove it from the list.
 
167
  node_array = []
 
168
  while node.childNodes and node.childNodes[0]:
 
169
    # Take a copy of the node and remove it from the list.
 
170
    current = node.childNodes[0]
 
171
    node.removeChild(current)
 
172
 
 
173
    # If the child is a filter, we want to append all its children
 
174
    # to this same list.
 
175
    if current.nodeName == 'Filter':
 
176
      node_array.extend(FlattenFilter(current))
 
177
    else:
 
178
      node_array.append(current)
 
179
 
 
180
 
 
181
  # Sort the list.
 
182
  node_array.sort(CmpNode())
 
183
 
 
184
  # Insert the nodes in the correct order.
 
185
  for new_node in node_array:
 
186
    # But don't append empty tool node.
 
187
    if new_node.nodeName == 'Tool':
 
188
      if new_node.attributes and new_node.attributes.length == 1:
 
189
        # This one was empty.
 
190
        continue
 
191
    if new_node.nodeName == 'UserMacro':
 
192
      continue
 
193
    node.appendChild(new_node)
 
194
 
 
195
def GetConfiguationNodes(vcproj):
 
196
  #TODO(nsylvain): Find a better way to navigate the xml.
 
197
  nodes = []
 
198
  for node in vcproj.childNodes:
 
199
    if node.nodeName == "Configurations":
 
200
      for sub_node in node.childNodes:
 
201
        if sub_node.nodeName == "Configuration":
 
202
          nodes.append(sub_node)
 
203
 
 
204
  return nodes
 
205
 
 
206
def GetChildrenVsprops(filename):
 
207
  dom = parse(filename)
 
208
  if dom.documentElement.attributes:
 
209
    vsprops = dom.documentElement.getAttribute('InheritedPropertySheets')
 
210
    return FixFilenames(vsprops.split(';'), os.path.dirname(filename))
 
211
  return []
 
212
 
 
213
def SeekToNode(node1, child2):
 
214
  # A text node does not have properties.
 
215
  if child2.nodeType == Node.TEXT_NODE:
 
216
    return None
 
217
 
 
218
  # Get the name of the current node.
 
219
  current_name = child2.getAttribute("Name")
 
220
  if not current_name:
 
221
    # There is no name. We don't know how to merge.
 
222
    return None
 
223
 
 
224
  # Look through all the nodes to find a match.
 
225
  for sub_node in node1.childNodes:
 
226
    if sub_node.nodeName == child2.nodeName:
 
227
      name = sub_node.getAttribute("Name")
 
228
      if name == current_name:
 
229
        return sub_node
 
230
 
 
231
  # No match. We give up.
 
232
  return None
 
233
 
 
234
def MergeAttributes(node1, node2):
 
235
  # No attributes to merge?
 
236
  if not node2.attributes:
 
237
    return
 
238
 
 
239
  for (name, value2) in node2.attributes.items():
 
240
    # Don't merge the 'Name' attribute.
 
241
    if name == 'Name':
 
242
      continue
 
243
    value1 = node1.getAttribute(name)
 
244
    if value1:
 
245
      # The attribute exist in the main node. If it's equal, we leave it
 
246
      # untouched, otherwise we concatenate it.
 
247
      if value1 != value2:
 
248
        node1.setAttribute(name, ';'.join([value1, value2]))
 
249
    else:
 
250
      # The attribute does nto exist in the main node. We append this one.
 
251
      node1.setAttribute(name, value2)
 
252
 
 
253
    # If the attribute was a property sheet attributes, we remove it, since
 
254
    # they are useless.
 
255
    if name == 'InheritedPropertySheets':
 
256
      node1.removeAttribute(name)
 
257
 
 
258
def MergeProperties(node1, node2):
 
259
  MergeAttributes(node1, node2)
 
260
  for child2 in node2.childNodes:
 
261
    child1 = SeekToNode(node1, child2)
 
262
    if child1:
 
263
      MergeProperties(child1, child2)
 
264
    else:
 
265
      node1.appendChild(child2.cloneNode(True))
 
266
 
 
267
def main(argv):
 
268
  global REPLACEMENTS
 
269
  global ARGUMENTS
 
270
  ARGUMENTS = argv
 
271
  """Main function of this vcproj prettifier."""
 
272
 
 
273
  # check if we have exactly 1 parameter.
 
274
  if len(argv) < 2:
 
275
    print ('Usage: %s "c:\\path\\to\\vcproj.vcproj" [key1=value1] '
 
276
           '[key2=value2]' % argv[0])
 
277
    return
 
278
 
 
279
  # Parse the keys
 
280
  for i in range(2, len(argv)):
 
281
    (key, value) = argv[i].split('=')
 
282
    REPLACEMENTS[key] = value
 
283
 
 
284
  # Open the vcproj and parse the xml.
 
285
  dom = parse(argv[1])
 
286
 
 
287
  # First thing we need to do is find the Configuration Node and merge them
 
288
  # with the vsprops they include.
 
289
  for configuration_node in GetConfiguationNodes(dom.documentElement):
 
290
    # Get the property sheets associated with this configuration.
 
291
    vsprops = configuration_node.getAttribute('InheritedPropertySheets')
 
292
 
 
293
    # Fix the filenames to be absolute.
 
294
    vsprops_list = FixFilenames(vsprops.strip().split(';'),
 
295
                                os.path.dirname(argv[1]))
 
296
 
 
297
    # Extend the list of vsprops with all vsprops contained in the current
 
298
    # vsprops.
 
299
    for current_vsprops in vsprops_list:
 
300
     vsprops_list.extend(GetChildrenVsprops(current_vsprops))
 
301
 
 
302
    # Now that we have all the vsprops, we need to merge them.
 
303
    for current_vsprops in vsprops_list:
 
304
      MergeProperties(configuration_node,
 
305
                      parse(current_vsprops).documentElement)
 
306
 
 
307
  # Now that everything is merged, we need to cleanup the xml.
 
308
  CleanupVcproj(dom.documentElement)
 
309
 
 
310
  # Finally, we use the prett xml function to print the vcproj back to the
 
311
  # user.
 
312
  #print dom.toprettyxml(newl="\n")
 
313
  PrettyPrintNode(dom.documentElement)
 
314
 
 
315
if __name__ == '__main__':
 
316
  main(sys.argv)