Remove extra line from unit_tests.isolate
[chromium-blink-merge.git] / ppapi / generators / idl_c_header.py
blobd6d897efb6b30ed1ae7b3fbbc7806f7105653fab
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.
6 """ Generator for C style prototypes and definitions """
8 import glob
9 import os
10 import re
11 import sys
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
22 Option('dstroot', 'Base directory of output', default=os.path.join('..', 'c'))
23 Option('guard', 'Include guard prefix', default=os.path.join('ppapi', 'c'))
24 Option('out', 'List of output files', default='')
27 def GetOutFileName(filenode, relpath=None, prefix=None):
28 path, name = os.path.split(filenode.GetProperty('NAME'))
29 name = os.path.splitext(name)[0] + '.h'
30 if prefix: name = '%s%s' % (prefix, name)
31 if path: name = os.path.join(path, name)
32 if relpath: name = os.path.join(relpath, name)
33 return name
36 def WriteGroupMarker(out, node, last_group):
37 # If we are part of a group comment marker...
38 if last_group and last_group != node.cls:
39 pre = CommentLines(['*',' @}', '']) + '\n'
40 else:
41 pre = '\n'
43 if node.cls in ['Typedef', 'Interface', 'Struct', 'Enum']:
44 if last_group != node.cls:
45 pre += CommentLines(['*',' @addtogroup %ss' % node.cls, ' @{', ''])
46 last_group = node.cls
47 else:
48 last_group = None
49 out.Write(pre)
50 return last_group
53 def GenerateHeader(out, filenode, releases):
54 cgen = CGen()
55 pref = ''
56 do_comments = True
58 # Generate definitions.
59 last_group = None
60 top_types = ['Typedef', 'Interface', 'Struct', 'Enum', 'Inline']
61 for node in filenode.GetListOf(*top_types):
62 # Skip if this node is not in this release
63 if not node.InReleases(releases):
64 print "Skiping %s" % node
65 continue
67 # End/Start group marker
68 if do_comments:
69 last_group = WriteGroupMarker(out, node, last_group)
71 if node.IsA('Inline'):
72 item = node.GetProperty('VALUE')
73 # If 'C++' use __cplusplus wrapper
74 if node.GetName() == 'cc':
75 item = '#ifdef __cplusplus\n%s\n#endif // __cplusplus\n\n' % item
76 # If not C++ or C, then skip it
77 elif not node.GetName() == 'c':
78 continue
79 if item: out.Write(item)
80 continue
83 # Otherwise we are defining a file level object, so generate the
84 # correct document notation.
86 item = cgen.Define(node, releases, prefix=pref, comment=True)
87 if not item: continue
88 asize = node.GetProperty('assert_size()')
89 if asize:
90 name = '%s%s' % (pref, node.GetName())
91 if node.IsA('Struct'):
92 form = 'PP_COMPILE_ASSERT_STRUCT_SIZE_IN_BYTES(%s, %s);\n'
93 elif node.IsA('Enum'):
94 if node.GetProperty('notypedef'):
95 form = 'PP_COMPILE_ASSERT_ENUM_SIZE_IN_BYTES(%s, %s);\n'
96 else:
97 form = 'PP_COMPILE_ASSERT_SIZE_IN_BYTES(%s, %s);\n'
98 else:
99 form = 'PP_COMPILE_ASSERT_SIZE_IN_BYTES(%s, %s);\n'
100 item += form % (name, asize[0])
102 if item: out.Write(item)
103 if last_group:
104 out.Write(CommentLines(['*',' @}', '']) + '\n')
107 class HGen(GeneratorByFile):
108 def __init__(self):
109 Generator.__init__(self, 'C Header', 'cgen', 'Generate the C headers.')
111 def GenerateFile(self, filenode, releases, options):
112 savename = GetOutFileName(filenode, GetOption('dstroot'))
113 unique_releases = filenode.GetUniqueReleases(releases)
114 if not unique_releases:
115 if os.path.isfile(savename):
116 print "Removing stale %s for this range." % filenode.GetName()
117 os.remove(os.path.realpath(savename))
118 return False
120 out = IDLOutFile(savename)
121 self.GenerateHead(out, filenode, releases, options)
122 self.GenerateBody(out, filenode, releases, options)
123 self.GenerateTail(out, filenode, releases, options)
124 return out.Close()
126 def GenerateHead(self, out, filenode, releases, options):
127 __pychecker__ = 'unusednames=options'
128 cgen = CGen()
129 gpath = GetOption('guard')
130 def_guard = GetOutFileName(filenode, relpath=gpath)
131 def_guard = def_guard.replace(os.sep,'_').replace('.','_').upper() + '_'
133 cright_node = filenode.GetChildren()[0]
134 assert(cright_node.IsA('Copyright'))
135 fileinfo = filenode.GetChildren()[1]
136 assert(fileinfo.IsA('Comment'))
138 out.Write('%s\n' % cgen.Copyright(cright_node))
140 # Wrap the From ... modified ... comment if it would be >80 characters.
141 from_text = 'From %s' % (
142 filenode.GetProperty('NAME').replace(os.sep,'/'))
143 modified_text = 'modified %s.' % (
144 filenode.GetProperty('DATETIME'))
145 if len(from_text) + len(modified_text) < 74:
146 out.Write('/* %s %s */\n\n' % (from_text, modified_text))
147 else:
148 out.Write('/* %s,\n * %s\n */\n\n' % (from_text, modified_text))
150 out.Write('#ifndef %s\n#define %s\n\n' % (def_guard, def_guard))
151 # Generate set of includes
153 deps = set()
154 for release in releases:
155 deps |= filenode.GetDeps(release)
157 includes = set([])
158 for dep in deps:
159 depfile = dep.GetProperty('FILE')
160 if depfile:
161 includes.add(depfile)
162 includes = [GetOutFileName(
163 include, relpath=gpath).replace(os.sep, '/') for include in includes]
164 includes.append('ppapi/c/pp_macros.h')
166 # Assume we need stdint if we "include" C or C++ code
167 if filenode.GetListOf('Include'):
168 includes.append('ppapi/c/pp_stdint.h')
170 includes = sorted(set(includes))
171 cur_include = GetOutFileName(filenode, relpath=gpath).replace(os.sep, '/')
172 for include in includes:
173 if include == cur_include: continue
174 out.Write('#include "%s"\n' % include)
176 # If we are generating a single release, then create a macro for the highest
177 # available release number.
178 if filenode.GetProperty('NAME').endswith('pp_macros.idl'):
179 releasestr = GetOption('release')
180 if releasestr:
181 release_numbers = re.findall('\d+', releasestr)
182 if release_numbers:
183 out.Write('\n#define PPAPI_RELEASE %s\n' % release_numbers[0])
185 # Generate all interface defines
186 out.Write('\n')
187 for node in filenode.GetListOf('Interface'):
188 idefs = ''
189 macro = cgen.GetInterfaceMacro(node)
190 unique = node.GetUniqueReleases(releases)
192 # Skip this interface if there are no matching versions
193 if not unique: continue
195 for rel in unique:
196 version = node.GetVersion(rel)
197 name = cgen.GetInterfaceString(node, version)
198 strver = str(version).replace('.', '_')
199 idefs += cgen.GetDefine('%s_%s' % (macro, strver), '"%s"' % name)
200 idefs += cgen.GetDefine(macro, '%s_%s' % (macro, strver)) + '\n'
201 out.Write(idefs)
203 # Generate the @file comment
204 out.Write('%s\n' % Comment(fileinfo, prefix='*\n @file'))
206 def GenerateBody(self, out, filenode, releases, options):
207 __pychecker__ = 'unusednames=options'
208 GenerateHeader(out, filenode, releases)
210 def GenerateTail(self, out, filenode, releases, options):
211 __pychecker__ = 'unusednames=options,releases'
212 gpath = GetOption('guard')
213 def_guard = GetOutFileName(filenode, relpath=gpath)
214 def_guard = def_guard.replace(os.sep,'_').replace('.','_').upper() + '_'
215 out.Write('#endif /* %s */\n\n' % def_guard)
218 hgen = HGen()
220 def Main(args):
221 # Default invocation will verify the golden files are unchanged.
222 failed = 0
223 if not args:
224 args = ['--wnone', '--diff', '--test', '--dstroot=.']
226 ParseOptions(args)
228 idldir = os.path.split(sys.argv[0])[0]
229 idldir = os.path.join(idldir, 'test_cgen', '*.idl')
230 filenames = glob.glob(idldir)
231 ast = ParseFiles(filenames)
232 if hgen.GenerateRelease(ast, 'M14', {}):
233 print "Golden file for M14 failed."
234 failed = 1
235 else:
236 print "Golden file for M14 passed."
239 idldir = os.path.split(sys.argv[0])[0]
240 idldir = os.path.join(idldir, 'test_cgen_range', '*.idl')
241 filenames = glob.glob(idldir)
243 ast = ParseFiles(filenames)
244 if hgen.GenerateRange(ast, ['M13', 'M14', 'M15'], {}):
245 print "Golden file for M13-M15 failed."
246 failed =1
247 else:
248 print "Golden file for M13-M15 passed."
250 return failed
252 if __name__ == '__main__':
253 sys.exit(Main(sys.argv[1:]))