"Fossies" - the Fresh Open Source Software Archive

Member "node-v12.18.4-win-x86/node_modules/npm/node_modules/node-gyp/gyp/tools/pretty_vcproj.py" (14 Feb 2020, 10046 Bytes) of package /windows/www/node-v12.18.4-win-x86.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

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