source: mainline/tools/checkers/vcc.py@ 5b8016d

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 5b8016d was 09a0bd4a, checked in by Martin Decky <martin@…>, 15 years ago

initial properties annotation and verification support
(does not do much yet, but also does not stand in the way)

  • Property mode set to 100755
File size: 5.3 KB
Line 
1#!/usr/bin/env python
2#
3# Copyright (c) 2010 Martin Decky
4# Copyright (c) 2010 Ondrej Sery
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10#
11# - Redistributions of source code must retain the above copyright
12# notice, this list of conditions and the following disclaimer.
13# - Redistributions in binary form must reproduce the above copyright
14# notice, this list of conditions and the following disclaimer in the
15# documentation and/or other materials provided with the distribution.
16# - The name of the author may not be used to endorse or promote products
17# derived from this software without specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29#
30"""
31Wrapper for Vcc checker
32"""
33
34import sys
35import os
36import subprocess
37import jobfile
38import re
39
40jobs = [
41 "kernel/kernel.job"
42]
43
44re_attribute = re.compile("__attribute__\s*\(\(.*\)\)")
45re_va_list = re.compile("__builtin_va_list")
46
47def usage(prname):
48 "Print usage syntax"
49 print prname + " <ROOT> [VCC_PATH]"
50
51def cygpath(upath):
52 "Convert Unix (Cygwin) path to Windows path"
53
54 return subprocess.Popen(['cygpath', '--windows', '--absolute', upath], stdout = subprocess.PIPE).communicate()[0].strip()
55
56def preprocess(srcfname, tmpfname, base, options):
57 "Preprocess source using GCC preprocessor and compatibility tweaks"
58
59 args = ['gcc', '-E']
60 args.extend(options.split())
61 args.extend(['-DCONFIG_VERIFY_VCC=1', srcfname])
62
63 # Change working directory
64
65 cwd = os.getcwd()
66 os.chdir(base)
67
68 preproc = subprocess.Popen(args, stdout = subprocess.PIPE).communicate()[0]
69
70 tmpf = file(tmpfname, "w")
71
72 tmpf.write("__specification(const char * const \\declspec_atomic_inline;)\n\n");
73
74 tmpf.write("#define __spec_attr(key, value) \\\n");
75 tmpf.write(" __declspec(System.Diagnostics.Contracts.CodeContract.StringVccAttr, \\\n");
76 tmpf.write(" key, value)\n\n");
77
78 for line in preproc.splitlines():
79
80 # Ignore preprocessor directives
81
82 if (line.startswith('#')):
83 continue
84
85 # Remove __attribute__((.*)) GCC extension
86
87 line = re.sub(re_attribute, "", line)
88
89 # Ignore unsupported __builtin_va_list type
90 # (a better solution replacing __builrin_va_list with
91 # an emulated implementation is needed)
92
93 line = re.sub(re_va_list, "void *", line)
94
95 tmpf.write("%s\n" % line)
96
97 tmpf.close()
98
99 os.chdir(cwd)
100
101 return True
102
103def vcc(vcc_path, root, job):
104 "Run Vcc on a jobfile"
105
106 # Parse jobfile
107
108 inname = os.path.join(root, job)
109
110 if (not os.path.isfile(inname)):
111 print "Unable to open %s" % inname
112 print "Did you run \"make precheck\" on the source tree?"
113 return False
114
115 inf = file(inname, "r")
116 records = inf.read().splitlines()
117 inf.close()
118
119 for record in records:
120 arg = jobfile.parse_arg(record)
121 if (not arg):
122 return False
123
124 if (len(arg) < 6):
125 print "Not enought jobfile record arguments"
126 return False
127
128 srcfname = arg[0]
129 tgtfname = arg[1]
130 tool = arg[2]
131 category = arg[3]
132 base = arg[4]
133 options = arg[5]
134
135 srcfqname = os.path.join(base, srcfname)
136 if (not os.path.isfile(srcfqname)):
137 print "Source %s not found" % srcfqname
138 return False
139
140 tmpfname = "%s.preproc" % srcfname
141 tmpfqname = os.path.join(base, tmpfname)
142
143 vccfname = "%s.i" % srcfname
144 vccfqname = os.path.join(base, vccfname);
145
146 # Only C files are interesting for us
147 if (tool != "cc"):
148 continue
149
150 # Preprocess sources
151
152 if (not preprocess(srcfname, tmpfname, base, options)):
153 return False
154
155 # Run Vcc
156 print " -- %s --" % srcfname
157 retval = subprocess.Popen([vcc_path, '/pointersize:32', cygpath(tmpfqname)]).wait()
158
159 if (retval != 0):
160 return False
161
162 # Cleanup, but only if verification was successful
163 # (to be able to examine the preprocessed file)
164
165 if (os.path.isfile(tmpfqname)):
166 os.remove(tmpfqname)
167 os.remove(vccfqname)
168
169 return True
170
171def main():
172 if (len(sys.argv) < 2):
173 usage(sys.argv[0])
174 return
175
176 rootdir = os.path.abspath(sys.argv[1])
177 if (len(sys.argv) > 2):
178 vcc_path = sys.argv[2]
179 else:
180 vcc_path = "/cygdrive/c/Program Files (x86)/Microsoft Research/Vcc/Binaries/vcc"
181
182 if (not os.path.isfile(vcc_path)):
183 print "%s is not a binary." % vcc_path
184 print "Please supply the full Cygwin path to Vcc as the second argument."
185 return
186
187 config = os.path.join(rootdir, "HelenOS.config")
188
189 if (not os.path.isfile(config)):
190 print "%s not found." % config
191 print "Please specify the path to HelenOS build tree root as the first argument."
192 return
193
194 for job in jobs:
195 if (not vcc(vcc_path, rootdir, job)):
196 print
197 print "Failed job: %s" % job
198 return
199
200 print
201 print "All jobs passed"
202
203if __name__ == '__main__':
204 main()
Note: See TracBrowser for help on using the repository browser.