Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(464)

Side by Side Diff: ppapi/generators/idl_c_header.py

Issue 7477056: Add base class for generators (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ppapi/generators/generator.py ('k') | ppapi/generators/idl_c_proto.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 """ Generator for C style prototypes and definitions """ 7 """ Generator for C style prototypes and definitions """
8 8
9 import glob 9 import glob
10 import os 10 import os
11 import sys 11 import sys
12 import subprocess 12 import subprocess
13 13
14 from idl_log import ErrOut, InfoOut, WarnOut 14 from idl_log import ErrOut, InfoOut, WarnOut
15 from idl_node import IDLAttribute, IDLNode 15 from idl_node import IDLAttribute, IDLNode
16 from idl_ast import IDLAst 16 from idl_ast import IDLAst
17 from idl_option import GetOption, Option, ParseOptions 17 from idl_option import GetOption, Option, ParseOptions
18 from idl_outfile import IDLOutFile 18 from idl_outfile import IDLOutFile
19 from idl_parser import ParseFiles 19 from idl_parser import ParseFiles
20 from idl_c_proto import CGen 20 from idl_c_proto import CGen
21 from idl_generator import Generator
21 22
22 Option('dstroot', 'Base directory of output', default='../c') 23 Option('dstroot', 'Base directory of output', default='../c')
23 Option('guard', 'Include guard prefix', default='ppapi/c') 24 Option('guard', 'Include guard prefix', default='ppapi/c')
24 Option('out', 'List of output files', default='') 25 Option('out', 'List of output files', default='')
25 26
26 cgen = CGen() 27 cgen = CGen()
27 28
28 def IDLToHeader(filenode, relpath=None, prefix=None): 29 def IDLToHeader(filenode, relpath=None, prefix=None):
29 path, name = os.path.split(filenode.GetProperty('NAME')) 30 path, name = os.path.split(filenode.GetProperty('NAME'))
30 name = os.path.splitext(name)[0] + '.h' 31 name = os.path.splitext(name)[0] + '.h'
31 if prefix: name = '%s%s' % (prefix, name) 32 if prefix: name = '%s%s' % (prefix, name)
32 if path: name = os.path.join(path, name) 33 if path: name = os.path.join(path, name)
33 if relpath: name = os.path.join(relpath, name) 34 if relpath: name = os.path.join(relpath, name)
34 return name 35 return name
35 36
36 37
37 def GenerateHeader(filenode, pref, inline=True): 38 def GenerateHeader(filenode, release, pref, inline=True):
38 name = filenode.GetProperty('NAME') 39 name = filenode.GetProperty('NAME')
39 # if name == 'pp_stdint.idl': return 40 # if name == 'pp_stdint.idl': return
40 41
41 # If we have an 'out' filter list, then check if we should output this file. 42 # If we have an 'out' filter list, then check if we should output this file.
42 outlist = GetOption('out') 43 outlist = GetOption('out')
43 if outlist: 44 if outlist:
44 outlist = outlist.split(',') 45 outlist = outlist.split(',')
45 if name not in outlist: 46 if name not in outlist:
46 return 47 return
47 48
(...skipping 11 matching lines...) Expand all
59 60
60 out.Write('%s\n' % cgen.Copyright(cright_node)) 61 out.Write('%s\n' % cgen.Copyright(cright_node))
61 out.Write('/* From %s modified %s. */\n\n'% ( 62 out.Write('/* From %s modified %s. */\n\n'% (
62 filenode.GetProperty('NAME'), filenode.GetProperty('DATETIME'))) 63 filenode.GetProperty('NAME'), filenode.GetProperty('DATETIME')))
63 out.Write('#ifndef %s\n#define %s\n\n' % (def_guard, def_guard)) 64 out.Write('#ifndef %s\n#define %s\n\n' % (def_guard, def_guard))
64 65
65 for label in filenode.GetListOf('Label'): 66 for label in filenode.GetListOf('Label'):
66 if label.GetName() == GetOption('label'): 67 if label.GetName() == GetOption('label'):
67 cgen.SetVersionMap(label) 68 cgen.SetVersionMap(label)
68 69
69 deps = filenode.GetDeps('M14') 70 deps = filenode.GetDeps(release)
70 # Generate set of includes 71 # Generate set of includes
71 includes = set([]) 72 includes = set([])
72 for dep in deps: 73 for dep in deps:
73 depfile = dep.GetProperty('FILE') 74 depfile = dep.GetProperty('FILE')
74 if depfile: 75 if depfile:
75 includes.add(depfile) 76 includes.add(depfile)
76 includes = [IDLToHeader(include, relpath=gpath) for include in includes] 77 includes = [IDLToHeader(include, relpath=gpath) for include in includes]
77 includes.append('ppapi/c/pp_macros.h') 78 includes.append('ppapi/c/pp_macros.h')
78 79
79 # Assume we need stdint if we "include" C or C++ code 80 # Assume we need stdint if we "include" C or C++ code
80 if filenode.GetListOf('Include'): 81 if filenode.GetListOf('Include'):
81 includes.append('ppapi/c/pp_stdint.h') 82 includes.append('ppapi/c/pp_stdint.h')
82 83
83 includes = sorted(set(includes)) 84 includes = sorted(set(includes))
84 cur_include = IDLToHeader(filenode, relpath=gpath) 85 cur_include = IDLToHeader(filenode, relpath=gpath)
85 for include in includes: 86 for include in includes:
86 if include == cur_include: continue 87 if include == cur_include: continue
87 out.Write('#include "%s"\n' % include) 88 out.Write('#include "%s"\n' % include)
88 89
89 # Generate all interface defines 90 # Generate all interface defines
90 release = 'M14'
91 out.Write('\n') 91 out.Write('\n')
92 for node in filenode.GetListOf('Interface'): 92 for node in filenode.GetListOf('Interface'):
93 out.Write( cgen.InterfaceDefs(node) ) 93 out.Write( cgen.InterfaceDefs(node) )
94 94
95 # Generate the @file comment 95 # Generate the @file comment
96 out.Write('%s\n' % cgen.Comment(fileinfo, prefix='*\n @file')) 96 out.Write('%s\n' % cgen.Comment(fileinfo, prefix='*\n @file'))
97 97
98 # Generate definitions. 98 # Generate definitions.
99 last_group = None 99 last_group = None
100 for node in filenode.GetChildren()[2:]: 100 for node in filenode.GetChildren()[2:]:
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 form = 'PP_COMPILE_ASSERT_STRUCT_SIZE_IN_BYTES(%s, %s);\n' 137 form = 'PP_COMPILE_ASSERT_STRUCT_SIZE_IN_BYTES(%s, %s);\n'
138 else: 138 else:
139 form = 'PP_COMPILE_ASSERT_SIZE_IN_BYTES(%s, %s);\n' 139 form = 'PP_COMPILE_ASSERT_SIZE_IN_BYTES(%s, %s);\n'
140 item += form % (name, asize[0]) 140 item += form % (name, asize[0])
141 141
142 if item: out.Write('%s%s' % (pre, item)) 142 if item: out.Write('%s%s' % (pre, item))
143 if last_group: 143 if last_group:
144 out.Write(cgen.CommentLines(['*',' @}', '']) + '\n') 144 out.Write(cgen.CommentLines(['*',' @}', '']) + '\n')
145 145
146 out.Write('#endif /* %s */\n\n' % def_guard) 146 out.Write('#endif /* %s */\n\n' % def_guard)
147 out.Close() 147 return out.Close()
148
149 class HGen(Generator):
150 def __init__(self):
151 Generator.__init__(self, 'C Header', 'cgen', 'Generate the C headers.')
152
153 def GenerateVersion(self, ast, release, options):
154 outdir = GetOption('dstroot')
155 skipList= []
156 prefix = ''
157 cfile = None
158 cnt = 0
159
160 for filenode in ast.GetListOf('File'):
161 if GetOption('verbose'):
162 print "Working on %s" % filenode
163
164 # If this file has errors, skip it
165 if filenode.GetProperty('ERRORS') > 0:
166 skipList.append(filenode)
167 continue
168
169 if GenerateHeader(filenode, release, prefix):
170 cnt = cnt + 1
171
172 for filenode in skipList:
173 errcnt = filenode.GetProperty('ERRORS')
174 ErrOut.Log('%s : Skipped because of %d errors.' % (
175 filenode.GetName(), errcnt))
176
177 if skipList:
178 return -len(skipList)
179
180 if GetOption('diff'):
181 return -cnt
182 return cnt
148 183
149 184
150 def GenerateFileTest(cfile, filenode, pref): 185 hgen = HGen()
151 tests = []
152 original = IDLToHeader(filenode, relpath='')
153 savename = IDLToHeader(filenode, relpath='', prefix=pref)
154 cfile.Write('/* Test %s */\n' % filenode.GetProperty('NAME'))
155 cfile.Write('#include "%s"\n' % original)
156 cfile.Write('#include "%s"\n' % savename)
157
158 # For all children (excluding copyright notice)
159 for node in filenode.children[1:]:
160 # Test enums by assigning all enum items to themselves. Unfortunately this
161 # will not catch cases where the '.h' has enums that the IDL does not.
162 if node.IsA('Enum'):
163 tests.append('test_%s' % node.GetProperty('NAME'))
164 cfile.Write('int test_%s() {\n' % node.GetProperty('NAME'))
165 cfile.Write(' int errors = 0;\n')
166 for enum in node.GetListOf('EnumItem'):
167 cfile.Write(' errors += VERIFY_ENUM(%s, %s%s);\n' %
168 (enum.GetProperty('NAME'), pref, enum.GetProperty('NAME')))
169 cfile.Write(' if (errors) printf("Failure in %s:%s.\\n");\n' %
170 (filenode.GetName(), node.GetName()))
171 cfile.Write(' return errors;\n}\n\n')
172 continue
173
174 # Use a structure asignment to verify equivilency
175 if node.IsA('Interface', 'Struct'):
176 tests.append('test_%s' % node.GetName())
177 rtype1 = cgen.GetTypeName(node)
178 rtype2 = cgen.GetTypeName(node, prefix='tst_')
179 cfile.Write('int test_%s() {\n' % node.GetName())
180 cfile.Write(' int errors = 0;\n');
181 cmp_structs = ' %s A;\n %s B;\n' % (rtype1, rtype2)
182 cfile.Write(cmp_structs)
183 cfile.Write(' memset(&A, 0, sizeof(A));\n')
184 cfile.Write(' memset(&B, 1, sizeof(B));\n')
185 for member in node.GetListOf('Member', 'Function'):
186 if member.GetOneOf('Array'):
187 cfile.Write(' memcpy(A.%s, B.%s, sizeof(A.%s));\n' %
188 (member.GetName(), member.GetName(), member.GetName()))
189 else:
190 cfile.Write(' A.%s = B.%s;\n' % (member.GetName(), member.GetName()))
191 cfile.Write(' errors += (sizeof(A) != sizeof(B)) ? 1 : 0;\n')
192 cfile.Write(' errors += (memcmp(&A, &B, sizeof(A))) ? 1 : 0;\n')
193 cfile.Write(' return (sizeof(A) == sizeof(B));\n}\n')
194 continue
195
196 cfile.Write('\n\n')
197 return tests
198
199 def GenerateBaseTest(cfile):
200 for inc in ['<stdio.h>','<string.h>','"pp_stdint.h"']:
201 cfile.Write('#include %s\n' % inc)
202 cfile.Write('\n')
203 cfile.Write('#define VERIFY_ENUM(orig, idl) Check(#orig, orig, idl)\n\n')
204 cfile.Write('int Check(const char *name, int v1, int v2) {\n')
205 cfile.Write(' if (v1 == v2) return 0;\n')
206 cfile.Write(' printf("Mismatch enum %s : %d vs %d\\n", name, v1, v2);\n')
207 cfile.Write(' return 1;\n}\n\n')
208
209 186
210 def Main(args): 187 def Main(args):
211 filenames = ParseOptions(args) 188 # Default invocation will verify the golden files are unchanged.
189 if not args:
190 args = ['--wnone', '--diff', '--test', '--dstroot=.']
191
192 ParseOptions(args)
193 idldir = os.path.split(sys.argv[0])[0]
194 idldir = os.path.join(idldir, 'test_cgen', '*.idl')
195 filenames = glob.glob(idldir)
196
212 ast = ParseFiles(filenames) 197 ast = ParseFiles(filenames)
213 testFuncs = [] 198 return hgen.GenerateVersion(ast, 'M14', {})
214 skipList = []
215
216 outdir = GetOption('dstroot')
217
218 if GetOption('test'):
219 prefix = 'tst_'
220 cfile = IDLOutFile(os.path.join(outdir, 'test.c'))
221 GenerateBaseTest(cfile)
222 else:
223 prefix = ''
224 cfile = None
225
226 for filenode in ast.GetListOf('File'):
227 if GetOption('verbose'):
228 print "Working on %s" % filenode
229
230 # If this file has errors, skip it
231 if filenode.GetProperty('ERRORS') > 0:
232 skipList.append(filenode)
233 continue
234
235 GenerateHeader(filenode, prefix, inline=not cfile)
236 if cfile: GenerateFileTest(cfile, filenode, prefix)
237
238 if cfile:
239 cfile.Write('int main(int argc, const char *args[]) {\n')
240 cfile.Write(' int errors = 0;\n');
241 for testname in testFuncs:
242 cfile.Write(' errors += %s();\n' % testname)
243
244 cfile.Write(' printf("Found %d error(s) in the IDL.\\n", errors);\n')
245 cfile.Write(' return errors;\n}\n\n')
246 cfile.Close()
247
248 # TODO(noelallen) Add a standard test
249 if not skipList:
250 args = ['gcc', '-o', 'tester', '%s/test.c' % outdir, '-I%s' % outdir,
251 '-I../c', '-I../..', '-DPPAPI_INSTANCE_REMOVE_SCRIPTING']
252 InfoOut.Log('Running: %s' % ' '.join(args))
253 ret = subprocess.call(args)
254 if ret:
255 ErrOut.Log('Failed to compile.')
256 return -1
257 InfoOut.Log('Running: ./tester')
258 ret = subprocess.call('./tester')
259 if ret > 0:
260 ErrOut.Log('Found %d errors.' % ret)
261 return ret
262 InfoOut.Log('Success!')
263 return 0
264
265 for filenode in skipList:
266 errcnt = filenode.GetProperty('ERRORS')
267 ErrOut.Log('%s : Skipped because of %d errors.' % (
268 filenode.GetName(), errcnt))
269
270 if not skipList:
271 InfoOut.Log('Processed %d files.' % len(ast.GetListOf('File')))
272 return len(skipList)
273 199
274 if __name__ == '__main__': 200 if __name__ == '__main__':
275 sys.exit(Main(sys.argv[1:])) 201 retval = Main(sys.argv[1:])
202 sys.exit(retval)
276 203
OLDNEW
« no previous file with comments | « ppapi/generators/generator.py ('k') | ppapi/generators/idl_c_proto.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698