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

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

Issue 7715036: More multi-version support (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 9 years, 3 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
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, GetNodeComments, CommentLines, Comment
21 from idl_generator import Generator 21 from idl_generator import Generator, GeneratorByFile
22 22
23 Option('dstroot', 'Base directory of output', default='../c') 23 Option('dstroot', 'Base directory of output', default='../c')
24 Option('guard', 'Include guard prefix', default='ppapi/c') 24 Option('guard', 'Include guard prefix', default='ppapi/c')
25 Option('out', 'List of output files', default='') 25 Option('out', 'List of output files', default='')
26 26
27 cgen = CGen() 27 def GetOutFileName(filenode, relpath=None, prefix=None):
28
29 def IDLToHeader(filenode, relpath=None, prefix=None):
30 path, name = os.path.split(filenode.GetProperty('NAME')) 28 path, name = os.path.split(filenode.GetProperty('NAME'))
31 name = os.path.splitext(name)[0] + '.h' 29 name = os.path.splitext(name)[0] + '.h'
32 if prefix: name = '%s%s' % (prefix, name) 30 if prefix: name = '%s%s' % (prefix, name)
33 if path: name = os.path.join(path, name) 31 if path: name = os.path.join(path, name)
34 if relpath: name = os.path.join(relpath, name) 32 if relpath: name = os.path.join(relpath, name)
35 return name 33 return name
36 34
37 35 def WriteGroupMarker(out, node, last_group):
38 def GenerateHeader(filenode, release, pref, inline=True): 36 # If we are part of a group comment marker...
39 name = filenode.GetProperty('NAME') 37 if last_group and last_group != node.cls:
40 # if name == 'pp_stdint.idl': return 38 pre = CommentLines(['*',' @}', '']) + '\n'
41 39 else:
42 # If we have an 'out' filter list, then check if we should output this file. 40 pre = '\n'
43 outlist = GetOption('out') 41
44 if outlist: 42 if node.cls in ['Typedef', 'Interface', 'Struct', 'Enum']:
45 outlist = outlist.split(',') 43 if last_group != node.cls:
46 if name not in outlist: 44 pre += CommentLines(['*',' @addtogroup %ss' % node.cls, ' @{', ''])
47 return 45 last_group = node.cls
48 46 else:
49 savename = IDLToHeader(filenode, relpath=GetOption('dstroot'), prefix=pref) 47 last_group = None
50 out = IDLOutFile(savename) 48 out.Write(pre)
51 49 return last_group
50
51
52 def GenerateHeader(out, filenode, releases):
52 gpath = GetOption('guard') 53 gpath = GetOption('guard')
53 def_guard = IDLToHeader(filenode, relpath=gpath, prefix=pref) 54 cgen = CGen()
54 def_guard = def_guard.replace('/','_').replace('.','_').upper() + '_' 55 pref = ''
55 cright_node = filenode.GetChildren()[0] 56 do_comments = True
56 assert(cright_node.IsA('Copyright'))
57
58 fileinfo = filenode.GetChildren()[1]
59 assert(fileinfo.IsA('Comment'))
60
61 out.Write('%s\n' % cgen.Copyright(cright_node))
62 out.Write('/* From %s modified %s. */\n\n'% (
63 filenode.GetProperty('NAME'), filenode.GetProperty('DATETIME')))
64 out.Write('#ifndef %s\n#define %s\n\n' % (def_guard, def_guard))
65 57
66 for label in filenode.GetListOf('Label'): 58 for label in filenode.GetListOf('Label'):
67 if label.GetName() == GetOption('label'): 59 if label.GetName() == GetOption('label'):
68 cgen.SetVersionMap(label) 60 cgen.SetVersionMap(label)
69 61
70 deps = filenode.GetDeps(release)
71 # Generate set of includes
72 includes = set([])
73 for dep in deps:
74 depfile = dep.GetProperty('FILE')
75 if depfile:
76 includes.add(depfile)
77 includes = [IDLToHeader(include, relpath=gpath) for include in includes]
78 includes.append('ppapi/c/pp_macros.h')
79
80 # Assume we need stdint if we "include" C or C++ code
81 if filenode.GetListOf('Include'):
82 includes.append('ppapi/c/pp_stdint.h')
83
84 includes = sorted(set(includes))
85 cur_include = IDLToHeader(filenode, relpath=gpath)
86 for include in includes:
87 if include == cur_include: continue
88 out.Write('#include "%s"\n' % include)
89
90 # Generate all interface defines
91 out.Write('\n')
92 for node in filenode.GetListOf('Interface'):
93 out.Write( cgen.InterfaceDefs(node) )
94
95 # Generate the @file comment
96 out.Write('%s\n' % cgen.Comment(fileinfo, prefix='*\n @file'))
97
98 # Generate definitions. 62 # Generate definitions.
99 last_group = None 63 last_group = None
100 for node in filenode.GetChildren()[2:]: 64 top_types = ['Typedef', 'Interface', 'Struct', 'Enum', 'Inline']
101 # If we are part of a group comment marker... 65 for node in filenode.GetListOf(*top_types):
102 if last_group and last_group != node.cls: 66 # Skip if this node is not in this release
103 pre = cgen.CommentLines(['*',' @}', '']) + '\n' 67 if not node.InReleases(releases):
104 else: 68 print "Skiping %s" % node
105 pre = '\n' 69 continue
106 70
107 if node.cls in ['Typedef', 'Interface', 'Struct', 'Enum']: 71 # End/Start group marker
108 if last_group != node.cls: 72 if do_comments:
109 pre += cgen.CommentLines(['*',' @addtogroup %ss' % node.cls, ' @{', '']) 73 last_group = WriteGroupMarker(out, node, last_group)
110 last_group = node.cls 74
111 else: 75 if node.IsA('Inline'):
112 last_group = None 76 item = node.GetProperty('VALUE')
113 77 # If 'C++' use __cplusplus wrapper
114 if node.IsA('Comment'):
115 item = '%s\n\n' % cgen.Comment(node)
116 elif node.IsA('Inline'):
117 if not inline: continue
118 if node.GetName() == 'cc': 78 if node.GetName() == 'cc':
119 item = cgen.Define(node, prefix=pref, comment=True)
120 item = '#ifdef __cplusplus\n%s\n#endif // __cplusplus\n\n' % item 79 item = '#ifdef __cplusplus\n%s\n#endif // __cplusplus\n\n' % item
121 elif node.GetName() == 'c': 80 # If not C++ or C, then skip it
122 item = cgen.Define(node, prefix=pref, comment=True) 81 elif not node.GetName() == 'c':
82 continue
83 if item: out.Write(item)
84 continue
85
86 #
87 # Otherwise we are defining a file level object, so generate the
88 # correct document notation.
89 #
90 item = cgen.Define(node, releases, prefix=pref, comment=True)
91 if not item: continue
92 asize = node.GetProperty('assert_size()')
93 if asize:
94 name = '%s%s' % (pref, node.GetName())
95 if node.IsA('Struct'):
96 form = 'PP_COMPILE_ASSERT_STRUCT_SIZE_IN_BYTES(%s, %s);\n'
123 else: 97 else:
124 continue 98 form = 'PP_COMPILE_ASSERT_SIZE_IN_BYTES(%s, %s);\n'
125 if not item: continue 99 item += form % (name, asize[0])
126 else: 100
127 # 101 if item: out.Write(item)
128 # Otherwise we are defining a file level object, so generate the
129 # correct document notation.
130 #
131 item = cgen.Define(node, prefix=pref, comment=True)
132 if not item: continue
133 asize = node.GetProperty('assert_size()')
134 if asize:
135 name = '%s%s' % (pref, node.GetName())
136 if node.IsA('Struct'):
137 form = 'PP_COMPILE_ASSERT_STRUCT_SIZE_IN_BYTES(%s, %s);\n'
138 else:
139 form = 'PP_COMPILE_ASSERT_SIZE_IN_BYTES(%s, %s);\n'
140 item += form % (name, asize[0])
141
142 if item: out.Write('%s%s' % (pre, item))
143 if last_group: 102 if last_group:
144 out.Write(cgen.CommentLines(['*',' @}', '']) + '\n') 103 out.Write(CommentLines(['*',' @}', '']) + '\n')
145 104
146 out.Write('#endif /* %s */\n\n' % def_guard) 105
147 return out.Close() 106 class HGen(GeneratorByFile):
148
149 class HGen(Generator):
150 def __init__(self): 107 def __init__(self):
151 Generator.__init__(self, 'C Header', 'cgen', 'Generate the C headers.') 108 Generator.__init__(self, 'C Header', 'cgen', 'Generate the C headers.')
152 109
153 def GenerateVersion(self, ast, release, options): 110 def GetMacro(self, node):
154 outdir = GetOption('dstroot') 111 name = node.GetName()
155 skipList= [] 112 name = name.upper()
156 prefix = '' 113 return "%s_INTERFACE" % name
157 cfile = None 114
158 cnt = 0 115 def GetDefine(self, name, value):
159 116 out = '#define %s %s' % (name, value)
160 for filenode in ast.GetListOf('File'): 117 if len(out) > 80:
161 if GetOption('verbose'): 118 out = '#define %s \\\n %s' % (name, value)
162 print "Working on %s" % filenode 119 return '%s\n' % out
163 120
164 # If this file has errors, skip it 121
165 if filenode.GetProperty('ERRORS') > 0: 122 def GetOutFile(self, filenode, options):
166 skipList.append(filenode) 123 savename = GetOutFileName(filenode, GetOption('dstroot'))
167 continue 124 return IDLOutFile(savename)
168 125
169 if GenerateHeader(filenode, release, prefix): 126 def GenerateHead(self, out, filenode, releases, options):
170 cnt = cnt + 1 127 cgen = CGen()
171 128 gpath = GetOption('guard')
172 for filenode in skipList: 129 release = releases[0]
173 errcnt = filenode.GetProperty('ERRORS') 130 def_guard = GetOutFileName(filenode, relpath=gpath)
174 ErrOut.Log('%s : Skipped because of %d errors.' % ( 131 def_guard = def_guard.replace('/','_').replace('.','_').upper() + '_'
175 filenode.GetName(), errcnt)) 132
176 133 cright_node = filenode.GetChildren()[0]
177 if skipList: 134 assert(cright_node.IsA('Copyright'))
178 return -len(skipList) 135 fileinfo = filenode.GetChildren()[1]
179 136 assert(fileinfo.IsA('Comment'))
180 if GetOption('diff'): 137
181 return -cnt 138 out.Write('%s\n' % cgen.Copyright(cright_node))
182 return cnt 139 out.Write('/* From %s modified %s. */\n\n'% (
140 filenode.GetProperty('NAME'), filenode.GetProperty('DATETIME')))
141 out.Write('#ifndef %s\n#define %s\n\n' % (def_guard, def_guard))
142 # Generate set of includes
143
144 deps = set()
145 for release in releases:
146 deps |= filenode.GetDeps(release)
147
148 includes = set([])
149 for dep in deps:
150 depfile = dep.GetProperty('FILE')
151 if depfile:
152 includes.add(depfile)
153 includes = [GetOutFileName(include, relpath=gpath) for include in includes]
154 includes.append('ppapi/c/pp_macros.h')
155
156 # Assume we need stdint if we "include" C or C++ code
157 if filenode.GetListOf('Include'):
158 includes.append('ppapi/c/pp_stdint.h')
159
160 includes = sorted(set(includes))
161 cur_include = GetOutFileName(filenode, relpath=gpath)
162 for include in includes:
163 if include == cur_include: continue
164 out.Write('#include "%s"\n' % include)
165
166 # Generate all interface defines
167 out.Write('\n')
168 for node in filenode.GetListOf('Interface'):
169 idefs = ''
170 name = node.GetName()
171 macro = node.GetProperty('macro')
172 if not macro:
173 macro = self.GetMacro(node)
174 label = node.GetLabel()
175 if label:
176 for vers in label.versions:
177 strver = str(vers).replace('.', '_')
178 idefs += self.GetDefine('%s_%s' % (macro, strver),
179 '"%s;%s"' % (name, vers))
180 if label.GetRelease(vers) == releases[-1]:
181 idefs += self.GetDefine(macro, '%s_%s' % (macro, strver))
182 idefs += '\n'
183 out.Write(idefs)
184
185 # Generate the @file comment
186 out.Write('%s\n' % Comment(fileinfo, prefix='*\n @file'))
187
188 def GenerateBody(self, out, filenode, releases, options):
189 GenerateHeader(out, filenode, releases)
190
191 def GenerateTail(self, out, filenode, releases, options):
192 gpath = GetOption('guard')
193 def_guard = GetOutFileName(filenode, relpath=gpath)
194 def_guard = def_guard.replace('/','_').replace('.','_').upper() + '_'
195 out.Write('#endif /* %s */\n\n' % def_guard)
183 196
184 197
185 hgen = HGen() 198 hgen = HGen()
186 199
187 def Main(args): 200 def Main(args):
188 # Default invocation will verify the golden files are unchanged. 201 # Default invocation will verify the golden files are unchanged.
202 failed = 0
189 if not args: 203 if not args:
190 args = ['--wnone', '--diff', '--test', '--dstroot=.'] 204 args = ['--wnone', '--diff', '--test', '--dstroot=.']
191 205
192 ParseOptions(args) 206 ParseOptions(args)
207
193 idldir = os.path.split(sys.argv[0])[0] 208 idldir = os.path.split(sys.argv[0])[0]
194 idldir = os.path.join(idldir, 'test_cgen', '*.idl') 209 idldir = os.path.join(idldir, 'test_cgen', '*.idl')
195 filenames = glob.glob(idldir) 210 filenames = glob.glob(idldir)
196
197 ast = ParseFiles(filenames) 211 ast = ParseFiles(filenames)
198 return hgen.GenerateVersion(ast, 'M14', {}) 212 if hgen.GenerateRelease(ast, 'M14', {}):
213 print "Golden file for M14 failed."
214 failed = 1
215 else:
216 print "Golden file for M14 passed."
217
218
219 idldir = os.path.split(sys.argv[0])[0]
220 idldir = os.path.join(idldir, 'test_cgen_range', '*.idl')
221 filenames = glob.glob(idldir)
222
223 ast = ParseFiles(filenames)
224 if hgen.GenerateRange(ast, ['M13', 'M14', 'M15'], {}):
225 print "Golden file for M13-M15 failed."
226 failed =1
227 else:
228 print "Golden file for M13-M15 passed."
229
230 return failed
199 231
200 if __name__ == '__main__': 232 if __name__ == '__main__':
201 retval = Main(sys.argv[1:]) 233 retval = Main(sys.argv[1:])
202 sys.exit(retval) 234 sys.exit(retval)
203 235
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698