| 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 |