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    blocks.optimizeMacros( macros )
70    blocks.optimizeIf01()
71    blocks.removeVarsAndFuncs( statics )
72    blocks.replaceTokens( kernel_token_replacements )
73    blocks.removeComments()
74    blocks.removeMacroDefines( kernel_ignored_macros )
75    blocks.removeWhiteSpace()
76
77    out = StringOutput()
78    out.write( kernel_disclaimer )
79    blocks.writeWithWarning(out, kernel_warning, 4)
80    return dst_path, out.get()
81
82
83if __name__ == "__main__":
84
85    def usage():
86        print """\
87    usage:  %s [options] <header_path>
88
89        options:
90            -v    enable verbose mode
91
92            -u    enabled update mode
93                this will try to update the corresponding 'clean header'
94                if the content has changed. with this, you can pass more
95                than one file on the command-line
96
97            -k<path>  specify path of original kernel headers
98            -d<path>  specify path of cleaned kernel headers
99
100        <header_path> must be in a subdirectory of 'original'
101    """ % os.path.basename(sys.argv[0])
102        sys.exit(1)
103
104    try:
105        optlist, args = getopt.getopt( sys.argv[1:], 'uvk:d:' )
106    except:
107        # unrecognized option
108        sys.stderr.write( "error: unrecognized option\n" )
109        usage()
110
111    for opt, arg in optlist:
112        if opt == '-u':
113            noUpdate = 0
114        elif opt == '-v':
115            verbose = 1
116            D_setlevel(1)
117        elif opt == '-k':
118            kernel_original_path = arg
119        elif opt == '-d':
120            kernel_cleaned_path = arg
121
122    if len(args) == 0:
123        usage()
124
125    if noUpdate:
126        for path in args:
127            dst_path, newdata = cleanupFile(path,kernel_original_path)
128            print newdata
129
130        sys.exit(0)
131
132    # now let's update our files.
133
134    b = BatchFileUpdater()
135
136    for path in args:
137        dst_path, newdata = cleanupFile(path,kernel_original_path)
138        if not dst_path:
139            continue
140
141        b.readFile( dst_path )
142        r = b.editFile( dst_path, newdata )
143        if r == 0:
144            r = "unchanged"
145        elif r == 1:
146            r = "edited"
147        else:
148            r = "added"
149
150        print "cleaning: %-*s -> %-*s (%s)" % ( 35, path, 35, dst_path, r )
151
152
153    b.updateGitFiles()
154
155    sys.exit(0)
156