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

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

Issue 12300042: Update idlsync.py to pull in dependencies required for chrome api generation. (Closed) Base URL: git://github.com/dart-lang/bleeding_edge.git@master
Patch Set: From another checkout Created 7 years, 9 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
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """ Generator for C style prototypes and definitions """
7
8 import glob
9 import os
10 import re
11 import sys
12
13 from idl_log import ErrOut, InfoOut, WarnOut
14 from idl_node import IDLAttribute, IDLNode
15 from idl_ast import IDLAst
16 from idl_option import GetOption, Option, ParseOptions
17 from idl_outfile import IDLOutFile
18 from idl_parser import ParseFiles
19 from idl_c_proto import CGen, GetNodeComments, CommentLines, Comment
20 from idl_generator import Generator, GeneratorByFile
21 from idl_visitor import IDLVisitor
22
23 Option('dstroot', 'Base directory of output', default=os.path.join('..', 'c'))
24 Option('guard', 'Include guard prefix', default=os.path.join('ppapi', 'c'))
25
26
27 #
28 # PrototypeResolver
29 #
30 # A specialized visitor which traverses the AST, building a mapping of
31 # Release names to Versions numbers and calculating a min version.
32 # The mapping is applied to the File nodes within the AST.
33 #
34 class ProtoResolver(IDLVisitor):
35 def __init__(self):
36 IDLVisitor.__init__(self)
37 self.struct_map = {}
38 self.interface_map = {}
39
40 def Arrive(self, node, ignore):
41 if node.IsA('Member') and node.GetProperty('ref'):
42 typeref = node.typelist.GetReleases()[0]
43 if typeref.IsA('Struct'):
44 nodelist = self.struct_map.get(typeref.GetName(), [])
45 nodelist.append(node)
46 self.struct_map[typeref.GetName()] = nodelist
47
48 if node.IsA('Param'):
49 typeref = node.typelist.GetReleases()[0]
50 if typeref.IsA('Interface'):
51 nodelist = self.struct_map.get(typeref.GetName(), [])
52 nodelist.append(node)
53 self.interface_map[typeref.GetName()] = nodelist
54
55 return None
56
57
58 def GetPathFromNode(filenode, relpath=None, ext=None):
59 path, name = os.path.split(filenode.GetProperty('NAME'))
60 if ext: name = os.path.splitext(name)[0] + ext
61 if path: name = os.path.join(path, name)
62 if relpath: name = os.path.join(relpath, name)
63 name = os.path.normpath(name)
64 return name
65
66
67 def GetHeaderFromNode(filenode, relpath=None):
68 return GetPathFromNode(filenode, relpath, ext='.h')
69
70
71 def WriteGroupMarker(out, node, last_group):
72 # If we are part of a group comment marker...
73 if last_group and last_group != node.cls:
74 pre = CommentLines(['*',' @}', '']) + '\n'
75 else:
76 pre = '\n'
77
78 if node.cls in ['Typedef', 'Interface', 'Struct', 'Enum']:
79 if last_group != node.cls:
80 pre += CommentLines(['*',' @addtogroup %ss' % node.cls, ' @{', ''])
81 last_group = node.cls
82 else:
83 last_group = None
84 out.Write(pre)
85 return last_group
86
87
88 def GenerateHeader(out, filenode, releases):
89 cgen = CGen()
90 pref = ''
91 do_comments = True
92
93 # Generate definitions.
94 last_group = None
95 top_types = ['Typedef', 'Interface', 'Struct', 'Enum', 'Inline']
96 for node in filenode.GetListOf(*top_types):
97 # Skip if this node is not in this release
98 if not node.InReleases(releases):
99 print "Skiping %s" % node
100 continue
101
102 # End/Start group marker
103 if do_comments:
104 last_group = WriteGroupMarker(out, node, last_group)
105
106 if node.IsA('Inline'):
107 item = node.GetProperty('VALUE')
108 # If 'C++' use __cplusplus wrapper
109 if node.GetName() == 'cc':
110 item = '#ifdef __cplusplus\n%s\n#endif /* __cplusplus */\n\n' % item
111 # If not C++ or C, then skip it
112 elif not node.GetName() == 'c':
113 continue
114 if item: out.Write(item)
115 continue
116
117 #
118 # Otherwise we are defining a file level object, so generate the
119 # correct document notation.
120 #
121 item = cgen.Define(node, releases, prefix=pref, comment=True)
122 if not item: continue
123 asize = node.GetProperty('assert_size()')
124 if asize:
125 name = '%s%s' % (pref, node.GetName())
126 if node.IsA('Struct'):
127 form = 'PP_COMPILE_ASSERT_STRUCT_SIZE_IN_BYTES(%s, %s);\n'
128 elif node.IsA('Enum'):
129 if node.GetProperty('notypedef'):
130 form = 'PP_COMPILE_ASSERT_ENUM_SIZE_IN_BYTES(%s, %s);\n'
131 else:
132 form = 'PP_COMPILE_ASSERT_SIZE_IN_BYTES(%s, %s);\n'
133 else:
134 form = 'PP_COMPILE_ASSERT_SIZE_IN_BYTES(%s, %s);\n'
135 item += form % (name, asize[0])
136
137 if item: out.Write(item)
138 if last_group:
139 out.Write(CommentLines(['*',' @}', '']) + '\n')
140
141
142 class HGen(GeneratorByFile):
143 def __init__(self):
144 Generator.__init__(self, 'C Header', 'cgen', 'Generate the C headers.')
145
146 def GenerateFile(self, filenode, releases, options):
147 savename = GetHeaderFromNode(filenode, GetOption('dstroot'))
148 my_min, my_max = filenode.GetMinMax(releases)
149 if my_min > releases[-1] or my_max < releases[0]:
150 if os.path.isfile(savename):
151 print "Removing stale %s for this range." % filenode.GetName()
152 os.remove(os.path.realpath(savename))
153 return False
154
155 out = IDLOutFile(savename)
156 self.GenerateHead(out, filenode, releases, options)
157 self.GenerateBody(out, filenode, releases, options)
158 self.GenerateTail(out, filenode, releases, options)
159 return out.Close()
160
161 def GenerateHead(self, out, filenode, releases, options):
162 __pychecker__ = 'unusednames=options'
163
164 proto = ProtoResolver()
165 proto.Visit(filenode, None)
166
167 cgen = CGen()
168 gpath = GetOption('guard')
169 def_guard = GetHeaderFromNode(filenode, relpath=gpath)
170 def_guard = def_guard.replace(os.sep,'_').replace('.','_').upper() + '_'
171
172 cright_node = filenode.GetChildren()[0]
173 assert(cright_node.IsA('Copyright'))
174 fileinfo = filenode.GetChildren()[1]
175 assert(fileinfo.IsA('Comment'))
176
177 out.Write('%s\n' % cgen.Copyright(cright_node))
178
179 # Wrap the From ... modified ... comment if it would be >80 characters.
180 from_text = 'From %s' % GetPathFromNode(filenode).replace(os.sep, '/')
181 modified_text = 'modified %s.' % (
182 filenode.GetProperty('DATETIME'))
183 if len(from_text) + len(modified_text) < 74:
184 out.Write('/* %s %s */\n\n' % (from_text, modified_text))
185 else:
186 out.Write('/* %s,\n * %s\n */\n\n' % (from_text, modified_text))
187
188 out.Write('#ifndef %s\n#define %s\n\n' % (def_guard, def_guard))
189 # Generate set of includes
190
191 deps = set()
192 for release in releases:
193 deps |= filenode.GetDeps(release)
194
195 includes = set([])
196 for dep in deps:
197 depfile = dep.GetProperty('FILE')
198 if depfile:
199 includes.add(depfile)
200 includes = [GetHeaderFromNode(
201 include, relpath=gpath).replace(os.sep, '/') for include in includes]
202 includes.append('ppapi/c/pp_macros.h')
203
204 # Assume we need stdint if we "include" C or C++ code
205 if filenode.GetListOf('Include'):
206 includes.append('ppapi/c/pp_stdint.h')
207
208 includes = sorted(set(includes))
209 cur_include = GetHeaderFromNode(filenode,
210 relpath=gpath).replace(os.sep, '/')
211 for include in includes:
212 if include == cur_include: continue
213 out.Write('#include "%s"\n' % include)
214
215 # Generate Prototypes
216 if proto.struct_map:
217 out.Write('\n/* Struct prototypes */\n')
218 for struct in proto.struct_map:
219 out.Write('struct %s;\n' % struct)
220
221 # Create a macro for the highest available release number.
222 if filenode.GetProperty('NAME').endswith('pp_macros.idl'):
223 releasestr = ' '.join(releases)
224 if releasestr:
225 release_numbers = re.findall('[\d\_]+', releasestr)
226 release = re.findall('\d+', release_numbers[-1])[0]
227 if release:
228 out.Write('\n#define PPAPI_RELEASE %s\n' % release)
229
230 # Generate all interface defines
231 out.Write('\n')
232 for node in filenode.GetListOf('Interface'):
233 idefs = ''
234 macro = cgen.GetInterfaceMacro(node)
235 unique = node.GetUniqueReleases(releases)
236
237 # Skip this interface if there are no matching versions
238 if not unique: continue
239
240 for rel in unique:
241 version = node.GetVersion(rel)
242 name = cgen.GetInterfaceString(node, version)
243 strver = str(version).replace('.', '_')
244 idefs += cgen.GetDefine('%s_%s' % (macro, strver), '"%s"' % name)
245 idefs += cgen.GetDefine(macro, '%s_%s' % (macro, strver)) + '\n'
246 out.Write(idefs)
247
248 # Generate the @file comment
249 out.Write('%s\n' % Comment(fileinfo, prefix='*\n @file'))
250
251 def GenerateBody(self, out, filenode, releases, options):
252 __pychecker__ = 'unusednames=options'
253 GenerateHeader(out, filenode, releases)
254
255 def GenerateTail(self, out, filenode, releases, options):
256 __pychecker__ = 'unusednames=options,releases'
257 gpath = GetOption('guard')
258 def_guard = GetPathFromNode(filenode, relpath=gpath, ext='.h')
259 def_guard = def_guard.replace(os.sep,'_').replace('.','_').upper() + '_'
260 out.Write('#endif /* %s */\n\n' % def_guard)
261
262
263 hgen = HGen()
264
265 def main(args):
266 # Default invocation will verify the golden files are unchanged.
267 failed = 0
268 if not args:
269 args = ['--wnone', '--diff', '--test', '--dstroot=.']
270
271 ParseOptions(args)
272
273 idldir = os.path.split(sys.argv[0])[0]
274 idldir = os.path.join(idldir, 'test_cgen', '*.idl')
275 filenames = glob.glob(idldir)
276 ast = ParseFiles(filenames)
277 if hgen.GenerateRelease(ast, 'M14', {}):
278 print "Golden file for M14 failed."
279 failed = 1
280 else:
281 print "Golden file for M14 passed."
282
283
284 idldir = os.path.split(sys.argv[0])[0]
285 idldir = os.path.join(idldir, 'test_cgen_range', '*.idl')
286 filenames = glob.glob(idldir)
287
288 ast = ParseFiles(filenames)
289 if hgen.GenerateRange(ast, ['M13', 'M14', 'M15'], {}):
290 print "Golden file for M13-M15 failed."
291 failed =1
292 else:
293 print "Golden file for M13-M15 passed."
294
295 return failed
296
297 if __name__ == '__main__':
298 sys.exit(main(sys.argv[1:]))
299
OLDNEW
« no previous file with comments | « third_party/chrome/ppapi/generators/idl_ast.py ('k') | third_party/chrome/ppapi/generators/idl_c_proto.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698