build/buildutils/defreeze.py
branchRCL_3
changeset 14 04becd199f91
equal deleted inserted replaced
13:f5050f1da672 14:04becd199f91
       
     1 #
       
     2 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 # All rights reserved.
       
     4 # This component and the accompanying materials are made available
       
     5 # under the terms of "Eclipse Public License v1.0"
       
     6 # which accompanies this distribution, and is available
       
     7 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 #
       
     9 # Initial Contributors:
       
    10 # Nokia Corporation - initial contribution.
       
    11 #
       
    12 # Contributors:
       
    13 #
       
    14 # Description: 
       
    15 #
       
    16 
       
    17 import re, sys, glob, os.path
       
    18 from optparse import OptionParser
       
    19 
       
    20 # When defreezing, these entries can exist, but only at the beginning of the exports. 
       
    21 # Anything after these will be defrozen.
       
    22 ALLOWEDENTRIES = set(['_Z10jni_lookupPKc', '_Z13findDllMethodPKc'])
       
    23 
       
    24 # Pattern for entries
       
    25 RE_ENTRY = re.compile(r"^\s+([^ ]+) +@ +\d+ +NONAME( +ABSENT)?( *;.*)?$")
       
    26 
       
    27 # Transient exports which will be marked as absent.
       
    28 # See http://www.codesourcery.com/public/cxx-abi/abi.html#mangling for detailed 
       
    29 # de-mangling instructions
       
    30 TRANSIENTS = set([
       
    31     # TI = typeinfo structures
       
    32     '_ZTISi', # Si == ::std::basic_istream<char,  std::char_traits<char> >
       
    33     '_ZTISo', # So == ::std::basic_ostream<char,  std::char_traits<char> >
       
    34     '_ZTISd', # Sd == ::std::basic_iostream<char, std::char_traits<char> >
       
    35     '_ZTISt13basic_istreamIwSt11char_traitsIwEE',
       
    36     '_ZTISt13basic_ostreamIwSt11char_traitsIwEE',
       
    37     '_ZTISt14basic_iostreamIwSt11char_traitsIwEE',
       
    38     '_ZTISt15basic_streambufIwSt11char_traitsIwEE',
       
    39     '_ZTISt15basic_streambufIcSt11char_traitsIcEE',
       
    40     '_ZTISt13basic_filebufIcSt11char_traitsIcEE',
       
    41     '_ZTISt15basic_stringbufIcSt11char_traitsIcESaIcEE',
       
    42     '_ZTISt15basic_stringbufIwSt11char_traitsIwESaIwEE',
       
    43     '_ZTISt18basic_stringstreamIcSt11char_traitsIcESaIcEE',
       
    44     '_ZTISt18basic_stringstreamIwSt11char_traitsIwESaIwEE',
       
    45     '_ZTISt19basic_ostringstreamIcSt11char_traitsIcESaIcEE',
       
    46     '_ZTISt19basic_ostringstreamIwSt11char_traitsIwESaIwEE',
       
    47     '_ZTISt19basic_istringstreamIcSt11char_traitsIcESaIcEE',
       
    48     '_ZTISt19basic_istringstreamIwSt11char_traitsIwESaIwEE',
       
    49 
       
    50     # TV = virtual tables
       
    51     '_ZTVSi',
       
    52     '_ZTVSo',
       
    53     '_ZTVSd',
       
    54     '_ZTVSt13basic_istreamIwSt11char_traitsIwEE',
       
    55     '_ZTVSt13basic_ostreamIwSt11char_traitsIwEE',
       
    56     '_ZTVSt14basic_iostreamIwSt11char_traitsIwEE',
       
    57     '_ZTVSt15basic_streambufIwSt11char_traitsIwEE',
       
    58     '_ZTVSt15basic_streambufIcSt11char_traitsIcEE',
       
    59     '_ZTVSt13basic_filebufIcSt11char_traitsIcEE',
       
    60     '_ZTVSt15basic_stringbufIcSt11char_traitsIcESaIcEE',
       
    61     '_ZTVSt15basic_stringbufIwSt11char_traitsIwESaIwEE',
       
    62     '_ZTVSt18basic_stringstreamIcSt11char_traitsIcESaIcEE',
       
    63     '_ZTVSt18basic_stringstreamIwSt11char_traitsIwESaIwEE',
       
    64     '_ZTVSt19basic_ostringstreamIcSt11char_traitsIcESaIcEE',
       
    65     '_ZTVSt19basic_ostringstreamIwSt11char_traitsIwESaIwEE',
       
    66     '_ZTVSt19basic_istringstreamIcSt11char_traitsIcESaIcEE',
       
    67     '_ZTVSt19basic_istringstreamIwSt11char_traitsIwESaIwEE',
       
    68 
       
    69     # VTT structure (construction vtable index)
       
    70     '_ZTTSd',
       
    71     '_ZTTSi',
       
    72     '_ZTTSo',
       
    73     '_ZTTSt13basic_istreamIwSt11char_traitsIwEE',
       
    74     '_ZTTSt13basic_ostreamIwSt11char_traitsIwEE',
       
    75     '_ZTTSt14basic_ifstreamIcSt11char_traitsIcEE',
       
    76     '_ZTTSt14basic_iostreamIwSt11char_traitsIwEE',
       
    77     '_ZTTSt14basic_ofstreamIcSt11char_traitsIcEE',
       
    78     '_ZTTSt18basic_stringstreamIcSt11char_traitsIcESaIcEE',
       
    79     '_ZTTSt18basic_stringstreamIwSt11char_traitsIwESaIwEE',
       
    80     '_ZTTSt19basic_ostringstreamIcSt11char_traitsIcESaIcEE',
       
    81     '_ZTTSt19basic_ostringstreamIwSt11char_traitsIwESaIwEE',
       
    82     '_ZTTSt19basic_istringstreamIcSt11char_traitsIcESaIcEE',
       
    83     '_ZTTSt19basic_istringstreamIwSt11char_traitsIwESaIwEE'
       
    84 ])
       
    85 
       
    86 # These are produced only by 9.2, not by 5.0
       
    87 TRANSIENTS_92 = set([
       
    88     '_ZTTSd',
       
    89     '_ZTTSi',
       
    90     '_ZTTSo',
       
    91     '_ZTTSt13basic_istreamIwSt11char_traitsIwEE',
       
    92     '_ZTTSt13basic_ostreamIwSt11char_traitsIwEE',
       
    93     '_ZTTSt14basic_ifstreamIcSt11char_traitsIcEE',
       
    94     '_ZTTSt14basic_iostreamIwSt11char_traitsIwEE',
       
    95     '_ZTTSt14basic_ofstreamIcSt11char_traitsIcEE'
       
    96 ])
       
    97 
       
    98 # Only produced by stl4 - not by stl5
       
    99 TRANSIENTS_STL4 = set([
       
   100     '_ZTISi',
       
   101     '_ZTISt13basic_istreamIwSt11char_traitsIwEE',
       
   102     '_ZTVSi',
       
   103     '_ZTVSt13basic_istreamIwSt11char_traitsIwEE'
       
   104 ])
       
   105 
       
   106 
       
   107 # Only produced by stl5
       
   108 TRANSIENTS_STL5 = set([
       
   109     '_ZTISt15basic_streambufIcSt11char_traitsIcEE',
       
   110     '_ZTISt15basic_stringbufIcSt11char_traitsIcESaIcEE',
       
   111     '_ZTISt15basic_stringbufIwSt11char_traitsIwESaIwEE',
       
   112     '_ZTISt18basic_stringstreamIcSt11char_traitsIcESaIcEE',
       
   113     '_ZTISt18basic_stringstreamIwSt11char_traitsIwESaIwEE',
       
   114     '_ZTISt19basic_ostringstreamIcSt11char_traitsIcESaIcEE',
       
   115     '_ZTISt19basic_ostringstreamIwSt11char_traitsIwESaIwEE',
       
   116     '_ZTISt19basic_istringstreamIcSt11char_traitsIcESaIcEE',
       
   117     '_ZTISt19basic_istringstreamIwSt11char_traitsIwESaIwEE',
       
   118 
       
   119     '_ZTTSt18basic_stringstreamIcSt11char_traitsIcESaIcEE',
       
   120     '_ZTTSt18basic_stringstreamIwSt11char_traitsIwESaIwEE',
       
   121     '_ZTTSt19basic_ostringstreamIcSt11char_traitsIcESaIcEE',
       
   122     '_ZTTSt19basic_ostringstreamIwSt11char_traitsIwESaIwEE',
       
   123     '_ZTTSt19basic_istringstreamIcSt11char_traitsIcESaIcEE',
       
   124     '_ZTTSt19basic_istringstreamIwSt11char_traitsIwESaIwEE'
       
   125 
       
   126     '_ZTVSt15basic_streambufIcSt11char_traitsIcEE',
       
   127     '_ZTVSt15basic_stringbufIcSt11char_traitsIcESaIcEE',
       
   128     '_ZTVSt15basic_stringbufIwSt11char_traitsIwESaIwEE',
       
   129     '_ZTVSt18basic_stringstreamIcSt11char_traitsIcESaIcEE',
       
   130     '_ZTVSt18basic_stringstreamIwSt11char_traitsIwESaIwEE',
       
   131     '_ZTVSt19basic_ostringstreamIcSt11char_traitsIcESaIcEE',
       
   132     '_ZTVSt19basic_ostringstreamIwSt11char_traitsIwESaIwEE',
       
   133     '_ZTVSt19basic_istringstreamIcSt11char_traitsIcESaIcEE',
       
   134     '_ZTVSt19basic_istringstreamIwSt11char_traitsIwESaIwEE'
       
   135 ])
       
   136 
       
   137 TRANSIENTS_SPECIFIC = TRANSIENTS_92 | TRANSIENTS_STL4 | TRANSIENTS_STL5
       
   138 TRANSIENTS_COMMON = TRANSIENTS - TRANSIENTS_SPECIFIC
       
   139 
       
   140 def readExports(file):
       
   141     lines = [l.rstrip() for l in open(file).readlines()]
       
   142     if lines.pop(0) != "EXPORTS":
       
   143         raise Exception("File %s is not a deffile" % file)
       
   144 
       
   145     exports = []
       
   146     
       
   147     for l in lines:
       
   148         # Skip empty lines
       
   149         if len(l.strip()) == 0:
       
   150             continue
       
   151 
       
   152         # Read lines
       
   153         match = RE_ENTRY.match(l)
       
   154         if not match:
       
   155             raise Exception("Unrecognized line on file %s: %s" % (file, l))
       
   156 
       
   157         (export, absent, comment) = match.groups()
       
   158         exports.append((export, absent, comment))
       
   159 
       
   160         
       
   161     return exports
       
   162 
       
   163 def movelastTransients(exports):
       
   164     return  [e for e in exports if e[0] not in TRANSIENTS] + \
       
   165             [e for e in exports if e[0] in TRANSIENTS]
       
   166 
       
   167 def removeSpecific(exports):
       
   168     return  [e for e in exports if e[0] not in TRANSIENTS_SPECIFIC]
       
   169 
       
   170 def absentTransients(exports):
       
   171     newExports = []
       
   172     for e in exports:
       
   173         if e[0] in TRANSIENTS:
       
   174             e = (e[0], " ABSENT", e[2])
       
   175         newExports.append(e)
       
   176     return newExports
       
   177 
       
   178 def removeTransients(exports):
       
   179     return  [e for e in exports if e[0] not in TRANSIENTS]
       
   180 
       
   181 def defreeze(exports):
       
   182     defrozen = []
       
   183     for export, absent, comment in exports:
       
   184         if export in ALLOWEDENTRIES:
       
   185             defrozen.append((export, absent, comment))
       
   186         else:
       
   187             break
       
   188     return defrozen
       
   189 
       
   190 def generate(exports):
       
   191     output = "EXPORTS\n"
       
   192 
       
   193     for index in range(len(exports)):
       
   194         (export, absent, comment) = exports[index]
       
   195         output = output + "\t%s @ %i NONAME%s%s\n" % (
       
   196             export, index + 1, absent or "", comment or "")
       
   197     return output + "\n"
       
   198 
       
   199 def list(exports):
       
   200     return "\n    ".join(["'%s'," % e[0] for e in exports])
       
   201 
       
   202 
       
   203 def main():
       
   204     parser = OptionParser()
       
   205     parser.add_option("-f", dest = "outputFile")
       
   206     parser.add_option("-d", dest = "outputDir")
       
   207     parser.add_option("-o", dest = "overwrite",
       
   208                       action = "store_true", default = False)
       
   209     parser.add_option("--reorder", dest = "reorder",
       
   210                       action = "store_true", default = False,
       
   211                       help = "reorder transient exports to last")
       
   212     parser.add_option("--removeSpecific", dest = "removeSpecific",
       
   213                       action = "store_true", default = False,
       
   214                       help = "remove exports which are specific to some environment")
       
   215     parser.add_option("--removeTransients", dest = "removeTransients",
       
   216                       action = "store_true", default = False,
       
   217                       help = "remove all exports which are transients")
       
   218     parser.add_option("--absentify", dest = "absentify",
       
   219                       action = "store_true", default = False,
       
   220                       help = "make absent transients exports")
       
   221     parser.add_option("--defreeze", dest = "defreeze",
       
   222                       action = "store_true", default = False,
       
   223                       help = "defreeze all except configured exports")
       
   224     parser.add_option("--list", dest = "list",
       
   225                       action = "store_true", default = False)
       
   226     (options, args) = parser.parse_args()
       
   227 
       
   228     # Read
       
   229     for file in sum([glob.glob(arg) for arg in args], []):
       
   230         exports = readExports(file)
       
   231 
       
   232         # Modify
       
   233         if options.reorder:
       
   234             exports = movelastTransients(exports)
       
   235         if options.removeSpecific:
       
   236             exports = removeSpecific(exports)
       
   237         if options.absentify:
       
   238             exports = absentTransients(exports)
       
   239         if options.defreeze:
       
   240             exports = defreeze(exports)
       
   241         if options.removeTransients:
       
   242             exports = removeTransients(exports)
       
   243 
       
   244         # Generate / list
       
   245         if options.list:
       
   246             output = list(exports)
       
   247         else:
       
   248             output = generate(exports)
       
   249 
       
   250         # Write / print
       
   251         if options.outputFile:
       
   252             open(options.outputFile, "w").write(output)
       
   253         elif options.outputDir:
       
   254             open(os.path.join(options.outputDir, os.path.basename(file)), 
       
   255                  "w").write(output)
       
   256         elif options.overwrite:
       
   257             open(file, "w").write(output)
       
   258             print "Modified %s" % file
       
   259         else:
       
   260             print output        
       
   261 
       
   262 if __name__ == "__main__":
       
   263     main()
       
   264 
       
   265