OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # | 2 # |
3 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 3 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 import sys | 7 import sys |
8 | 8 |
9 from idl_log import ErrOut, InfoOut, WarnOut | 9 from idl_log import ErrOut, InfoOut, WarnOut |
10 from idl_option import GetOption, Option, ParseOptions | 10 from idl_option import GetOption, Option, ParseOptions |
| 11 from idl_parser import ParseFiles |
11 | 12 |
12 GeneratorList = [] | 13 GeneratorList = [] |
13 | 14 |
14 Option('release', 'Which release to generate.', default='') | 15 Option('release', 'Which release to generate.', default='') |
15 Option('range', 'Which ranges in the form of MIN,MAX.', default='start,end') | 16 Option('range', 'Which ranges in the form of MIN,MAX.', default='start,end') |
16 | 17 |
17 | 18 |
18 # | 19 # |
19 # Generator | 20 # Generator |
20 # | 21 # |
(...skipping 11 matching lines...) Expand all Loading... |
32 # NOTE: Generators still have access to global options | 33 # NOTE: Generators still have access to global options |
33 | 34 |
34 class Generator(object): | 35 class Generator(object): |
35 def __init__(self, name, sname, desc): | 36 def __init__(self, name, sname, desc): |
36 self.name = name | 37 self.name = name |
37 self.run_switch = Option(sname, desc) | 38 self.run_switch = Option(sname, desc) |
38 self.opt_switch = Option(sname + '_opt', 'Options for %s.' % sname, | 39 self.opt_switch = Option(sname + '_opt', 'Options for %s.' % sname, |
39 default='') | 40 default='') |
40 GeneratorList.append(self) | 41 GeneratorList.append(self) |
41 self.errors = 0 | 42 self.errors = 0 |
| 43 self.skip_list = [] |
42 | 44 |
43 def Error(self, msg): | 45 def Error(self, msg): |
44 ErrOut.Log('Error %s : %s' % (self.name, msg)) | 46 ErrOut.Log('Error %s : %s' % (self.name, msg)) |
45 self.errors += 1 | 47 self.errors += 1 |
46 | 48 |
47 def GetRunOptions(self): | 49 def GetRunOptions(self): |
48 options = {} | 50 options = {} |
49 option_list = self.opt_switch.Get() | 51 option_list = self.opt_switch.Get() |
50 if option_list: | 52 if option_list: |
51 option_list = option_list.split(',') | 53 option_list = option_list.split(',') |
52 for opt in option_list: | 54 for opt in option_list: |
53 offs = opt.find('=') | 55 offs = opt.find('=') |
54 if offs > 0: | 56 if offs > 0: |
55 options[opt[:offs]] = opt[offs+1:] | 57 options[opt[:offs]] = opt[offs+1:] |
56 else: | 58 else: |
57 options[opt] = True | 59 options[opt] = True |
58 return options | 60 return options |
59 if self.run_switch.Get(): | 61 if self.run_switch.Get(): |
60 return options | 62 return options |
61 return None | 63 return None |
62 | 64 |
63 def Generate(self, ast, options): | 65 def Generate(self, ast, options): |
64 self.errors = 0 | 66 self.errors = 0 |
65 | 67 |
66 rangestr = GetOption('range') | 68 rangestr = GetOption('range') |
67 releasestr = GetOption('release') | 69 releasestr = GetOption('release') |
68 | 70 |
69 print "Found releases: %s" % ast.releases | 71 print "Found releases: %s" % ast.releases |
70 | 72 |
| 73 # Generate list of files to ignore due to errors |
| 74 for filenode in ast.GetListOf('File'): |
| 75 # If this file has errors, skip it |
| 76 if filenode.GetProperty('ERRORS') > 0: |
| 77 self.skip_list.append(filenode) |
| 78 continue |
| 79 |
71 # Check for a range option which over-rides a release option | 80 # Check for a range option which over-rides a release option |
72 if not releasestr and rangestr: | 81 if not releasestr and rangestr: |
73 range_list = rangestr.split(',') | 82 range_list = rangestr.split(',') |
74 if len(range_list) != 2: | 83 if len(range_list) != 2: |
75 self.Error('Failed to generate for %s, incorrect range: "%s"' % | 84 self.Error('Failed to generate for %s, incorrect range: "%s"' % |
76 (self.name, rangestr)) | 85 (self.name, rangestr)) |
77 else: | 86 else: |
78 vmin = range_list[0] | 87 vmin = range_list[0] |
79 vmax = range_list[1] | 88 vmax = range_list[1] |
80 | 89 |
81 # Generate 'start' and 'end' represent first and last found. | 90 # Generate 'start' and 'end' represent first and last found. |
82 if vmin == 'start': | 91 if vmin == 'start': |
83 vmin = ast.releases[0] | 92 vmin = ast.releases[0] |
84 if vmax == 'end': | 93 if vmax == 'end': |
85 vmax = ast.releases[-1] | 94 vmax = ast.releases[-1] |
86 | 95 |
87 vmin = ast.releases.index(vmin) | 96 vmin = ast.releases.index(vmin) |
88 vmax = ast.releases.index(vmax) + 1 | 97 vmax = ast.releases.index(vmax) + 1 |
89 range = ast.releases[vmin:vmax] | 98 releases = ast.releases[vmin:vmax] |
90 InfoOut.Log('Generate range %s of %s.' % (range, self.name)) | 99 InfoOut.Log('Generate range %s of %s.' % (range, self.name)) |
91 ret = self.GenerateRange(ast, range, options) | 100 ret = self.GenerateRange(ast, releases, options) |
92 if ret < 0: | 101 if ret < 0: |
93 self.Error('Failed to generate range %s : %s.' %(vmin, vmax)) | 102 self.Error('Failed to generate range %s : %s.' %(vmin, vmax)) |
94 else: | 103 else: |
95 InfoOut.Log('%s wrote %d files.' % (self.name, ret)) | 104 InfoOut.Log('%s wrote %d files.' % (self.name, ret)) |
96 # Otherwise this should be a single release generation | 105 # Otherwise this should be a single release generation |
97 else: | 106 else: |
98 if releasestr: | 107 if releasestr: |
99 InfoOut.Log('Generate release %s of %s.' % (releasestr, self.name)) | 108 InfoOut.Log('Generate release %s of %s.' % (releasestr, self.name)) |
100 ret = self.GenerateRelease(ast, releasestr, options) | 109 ret = self.GenerateRelease(ast, releasestr, options) |
101 if ret < 0: | 110 if ret < 0: |
102 self.Error('Failed to generate release %s.' % releasestr) | 111 self.Error('Failed to generate release %s.' % releasestr) |
103 else: | 112 else: |
104 InfoOut.Log('%s wrote %d files.' % (self.name, ret)) | 113 InfoOut.Log('%s wrote %d files.' % (self.name, ret)) |
105 | 114 |
106 else: | 115 else: |
107 self.Error('No range or release specified for %s.' % releasestr) | 116 self.Error('No range or release specified for %s.' % releasestr) |
108 return self.errors | 117 return self.errors |
109 | 118 |
110 def GenerateRelease(self, ast, release, options): | 119 def GenerateRelease(self, ast, release, options): |
111 __pychecker__ = 'unusednames=ast,release,options' | 120 __pychecker__ = 'unusednames=ast,release,options' |
112 self.Error("Undefined release generator.") | 121 self.Error("Undefined release generator.") |
113 return 0 | 122 return 0 |
114 | 123 |
115 def GenerateRange(self, ast, vmin, vmax, options): | 124 def GenerateRange(self, ast, releases, options): |
116 __pychecker__ = 'unusednames=ast,vmin,vmax,options' | 125 __pychecker__ = 'unusednames=ast,releases,options' |
117 self.Error("Undefined range generator.") | 126 self.Error("Undefined range generator.") |
118 return 0 | 127 return 0 |
119 | 128 |
120 @staticmethod | 129 @staticmethod |
121 def Run(ast): | 130 def Run(ast): |
122 fail_count = 0 | 131 fail_count = 0 |
123 | 132 |
124 # Check all registered generators if they should run. | 133 # Check all registered generators if they should run. |
125 for gen in GeneratorList: | 134 for gen in GeneratorList: |
126 options = gen.GetRunOptions() | 135 options = gen.GetRunOptions() |
127 if options is not None: | 136 if options is not None: |
128 if gen.Generate(ast, options): | 137 if gen.Generate(ast, options): |
129 fail_count += 1 | 138 fail_count += 1 |
130 return fail_count | 139 return fail_count |
131 | 140 |
132 | 141 |
133 # | 142 # |
134 # GeneratorByFile | 143 # GeneratorByFile |
135 # | 144 # |
136 # A subclass of Generator for use of generators which have a one to one | 145 # A subclass of Generator for use of generators which have a one to one |
137 # mapping between IDL sources and output files. To use, derive a new class | 146 # mapping between IDL sources and output files. To use, derive a new class |
138 # which defines: | 147 # which defines: |
139 # | 148 # |
140 # GetOutFile - Returns an IDLOutFile based on filenode (name) and options | 149 # GetOutFile - Returns an IDLOutFile based on filenode (name) and options |
141 # GenerateHead - Writes the first part of the file (includes, etc...) | 150 # GenerateHead - Writes the first part of the file (includes, etc...) |
142 # GenerateBody - Writes the body of the file (definitions) | 151 # GenerateBody - Writes the body of the file (definitions) |
143 # GenerateTail - Writes the end of the file (closing include guard, etc...) | 152 # GenerateTail - Writes the end of the file (closing include guard, etc...) |
144 # | 153 # |
145 class GeneratorByFile(Generator): | 154 class GeneratorByFile(Generator): |
| 155 def GenerateFile(self, filenode, releases, options): |
| 156 __pychecker__ = 'unusednames=filenode,releases,options' |
| 157 self.Error("Undefined release generator.") |
| 158 return 0 |
| 159 |
146 def GenerateRelease(self, ast, release, options): | 160 def GenerateRelease(self, ast, release, options): |
147 return self.GenerateRange(ast, [release], options) | 161 return self.GenerateRange(ast, [release], options) |
148 | 162 |
149 def GenerateRange(self, ast, releases, options): | 163 def GenerateRange(self, ast, releases, options): |
150 # Get list of out files | 164 # Get list of out files |
151 outlist = GetOption('out') | 165 outlist = GetOption('out') |
152 if outlist: outlist = outlist.split(',') | 166 if outlist: outlist = outlist.split(',') |
153 | 167 |
154 skipList = [] | 168 skipList = [] |
155 cnt = 0 | 169 cnt = 0 |
156 for filenode in ast.GetListOf('File'): | 170 for filenode in ast.GetListOf('File'): |
| 171 # Ignore files with errors |
| 172 if filenode in self.skip_list: |
| 173 continue |
| 174 |
157 # Skip this file if not required | 175 # Skip this file if not required |
158 if outlist and filenode.GetName() not in outlist: | 176 if outlist and filenode.GetName() not in outlist: |
159 continue | 177 continue |
160 | 178 |
161 # If this file has errors, skip it | 179 # Create the output file and increment out count if there was a delta |
162 if filenode.GetProperty('ERRORS') > 0: | 180 if self.GenerateFile(filenode, releases, options): |
163 skipList.append(filenode) | 181 cnt = cnt + 1 |
164 continue | |
165 | |
166 # Create output file | |
167 out = self.GetOutFile(filenode, options) | |
168 self.GenerateHead(out, filenode, releases, options) | |
169 self.GenerateBody(out, filenode, releases, options) | |
170 self.GenerateTail(out, filenode, releases, options) | |
171 | |
172 if out.Close(): cnt = cnt + 1 | |
173 | 182 |
174 for filenode in skipList: | 183 for filenode in skipList: |
175 errcnt = filenode.GetProperty('ERRORS') | 184 errcnt = filenode.GetProperty('ERRORS') |
176 ErrOut.Log('%s : Skipped because of %d errors.' % ( | 185 ErrOut.Log('%s : Skipped because of %d errors.' % ( |
177 filenode.GetName(), errcnt)) | 186 filenode.GetName(), errcnt)) |
178 | 187 |
179 if skipList: | 188 if skipList: |
180 return -len(skipList) | 189 return -len(skipList) |
181 | 190 |
182 if GetOption('diff'): | 191 if GetOption('diff'): |
(...skipping 18 matching lines...) Expand all Loading... |
201 check_item = check_map[item] | 210 check_item = check_map[item] |
202 option_item = options.get(item, None) | 211 option_item = options.get(item, None) |
203 if check_item != option_item: | 212 if check_item != option_item: |
204 print 'Option %s is %s, expecting %s' % (item, option_item, check_item) | 213 print 'Option %s is %s, expecting %s' % (item, option_item, check_item) |
205 check_release = 0 | 214 check_release = 0 |
206 | 215 |
207 if release != 'M14': | 216 if release != 'M14': |
208 check_release = 0 | 217 check_release = 0 |
209 return check_release == 1 | 218 return check_release == 1 |
210 | 219 |
211 def GenerateRange(self, ast, vmin, vmax, options = {}): | 220 def GenerateRange(self, ast, releases, options): |
212 __pychecker__ = 'unusednames=ast,vmin,vmax,options' | 221 __pychecker__ = 'unusednames=ast,releases,options' |
213 global check_range | 222 global check_range |
214 check_range = 1 | 223 check_range = 1 |
215 return True | 224 return True |
216 | 225 |
217 def Test(): | 226 def Test(): |
218 __pychecker__ = 'unusednames=args' | 227 __pychecker__ = 'unusednames=args' |
219 global check_release | 228 global check_release |
220 global check_range | 229 global check_range |
221 | 230 |
222 ParseOptions(['--testgen_opt=so_long,MyOpt=XYZ,goodbye']) | 231 ParseOptions(['--testgen_opt=so_long,MyOpt=XYZ,goodbye']) |
(...skipping 14 matching lines...) Expand all Loading... |
237 if check_release != 0 or check_range != 1: | 246 if check_release != 0 or check_range != 1: |
238 print 'Gererate range: Failed to run.\n' | 247 print 'Gererate range: Failed to run.\n' |
239 return -1 | 248 return -1 |
240 | 249 |
241 print 'Generator test: Pass' | 250 print 'Generator test: Pass' |
242 return 0 | 251 return 0 |
243 | 252 |
244 | 253 |
245 def Main(args): | 254 def Main(args): |
246 if not args: return Test() | 255 if not args: return Test() |
247 | |
248 filenames = ParseOptions(args) | 256 filenames = ParseOptions(args) |
249 ast = ParseFiles(filenames) | 257 ast = ParseFiles(filenames) |
250 | 258 |
251 return Generator.Run(ast) | 259 return Generator.Run(ast) |
252 | 260 |
253 | 261 |
254 if __name__ == '__main__': | 262 if __name__ == '__main__': |
255 GeneratorReleaseTest('Test Gen', 'testgen', 'Generator Class Test.') | 263 GeneratorReleaseTest('Test Gen', 'testgen', 'Generator Class Test.') |
256 sys.exit(Main(sys.argv[1:])) | 264 sys.exit(Main(sys.argv[1:])) |
257 | 265 |
OLD | NEW |