blob: fe315f6df09992f9bcfc72fec8f4df0b5f6768f4 [file] [log] [blame]
Ted Kremenekb0982882008-03-25 22:35:32 +00001#!/usr/bin/env python
2#
3# The LLVM Compiler Infrastructure
4#
5# This file is distributed under the University of Illinois Open Source
6# License. See LICENSE.TXT for details.
7#
8##===----------------------------------------------------------------------===##
9#
10# A reduced version of the 'ccc' script that is designed to handle off
11# actual compilation to gcc, but run the code passed to gcc through the
12# static analyzer.
13#
14##===----------------------------------------------------------------------===##
15
16import sys
17import subprocess
18import os
19
20def error(message):
21 print >> sys.stderr, 'ccc: ' + message
22 sys.exit(1)
23
Seo Sanghyeond3894652008-04-04 11:02:21 +000024def quote(arg):
25 if '"' in arg:
26 return repr(arg)
27 return arg
28
Ted Kremenekb0982882008-03-25 22:35:32 +000029def run(args):
Seo Sanghyeond3894652008-04-04 11:02:21 +000030 print ' '.join(map(quote, args))
31 print
Ted Kremenekb0982882008-03-25 22:35:32 +000032 code = subprocess.call(args)
33 if code > 255:
34 code = 1
35 if code:
36 sys.exit(code)
37
38def preprocess(args):
39 command = 'clang -E'.split()
40 run(command + args)
41
42def compile(args):
43 print >> sys.stderr, '\n'
44 command = 'gcc'.split()
45 run(command + args)
46
47def remove_pch_extension(path):
48 i = path.rfind('.gch')
49 if i < 0:
50 return path
51 return path[:i]
52
Ted Kremenek09c2ad62008-03-31 18:25:05 +000053def analyze(args,language,output,files,verbose,htmldir):
Ted Kremenek8cb53fb2008-04-03 21:29:11 +000054 if language.find("c++") > 0:
Ted Kremenekb0982882008-03-25 22:35:32 +000055 return
56
Ted Kremenekb0982882008-03-25 22:35:32 +000057 print_args = []
58
Ted Kremenek09c2ad62008-03-31 18:25:05 +000059 if verbose:
60 print >> sys.stderr, ' '.join(['\n[LOCATION]:', os.getcwd(), '\n' ])
61 i = 0
62 while i < len(args):
Ted Kremenekb0982882008-03-25 22:35:32 +000063 print_args.append(''.join([ '\'', args[i], '\'' ]))
64 i += 1
65
66 if language.find("header") > 0:
67 target = remove_pch_extension(output)
68 command = 'cp'.split()
69 args = command + files + target.split()
70 else:
71 command = 'clang --grsimple'.split()
Ted Kremenek69b64422008-03-31 21:20:32 +000072 args = command + args;
73
74 if htmldir is not None:
75 args.append('-o')
76 print_args.append('-o')
77 args.append(htmldir)
78 print_args.append(htmldir)
Ted Kremenek09c2ad62008-03-31 18:25:05 +000079
80 if verbose:
81 print >> sys.stderr, ' '.join(command+print_args)
82 print >> sys.stderr, '\n'
Ted Kremenekb0982882008-03-25 22:35:32 +000083
Ted Kremenekb0982882008-03-25 22:35:32 +000084 subprocess.call(args)
85
86def link(args):
87 command = 'gcc'.split()
88 run(command + args)
89
90def extension(path):
91 return path.split(".")[-1]
92
93def changeextension(path, newext):
94 i = path.rfind('.')
95 if i < 0:
96 return path
97 j = path.rfind('/', 0, i)
98 print path
99 if j < 0:
100 return path[:i] + "." + newext
101 return path[j+1:i] + "." + newext
102
103def inferlanguage(extension):
104 if extension == "c":
105 return "c"
106 elif extension in ["cpp", "cc"]:
107 return "c++"
108 elif extension == "i":
109 return "c-cpp-output"
110 elif extension == "m":
111 return "objective-c"
112 elif extension == "mi":
113 return "objective-c-cpp-output"
114 else:
115 return "unknown"
116
117def main(args):
118 old_args = args
119 action = 'link'
120 output = ''
121 compile_opts = [ ]
122 link_opts = [ ]
123 files = []
124 save_temps = 0
125 language = ''
126
Ted Kremenek09c2ad62008-03-31 18:25:05 +0000127 verbose = 0
128
129 if os.environ.get('CCC_ANALYZER_VERBOSE') is not None:
130 verbose =1
131
132 htmldir = os.environ.get('CCC_ANALYZER_HTML')
Ted Kremenek09c2ad62008-03-31 18:25:05 +0000133
Ted Kremenekb0982882008-03-25 22:35:32 +0000134 i = 0
135 while i < len(args):
136 arg = args[i]
137
138 # Modes ccc supports
139 if arg == '-E':
140 action = 'preprocess'
141 if arg == '-c':
142 action = 'compile'
143 if arg.startswith('-print-prog-name'):
144 action = 'print-prog-name'
145 if arg == '-save-temps':
146 save_temps = 1
147
148 # Options with no arguments that should pass through
149 if arg in ['-v']:
150 compile_opts.append(arg)
151 link_opts.append(arg)
152
153 # Options with one argument that should be ignored
154 if arg in ['--param', '-arch', '-u']:
155 i += 1
156
157 # Prefix matches for the compile mode
158 if arg[:2] in ['-D', '-I', '-U', '-F']:
159 if not arg[2:]:
160 arg += args[i+1]
161 i += 1
162 compile_opts.append(arg)
163 if arg[:5] in ['-std=']:
164 compile_opts.append(arg)
165
166 # Options with one argument that should pass through
167 if arg in ['-include']:
168 compile_opts.append(arg)
169 compile_opts.append(args[i+1])
170 i += 1
171
172 # Prefix matches for the link mode
173 if arg[:2] in ['-l', '-L', '-O', '-F']:
174 if arg == '-O': arg = '-O1'
175 if arg == '-Os': arg = '-O2'
176 link_opts.append(arg)
177
178 # Options with one argument that should pass through
179 if arg in ['-framework']:
180 link_opts.append(arg)
181 link_opts.append(args[i+1])
182 i += 1
183
184 # Input files
185 if arg == '-filelist':
186 f = open(args[i+1])
187 for line in f:
188 files.append(line.strip())
189 f.close()
190 i += 1
191 if arg == '-x':
192 language = args[i+1]
193 i += 1
194 if arg[0] != '-':
195 files.append(arg)
196
197 # Output file
198 if arg == '-o':
199 output = args[i+1]
200 i += 1
201
202 i += 1
203
204 if action == 'print-prog-name':
205 # assume we can handle everything
206 print sys.argv[0]
207 return
208
209 if not files:
210 error('no input files')
211
212 if action == 'preprocess' or save_temps:
213 compile(args)
214
215 if action == 'compile' or save_temps:
216 for i, file in enumerate(files):
217 if not language:
218 language = inferlanguage(extension(file))
219 if save_temps and action != "compile":
220 # Need a temporary output file
221 coutput = changeextension(file, "o");
222 files[i] = coutput
223 elif not output:
224 coutput = changeextension(file, "o")
225 else:
226 coutput = output
227 analyze_args = [ file ]
228 if language != 'unknown':
229 analyze_args = analyze_args + [ '-x', language ]
230 analyze_args = analyze_args + compile_opts
Ted Kremenek09c2ad62008-03-31 18:25:05 +0000231 analyze(analyze_args, language, output, files, verbose, htmldir)
Ted Kremenekb0982882008-03-25 22:35:32 +0000232 compile(args)
233
234
235 if action == 'link':
236 link(args)
237# analyze(link_opts)
238
239if __name__ == '__main__':
240 main(sys.argv[1:])