OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 # pylint: disable=W0104,W0106,F0401,R0201 | 6 # pylint: disable=W0104,W0106,F0401,R0201 |
7 | 7 |
8 import errno | 8 import errno |
9 import optparse | |
10 import os.path | 9 import os.path |
11 import sys | 10 import sys |
12 | 11 |
13 import interface | 12 import interface |
14 | 13 |
15 | 14 |
16 def _ScriptDir(): | 15 def ScriptDir(): |
17 return os.path.dirname(os.path.abspath(__file__)) | 16 return os.path.dirname(os.path.abspath(__file__)) |
18 | 17 |
19 | 18 |
20 def _GetDirAbove(dirname): | 19 def RepoRoot(): |
21 """Returns the directory "above" this file containing |dirname| (which must | 20 return os.path.dirname(ScriptDir()) |
22 also be "above" this file).""" | |
23 path = _ScriptDir() | |
24 while True: | |
25 path, tail = os.path.split(path) | |
26 assert tail | |
27 if tail == dirname: | |
28 return path | |
29 | 21 |
30 | 22 |
31 def _AddThirdPartyImportPath(): | 23 def _AddThirdPartyImportPath(): |
32 sys.path.append(os.path.join(_GetDirAbove('mojo'), 'third_party')) | 24 sys.path.append(os.path.join(RepoRoot(), 'third_party')) |
33 | 25 |
34 | 26 |
35 _AddThirdPartyImportPath() | 27 _AddThirdPartyImportPath() |
36 import jinja2 | 28 import jinja2 |
37 | 29 |
38 loader = jinja2.FileSystemLoader(_ScriptDir()) | 30 loader = jinja2.FileSystemLoader(ScriptDir()) |
39 jinja_env = jinja2.Environment(loader=loader, keep_trailing_newline=True) | 31 jinja_env = jinja2.Environment(loader=loader, keep_trailing_newline=True) |
40 | 32 |
41 | 33 |
42 # Accumulate lines of code with varying levels of indentation. | 34 # Accumulate lines of code with varying levels of indentation. |
43 class CodeWriter(object): | 35 class CodeWriter(object): |
44 def __init__(self): | 36 def __init__(self): |
45 self._lines = [] | 37 self._lines = [] |
46 self._margin = '' | 38 self._margin = '' |
47 self._margin_stack = [] | 39 self._margin_stack = [] |
48 | 40 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 return lines | 88 return lines |
97 | 89 |
98 | 90 |
99 def GeneratorWarning(): | 91 def GeneratorWarning(): |
100 return ('// WARNING this file was generated by %s\n// Do not edit by hand.' % | 92 return ('// WARNING this file was generated by %s\n// Do not edit by hand.' % |
101 os.path.basename(__file__)) | 93 os.path.basename(__file__)) |
102 | 94 |
103 | 95 |
104 # Untrusted library which thunks from the public Mojo API to the IRT interface | 96 # Untrusted library which thunks from the public Mojo API to the IRT interface |
105 # implementing the public Mojo API. | 97 # implementing the public Mojo API. |
106 def GenerateLibMojo(functions, out): | 98 def GenerateLibMojo(functions, common_vars, out): |
107 template = jinja_env.get_template('libmojo.cc.tmpl') | 99 template = jinja_env.get_template('libmojo.cc.tmpl') |
108 | 100 |
109 code = CodeWriter() | 101 code = CodeWriter() |
110 | 102 |
111 for f in functions: | 103 for f in functions: |
112 for line in Wrap('%s %s(' % (f.return_type, f.name), f.ParamList(), ') {'): | 104 for line in Wrap('%s %s(' % (f.return_type, f.name), f.ParamList(), ') {'): |
113 code << line | 105 code << line |
114 | 106 |
115 with code.Indent(): | 107 with code.Indent(): |
116 code << 'struct nacl_irt_mojo* irt_mojo = get_irt_mojo();' | 108 code << 'struct nacl_irt_mojo* irt_mojo = get_irt_mojo();' |
117 code << 'if (irt_mojo == NULL)' | 109 code << 'if (irt_mojo == NULL)' |
118 with code.Indent(): | 110 with code.Indent(): |
119 code << 'return MOJO_RESULT_INTERNAL;' | 111 code << 'return MOJO_RESULT_INTERNAL;' |
120 code << 'return irt_mojo->%s(%s);' % ( | 112 code << 'return irt_mojo->%s(%s);' % ( |
121 f.name, ', '.join([p.name for p in f.params])) | 113 f.name, ', '.join([p.name for p in f.params])) |
122 | 114 |
123 code << '}' | 115 code << '}' |
124 code << '' | 116 code << '' |
125 | 117 |
126 body = code.GetValue() | 118 body = code.GetValue() |
127 text = template.render( | 119 text = template.render( |
128 generator_warning=GeneratorWarning(), | 120 body=body, |
129 body=body) | 121 **common_vars) |
130 out.write(text) | 122 out.write(text) |
131 | 123 |
132 | 124 |
133 # Parameters passed into trusted code are handled differently depending on | 125 # Parameters passed into trusted code are handled differently depending on |
134 # details of the parameter. ParamImpl instances encapsulate these differences | 126 # details of the parameter. ParamImpl instances encapsulate these differences |
135 # and are used to generate the code that transfers parameters across the | 127 # and are used to generate the code that transfers parameters across the |
136 # untrusted/trusted boundary. | 128 # untrusted/trusted boundary. |
137 class ParamImpl(object): | 129 class ParamImpl(object): |
138 def __init__(self, param): | 130 def __init__(self, param): |
139 self.param = param | 131 self.param = param |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
301 return ScalarOutputImpl(p) | 293 return ScalarOutputImpl(p) |
302 assert False, p.name | 294 assert False, p.name |
303 | 295 |
304 | 296 |
305 def CBool(value): | 297 def CBool(value): |
306 return 'true' if value else 'false' | 298 return 'true' if value else 'false' |
307 | 299 |
308 | 300 |
309 # A trusted wrapper that validates the arguments passed from untrusted code | 301 # A trusted wrapper that validates the arguments passed from untrusted code |
310 # before passing them to the underlying public Mojo API. | 302 # before passing them to the underlying public Mojo API. |
311 def GenerateMojoSyscall(functions, out): | 303 def GenerateMojoSyscall(functions, common_vars, out): |
312 template = jinja_env.get_template('mojo_syscall.cc.tmpl') | 304 template = jinja_env.get_template('mojo_syscall.cc.tmpl') |
313 | 305 |
314 code = CodeWriter() | 306 code = CodeWriter() |
315 code.PushMargin() | 307 code.PushMargin() |
316 | 308 |
317 for f in functions: | 309 for f in functions: |
318 impls = [ImplForParam(p) for p in f.params] | 310 impls = [ImplForParam(p) for p in f.params] |
319 impls.append(ImplForParam(f.result_param)) | 311 impls.append(ImplForParam(f.result_param)) |
320 | 312 |
321 code << 'case %d:' % f.uid | 313 code << 'case %d:' % f.uid |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 code << '}' | 362 code << '}' |
371 code << '' | 363 code << '' |
372 | 364 |
373 code << 'return 0;' | 365 code << 'return 0;' |
374 code << '}' | 366 code << '}' |
375 | 367 |
376 code.PopMargin() | 368 code.PopMargin() |
377 | 369 |
378 body = code.GetValue() | 370 body = code.GetValue() |
379 text = template.render( | 371 text = template.render( |
380 generator_warning=GeneratorWarning(), | 372 body=body, |
381 body=body) | 373 **common_vars) |
382 out.write(text) | 374 out.write(text) |
383 | 375 |
384 | 376 |
385 # A header declaring the IRT interface for accessing Mojo functions. | 377 # A header declaring the IRT interface for accessing Mojo functions. |
386 def GenerateMojoIrtHeader(functions, out): | 378 def GenerateMojoIrtHeader(functions, common_vars, out): |
387 template = jinja_env.get_template('mojo_irt.h.tmpl') | 379 template = jinja_env.get_template('mojo_irt.h.tmpl') |
388 code = CodeWriter() | 380 code = CodeWriter() |
389 | 381 |
390 code << 'struct nacl_irt_mojo {' | 382 code << 'struct nacl_irt_mojo {' |
391 with code.Indent(): | 383 with code.Indent(): |
392 for f in functions: | 384 for f in functions: |
393 for line in Wrap('%s (*%s)(' % (f.return_type, f.name), | 385 for line in Wrap('%s (*%s)(' % (f.return_type, f.name), |
394 f.ParamList(), | 386 f.ParamList(), |
395 ');'): | 387 ');'): |
396 code << line | 388 code << line |
397 | 389 |
398 code << '};' | 390 code << '};' |
399 | 391 |
400 body = code.GetValue() | 392 body = code.GetValue() |
401 | 393 |
402 text = template.render( | 394 text = template.render( |
403 generator_warning=GeneratorWarning(), | 395 body=body, |
404 body=body) | 396 **common_vars) |
405 out.write(text) | 397 out.write(text) |
406 | 398 |
407 # IRT interface which implements the Mojo public API. | 399 # IRT interface which implements the Mojo public API. |
408 def GenerateMojoIrtImplementation(functions, out): | 400 def GenerateMojoIrtImplementation(functions, common_vars, out): |
409 template = jinja_env.get_template('mojo_irt.c.tmpl') | 401 template = jinja_env.get_template('mojo_irt.c.tmpl') |
410 code = CodeWriter() | 402 code = CodeWriter() |
411 | 403 |
412 for f in functions: | 404 for f in functions: |
413 for line in Wrap('static %s irt_%s(' % (f.return_type, f.name), | 405 for line in Wrap('static %s irt_%s(' % (f.return_type, f.name), |
414 f.ParamList(), | 406 f.ParamList(), |
415 ') {'): | 407 ') {'): |
416 code << line | 408 code << line |
417 | 409 |
418 # 2 extra parameters: message ID and return value. | 410 # 2 extra parameters: message ID and return value. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
452 # definition. | 444 # definition. |
453 code << 'struct nacl_irt_mojo kIrtMojo = {' | 445 code << 'struct nacl_irt_mojo kIrtMojo = {' |
454 for f in functions: | 446 for f in functions: |
455 with code.Indent(): | 447 with code.Indent(): |
456 code << '&irt_%s,' % f.name | 448 code << '&irt_%s,' % f.name |
457 code << '};' | 449 code << '};' |
458 | 450 |
459 body = code.GetValue() | 451 body = code.GetValue() |
460 | 452 |
461 text = template.render( | 453 text = template.render( |
462 generator_warning=GeneratorWarning(), | 454 body=body, |
463 body=body) | 455 **common_vars) |
464 out.write(text) | 456 out.write(text) |
465 | 457 |
466 | 458 |
467 def OutFile(dir_path, name): | 459 def OutFile(dir_path, name): |
468 if not os.path.exists(dir_path): | 460 if not os.path.exists(dir_path): |
469 try: | 461 try: |
470 os.makedirs(dir_path) | 462 os.makedirs(dir_path) |
471 except OSError as e: | 463 except OSError as e: |
472 # There may have been a race to create this directory. | 464 # There may have been a race to create this directory. |
473 if e.errno != errno.EEXIST: | 465 if e.errno != errno.EEXIST: |
474 raise | 466 raise |
475 return open(os.path.join(dir_path, name), 'w') | 467 full_path = os.path.join(dir_path, name) |
| 468 print full_path |
| 469 return open(full_path, 'w') |
476 | 470 |
477 | 471 |
478 def main(args): | 472 def main(): |
479 usage = 'usage: %prog [options]' | 473 root_dir = RepoRoot() |
480 parser = optparse.OptionParser(usage=usage) | 474 |
481 parser.add_option( | 475 platform_dir = 'mojo/public/platform/nacl' |
482 '-d', | 476 bindings_dir = 'nacl_bindings' |
483 dest='out_dir', | 477 |
484 metavar='DIR', | 478 full_platform_dir = os.path.join(root_dir, platform_dir) |
485 help='output generated code into directory DIR') | 479 full_bindings_dir = os.path.join(root_dir, bindings_dir) |
486 options, args = parser.parse_args(args=args) | 480 |
487 if not options.out_dir: | 481 common_vars = dict( |
488 parser.error('-d is required') | 482 generator_warning=GeneratorWarning(), |
489 if args: | 483 platform_dir=platform_dir, |
490 parser.error('unexpected positional arguments: %s' % ' '.join(args)) | 484 platform_dir_header_path=platform_dir.replace("/", "_").upper(), |
| 485 bindings_dir=bindings_dir, |
| 486 ) |
491 | 487 |
492 mojo = interface.MakeInterface() | 488 mojo = interface.MakeInterface() |
493 | 489 |
494 out = OutFile(options.out_dir, 'libmojo.cc') | 490 out = OutFile(full_platform_dir, 'libmojo.cc') |
495 GenerateLibMojo(mojo.functions, out) | 491 GenerateLibMojo(mojo.functions, common_vars, out) |
496 | 492 |
497 out = OutFile(options.out_dir, 'mojo_syscall.cc') | 493 out = OutFile(full_bindings_dir, 'mojo_syscall.cc') |
498 GenerateMojoSyscall(mojo.functions, out) | 494 GenerateMojoSyscall(mojo.functions, common_vars, out) |
499 | 495 |
500 out = OutFile(options.out_dir, 'mojo_irt.h') | 496 out = OutFile(full_platform_dir, 'mojo_irt.h') |
501 GenerateMojoIrtHeader(mojo.functions, out) | 497 GenerateMojoIrtHeader(mojo.functions, common_vars, out) |
502 | 498 |
503 out = OutFile(options.out_dir, 'mojo_irt.c') | 499 out = OutFile(full_bindings_dir, 'mojo_irt.c') |
504 GenerateMojoIrtImplementation(mojo.functions, out) | 500 GenerateMojoIrtImplementation(mojo.functions, common_vars, out) |
505 | 501 |
506 if __name__ == '__main__': | 502 if __name__ == '__main__': |
507 main(sys.argv[1:]) | 503 main() |
OLD | NEW |