1#!/usr/bin/env python
2#
3
4import sys, cpp, kernel, glob, os, re, getopt
5from defaults import *
6from utils import *
7
8noUpdate = 1
9
10def  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
86if __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