Home | History | Annotate | Download | only in tools
      1 #!/usr/bin/env python
      2 #
      3 
      4 import sys, cpp, kernel, glob, os, re, getopt
      5 from defaults import *
      6 from utils import *
      7 
      8 noUpdate = 1
      9 
     10 def  cleanupFile( path, original_path):
     11     """reads an original header and perform the cleanup operation on it
     12        this functions returns the destination path and the clean header
     13        as a single string"""
     14     # check the header path
     15     src_path = path
     16 
     17     if not os.path.exists(src_path):
     18         if noUpdate:
     19             panic( "file does not exist: '%s'\n" % path )
     20         sys.stderr.write( "warning: file does not exit: %s\n" % path )
     21         return None, None
     22 
     23     if not os.path.isfile(src_path):
     24         if noUpdate:
     25             panic( "path is not a file: '%s'\n" % path )
     26         sys.stderr.write( "warning: not a file: %s\n" % path )
     27         return None, None
     28 
     29     if os.path.commonprefix( [ src_path, original_path ] ) != original_path:
     30         if noUpdate:
     31             panic( "file is not in 'original' directory: %s\n" % path );
     32         sys.stderr.write( "warning: file not in 'original' ignored: %s\n" % path )
     33         return None, None
     34 
     35     src_path = src_path[len(original_path):]
     36     if len(src_path) > 0 and src_path[0] == '/':
     37         src_path = src_path[1:]
     38 
     39     if len(src_path) == 0:
     40         panic( "oops, internal error, can't extract correct relative path\n" )
     41 
     42     # convert into destination path, extracting architecture if needed
     43     # and the corresponding list of known static functions
     44     #
     45     arch = None
     46     re_asm_arch = re.compile( r"asm-([\w\d_\+\.\-]+)(/.*)" )
     47     m = re_asm_arch.match(src_path)
     48     statics = kernel_known_generic_statics
     49     if m and m.group(1) != 'generic':
     50         dst_path = "arch-%s/asm/%s" % m.groups()
     51         arch     = m.group(1)
     52         statics  = statics.union( kernel_known_statics.get( arch, set() ) )
     53     else:
     54         dst_path = "common/" + src_path
     55 
     56     dst_path = os.path.normpath( kernel_cleaned_path + "/" + dst_path )
     57 
     58     # now, let's parse the file
     59     #
     60     blocks = cpp.BlockParser().parseFile(path)
     61     if not blocks:
     62         sys.stderr.write( "error: can't parse '%s'" % path )
     63         sys.exit(1)
     64 
     65     macros = kernel_known_macros.copy()
     66     if arch and arch in kernel_default_arch_macros:
     67         macros.update(kernel_default_arch_macros[arch])
     68 
     69     if arch and arch in kernel_arch_token_replacements:
     70         blocks.replaceTokens( kernel_arch_token_replacements[arch] )
     71 
     72     blocks.optimizeMacros( macros )
     73     blocks.optimizeIf01()
     74     blocks.removeVarsAndFuncs( statics )
     75     blocks.replaceTokens( kernel_token_replacements )
     76     blocks.removeComments()
     77     blocks.removeMacroDefines( kernel_ignored_macros )
     78     blocks.removeWhiteSpace()
     79 
     80     out = StringOutput()
     81     out.write( kernel_disclaimer )
     82     blocks.writeWithWarning(out, kernel_warning, 4)
     83     return dst_path, out.get()
     84 
     85 
     86 if __name__ == "__main__":
     87 
     88     def usage():
     89         print """\
     90     usage:  %s [options] <header_path>
     91 
     92         options:
     93             -v    enable verbose mode
     94 
     95             -u    enabled update mode
     96                 this will try to update the corresponding 'clean header'
     97                 if the content has changed. with this, you can pass more
     98                 than one file on the command-line
     99 
    100             -k<path>  specify path of original kernel headers
    101             -d<path>  specify path of cleaned kernel headers
    102 
    103         <header_path> must be in a subdirectory of 'original'
    104     """ % os.path.basename(sys.argv[0])
    105         sys.exit(1)
    106 
    107     try:
    108         optlist, args = getopt.getopt( sys.argv[1:], 'uvk:d:' )
    109     except:
    110         # unrecognized option
    111         sys.stderr.write( "error: unrecognized option\n" )
    112         usage()
    113 
    114     for opt, arg in optlist:
    115         if opt == '-u':
    116             noUpdate = 0
    117         elif opt == '-v':
    118             verbose = 1
    119             D_setlevel(1)
    120         elif opt == '-k':
    121             kernel_original_path = arg
    122         elif opt == '-d':
    123             kernel_cleaned_path = arg
    124 
    125     if len(args) == 0:
    126         usage()
    127 
    128     if noUpdate:
    129         for path in args:
    130             dst_path, newdata = cleanupFile(path,kernel_original_path)
    131             print newdata
    132 
    133         sys.exit(0)
    134 
    135     # now let's update our files.
    136 
    137     b = BatchFileUpdater()
    138 
    139     for path in args:
    140         dst_path, newdata = cleanupFile(path,kernel_original_path)
    141         if not dst_path:
    142             continue
    143 
    144         b.readFile( dst_path )
    145         r = b.editFile( dst_path, newdata )
    146         if r == 0:
    147             r = "unchanged"
    148         elif r == 1:
    149             r = "edited"
    150         else:
    151             r = "added"
    152 
    153         print "cleaning: %-*s -> %-*s (%s)" % ( 35, path, 35, dst_path, r )
    154 
    155 
    156     b.updateGitFiles()
    157 
    158     sys.exit(0)
    159